soba-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.claude/commands/osoba/add-backlog.md +173 -0
  3. data/.claude/commands/osoba/implement.md +151 -0
  4. data/.claude/commands/osoba/plan.md +217 -0
  5. data/.claude/commands/osoba/review.md +133 -0
  6. data/.claude/commands/osoba/revise.md +176 -0
  7. data/.claude/commands/soba/implement.md +88 -0
  8. data/.claude/commands/soba/plan.md +93 -0
  9. data/.claude/commands/soba/review.md +91 -0
  10. data/.claude/commands/soba/revise.md +76 -0
  11. data/.devcontainer/.env +2 -0
  12. data/.devcontainer/Dockerfile +3 -0
  13. data/.devcontainer/LICENSE +21 -0
  14. data/.devcontainer/README.md +85 -0
  15. data/.devcontainer/bin/devcontainer-common.sh +50 -0
  16. data/.devcontainer/bin/down +35 -0
  17. data/.devcontainer/bin/rebuild +10 -0
  18. data/.devcontainer/bin/up +11 -0
  19. data/.devcontainer/compose.yaml +28 -0
  20. data/.devcontainer/devcontainer.json +53 -0
  21. data/.devcontainer/post-attach.sh +29 -0
  22. data/.devcontainer/post-create.sh +62 -0
  23. data/.devcontainer/setup/01-os-package.sh +19 -0
  24. data/.devcontainer/setup/02-npm-package.sh +22 -0
  25. data/.devcontainer/setup/03-mcp-server.sh +33 -0
  26. data/.devcontainer/setup/04-tool.sh +17 -0
  27. data/.devcontainer/setup/05-soba-setup.sh +66 -0
  28. data/.devcontainer/setup/scripts/functions/install_apt.sh +77 -0
  29. data/.devcontainer/setup/scripts/functions/install_npm.sh +71 -0
  30. data/.devcontainer/setup/scripts/functions/mcp_config.sh +14 -0
  31. data/.devcontainer/setup/scripts/functions/print_message.sh +59 -0
  32. data/.devcontainer/setup/scripts/setup/mcp-markdownify.sh +39 -0
  33. data/.devcontainer/sync-envs.sh +58 -0
  34. data/.envrc.sample +7 -0
  35. data/.rspec +4 -0
  36. data/.rubocop.yml +70 -0
  37. data/.rubocop_airbnb.yml +2 -0
  38. data/.rubocop_todo.yml +74 -0
  39. data/.tool-versions +1 -0
  40. data/CLAUDE.md +20 -0
  41. data/LICENSE +21 -0
  42. data/README.md +384 -0
  43. data/README_ja.md +384 -0
  44. data/Rakefile +18 -0
  45. data/bin/soba +120 -0
  46. data/config/config.yml.example +36 -0
  47. data/docs/business/INDEX.md +6 -0
  48. data/docs/business/overview.md +42 -0
  49. data/docs/business/workflow.md +143 -0
  50. data/docs/development/INDEX.md +10 -0
  51. data/docs/development/architecture.md +69 -0
  52. data/docs/development/coding-standards.md +152 -0
  53. data/docs/development/distribution.md +26 -0
  54. data/docs/development/implementation-guide.md +103 -0
  55. data/docs/development/testing-strategy.md +128 -0
  56. data/docs/development/tmux-management.md +253 -0
  57. data/docs/document_system.md +58 -0
  58. data/lib/soba/commands/config/show.rb +63 -0
  59. data/lib/soba/commands/init.rb +778 -0
  60. data/lib/soba/commands/open.rb +144 -0
  61. data/lib/soba/commands/start.rb +442 -0
  62. data/lib/soba/commands/status.rb +175 -0
  63. data/lib/soba/commands/stop.rb +147 -0
  64. data/lib/soba/config_loader.rb +32 -0
  65. data/lib/soba/configuration.rb +268 -0
  66. data/lib/soba/container.rb +48 -0
  67. data/lib/soba/domain/issue.rb +38 -0
  68. data/lib/soba/domain/phase_strategy.rb +74 -0
  69. data/lib/soba/infrastructure/errors.rb +23 -0
  70. data/lib/soba/infrastructure/github_client.rb +399 -0
  71. data/lib/soba/infrastructure/lock_manager.rb +129 -0
  72. data/lib/soba/infrastructure/tmux_client.rb +331 -0
  73. data/lib/soba/services/ansi_processor.rb +92 -0
  74. data/lib/soba/services/auto_merge_service.rb +133 -0
  75. data/lib/soba/services/closed_issue_window_cleaner.rb +96 -0
  76. data/lib/soba/services/daemon_service.rb +83 -0
  77. data/lib/soba/services/git_workspace_manager.rb +102 -0
  78. data/lib/soba/services/issue_monitor.rb +29 -0
  79. data/lib/soba/services/issue_processor.rb +215 -0
  80. data/lib/soba/services/issue_watcher.rb +193 -0
  81. data/lib/soba/services/pid_manager.rb +87 -0
  82. data/lib/soba/services/process_info.rb +58 -0
  83. data/lib/soba/services/queueing_service.rb +98 -0
  84. data/lib/soba/services/session_logger.rb +111 -0
  85. data/lib/soba/services/session_resolver.rb +72 -0
  86. data/lib/soba/services/slack_notifier.rb +121 -0
  87. data/lib/soba/services/status_manager.rb +74 -0
  88. data/lib/soba/services/test_process_manager.rb +84 -0
  89. data/lib/soba/services/tmux_session_manager.rb +251 -0
  90. data/lib/soba/services/workflow_blocking_checker.rb +73 -0
  91. data/lib/soba/services/workflow_executor.rb +256 -0
  92. data/lib/soba/services/workflow_integrity_checker.rb +151 -0
  93. data/lib/soba/templates/claude_commands/implement.md +88 -0
  94. data/lib/soba/templates/claude_commands/plan.md +93 -0
  95. data/lib/soba/templates/claude_commands/review.md +91 -0
  96. data/lib/soba/templates/claude_commands/revise.md +76 -0
  97. data/lib/soba/version.rb +5 -0
  98. data/lib/soba.rb +44 -0
  99. data/lib/tasks/gem.rake +75 -0
  100. data/soba-cli.gemspec +59 -0
  101. metadata +430 -0
@@ -0,0 +1,253 @@
1
+ # tmux管理機能
2
+
3
+ ## 概要
4
+
5
+ sobaのtmux管理機能は、Claude Codeの実行環境をtmuxセッション内で分離・管理することで、長時間実行される処理の監視や並行実行を可能にします。
6
+
7
+ ## アーキテクチャ
8
+
9
+ ### コンポーネント構成
10
+
11
+ ```
12
+ ┌────────────────────────────┐
13
+ │ WorkflowExecutor │ → ワークフロー実行制御
14
+ └────────┬───────────────────┘
15
+
16
+
17
+ ┌────────────────────────────┐
18
+ │ TmuxSessionManager │ → セッション管理ロジック
19
+ └────────┬───────────────────┘
20
+
21
+
22
+ ┌────────────────────────────┐
23
+ │ TmuxClient │ → tmuxコマンドラッパー
24
+ └────────────────────────────┘
25
+ ```
26
+
27
+ ### 責務分担
28
+
29
+ | コンポーネント | 責務 |
30
+ |--------------|------|
31
+ | **TmuxSessionManager** | セッションライフサイクル管理、命名規則の実装、古いセッションのクリーンアップ |
32
+ | **TmuxClient** | tmuxコマンドの実行、エラーハンドリング、出力のパース |
33
+
34
+ ## 主要機能
35
+
36
+ ### セッション管理
37
+
38
+ #### 命名規則
39
+ セッション名は以下の形式で統一されています:
40
+ ```
41
+ soba-{repository}
42
+ ```
43
+ - `repository`: GitHubリポジトリ名(スラッシュやドットはハイフンに変換)
44
+
45
+ #### ライフサイクル
46
+ 1. **作成**: `find_or_create_repository_session` - リポジトリ用セッションを作成または取得
47
+ 2. **ウィンドウ作成**: `create_issue_window` - Issue用ウィンドウを作成
48
+ 3. **ペイン作成**: `create_phase_pane` - フェーズ用ペインを作成
49
+ 4. **クリーンアップ**: 自動または手動でセッション・ウィンドウ・ペインを削除
50
+
51
+ ### ペイン操作
52
+
53
+ #### 基本操作
54
+ - `send_keys`: コマンドをペインに送信
55
+ - `capture_pane`: ペイン出力をキャプチャ
56
+ - `capture_pane_continuous`: 出力を継続的に監視(ストリーミング)
57
+
58
+ #### 高度な操作
59
+ - `split_pane`: ペインの分割(水平/垂直)
60
+ - `resize_pane`: ペインサイズ調整
61
+ - `select_pane`: アクティブペインの切り替え
62
+ - `list_panes`: ペイン一覧と作成時刻の取得
63
+ - `kill_pane`: 指定ペインの削除
64
+ - `select_layout`: レイアウトの自動調整
65
+
66
+ ### ペイン管理の自動化
67
+
68
+ #### ペイン数制限機能
69
+ フェーズ実行時に自動的にペイン数を管理:
70
+ - **最大ペイン数**: デフォルトで3つに制限
71
+ - **自動削除**: 4つ目のペイン作成時に最古のペインを自動削除
72
+ - **作成時刻追跡**: `#{pane_start_time}`フォーマットを使用
73
+
74
+ #### レイアウト自動調整
75
+ ペイン作成・削除後に自動的にレイアウトを調整:
76
+ - **水平分割**: フェーズ実行時のデフォルト(`vertical: false`)
77
+ - **自動調整**: `even-horizontal`レイアウトを適用
78
+ - **均等配置**: すべてのペインが同じ幅になるよう調整
79
+
80
+ ### 自動クリーンアップ
81
+
82
+ クローズされたIssueのウィンドウは自動的に削除されます:
83
+ - `soba start`コマンド実行時に自動チェック
84
+ - GitHub APIでIssueステータスを確認
85
+ - クローズされたIssueのウィンドウを自動削除
86
+
87
+ ## 使用例
88
+
89
+ ### リポジトリセッションの作成
90
+
91
+ ```ruby
92
+ # TmuxSessionManagerのインスタンス作成
93
+ manager = Soba::Services::TmuxSessionManager.new(
94
+ tmux_client: Soba::Infrastructure::TmuxClient.new
95
+ )
96
+
97
+ # リポジトリセッションの作成または取得
98
+ result = manager.find_or_create_repository_session
99
+
100
+ if result[:success]
101
+ session_name = result[:session_name]
102
+ # => "soba-owner-repo"
103
+ end
104
+ ```
105
+
106
+ ### Issueウィンドウの作成
107
+
108
+ ```ruby
109
+ # Issueごとのウィンドウを作成
110
+ window_result = manager.create_issue_window(
111
+ session_name: "soba-owner-repo",
112
+ issue_number: 42
113
+ )
114
+ # => {
115
+ # success: true,
116
+ # window_name: "issue-42",
117
+ # created: true
118
+ # }
119
+ ```
120
+
121
+ ### 並行実行の管理
122
+
123
+ ```ruby
124
+ # リポジトリセッション内で複数Issueを並行処理
125
+ session_result = manager.find_or_create_repository_session
126
+
127
+ [24, 25, 26].each do |issue_number|
128
+ window_result = manager.create_issue_window(
129
+ session_name: session_result[:session_name],
130
+ issue_number: issue_number
131
+ )
132
+
133
+ pane_result = manager.create_phase_pane(
134
+ session_name: session_result[:session_name],
135
+ window_name: window_result[:window_name],
136
+ phase: 'implementation'
137
+ )
138
+ end
139
+ ```
140
+
141
+ ### フェーズごとのペイン管理
142
+
143
+ ```ruby
144
+ # リポジトリセッションとIssueウィンドウの作成
145
+ session_result = manager.find_or_create_repository_session
146
+ window_result = manager.create_issue_window(
147
+ session_name: session_result[:session_name],
148
+ issue_number: 42
149
+ )
150
+
151
+ # フェーズごとにペインを作成(水平分割、最大3ペイン)
152
+ phases = ['planning', 'implementation', 'review', 'testing']
153
+ phases.each do |phase|
154
+ pane_result = manager.create_phase_pane(
155
+ session_name: session_result[:session_name],
156
+ window_name: window_result[:window_name],
157
+ phase: phase,
158
+ vertical: false, # 水平分割
159
+ max_panes: 3 # 最大3ペイン(4つ目から古いペインを削除)
160
+ )
161
+
162
+ if pane_result[:success]
163
+ puts "Phase #{phase} started in pane #{pane_result[:pane_id]}"
164
+ end
165
+ end
166
+ ```
167
+
168
+ ### クリーンアップ実行
169
+
170
+ ```ruby
171
+ # クローズされたIssueのウィンドウを削除
172
+ manager = Soba::Services::TmuxSessionManager.new
173
+ sessions = manager.list_soba_sessions
174
+
175
+ sessions.each do |session_name|
176
+ windows = @tmux_client.list_windows(session_name)
177
+ windows.select { |w| w.start_with?('issue-') }.each do |window|
178
+ issue_number = window.match(/issue-(\d+)/)[1]
179
+ # GitHub APIでクローズ状態を確認して削除
180
+ end
181
+ end
182
+ ```
183
+
184
+ ## エラーハンドリング
185
+
186
+ ### TmuxNotInstalled例外
187
+ tmuxがインストールされていない場合に発生:
188
+
189
+ ```ruby
190
+ begin
191
+ client.create_session("test")
192
+ rescue Soba::Infrastructure::TmuxNotInstalled => e
193
+ puts "tmuxをインストールしてください"
194
+ end
195
+ ```
196
+
197
+ ### ウィンドウ作成失敗
198
+ セッションが存在しない場合など:
199
+
200
+ ```ruby
201
+ result = manager.create_issue_window(
202
+ session_name: "non-existent",
203
+ issue_number: 24
204
+ )
205
+ if !result[:success]
206
+ puts "エラー: #{result[:error]}"
207
+ end
208
+ ```
209
+
210
+ ## テスト戦略
211
+
212
+ ### モックを使用した単体テスト
213
+ ```ruby
214
+ RSpec.describe Soba::Services::TmuxSessionManager do
215
+ let(:tmux_client) { instance_double(Soba::Infrastructure::TmuxClient) }
216
+
217
+ it "creates repository session with correct name" do
218
+ allow(tmux_client).to receive(:session_exists?).and_return(false)
219
+ allow(tmux_client).to receive(:create_session).and_return(true)
220
+
221
+ result = manager.find_or_create_repository_session
222
+ expect(result[:session_name]).to match(/^soba-[\w-]+$/)
223
+ end
224
+ end
225
+ ```
226
+
227
+ ### 実環境での統合テスト
228
+ ```ruby
229
+ RSpec.describe "Tmux Integration", integration: true do
230
+ it "manages window lifecycle" do
231
+ session = manager.find_or_create_repository_session
232
+ window = manager.create_issue_window(
233
+ session_name: session[:session_name],
234
+ issue_number: 99
235
+ )
236
+ expect(window[:success]).to be true
237
+
238
+ pane = manager.create_phase_pane(
239
+ session_name: session[:session_name],
240
+ window_name: window[:window_name],
241
+ phase: 'test'
242
+ )
243
+ expect(pane[:success]).to be true
244
+ end
245
+ end
246
+ ```
247
+
248
+ ## 注意事項
249
+
250
+ - tmuxセッションは手動でアタッチ可能(`tmux attach-session -t soba-{repository}`)
251
+ - リポジトリごとに1つのセッションを使用し、Issue単位でウィンドウを管理
252
+ - フェーズごとにペインを作成し、最大3ペインまで自動管理
253
+ - tmuxがインストールされていない環境では動作しない
@@ -0,0 +1,58 @@
1
+ You are part of a documentation-aware AI system.
2
+
3
+ This project uses a structured **Document System** under the `docs/` directory to manage business and technical documents in a hierarchical and searchable format.
4
+
5
+ ## Folder Structure Overview
6
+
7
+ ```
8
+ docs/
9
+ ├── business/ # Business documents
10
+ │ ├── INDEX.md # Index file for this folder
11
+ │ ├── overview.md # Project overview
12
+ │ └── model.md # Business model description
13
+
14
+ ├── development/ # Development-related documents
15
+ │ ├── INDEX.md # Index file for this folder
16
+ │ ├── guideline.md # Development guide
17
+ │ └── coding-rule.md # Coding standards
18
+
19
+ ├── operations/ # (Planned) Operational documents
20
+ │ ├── INDEX.md # Index file for this folder
21
+ │ ├── server.md # Server operations
22
+ │ └── monitoring.md # Monitoring and incident response
23
+ ```
24
+
25
+ ## Document Characteristics
26
+
27
+ - All documents are written in Markdown format.
28
+ - Each directory contains an `INDEX.md` file listing:
29
+ - The filenames in the same directory
30
+ - A brief description for each
31
+
32
+ Example:
33
+ ```markdown
34
+ # Development Documents
35
+
36
+ - `guideline.md`: A guide to the development workflow.
37
+ - `coding-rule.md`: Coding standards for this project.
38
+ ```
39
+
40
+ ## Integration with CLAUDE.md
41
+
42
+ The AI system does **not directly reference documents**. Instead, it recognizes document availability via `CLAUDE.md`, where paths are listed using the format:
43
+
44
+ ```
45
+ @docs/development/INDEX.md
46
+ ```
47
+
48
+ This tells the AI:
49
+ - The document exists
50
+ - It may be referenced when needed
51
+ - But the AI should **autonomously decide** which document to consult
52
+
53
+ ## Purpose
54
+
55
+ The Document System allows AI agents to:
56
+ - Navigate structured, maintainable documentation
57
+ - Understand the project context through index files
58
+ - Autonomously choose and reference relevant documents during tasks
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/blank"
4
+ require_relative "../../config_loader"
5
+ require_relative "../../configuration"
6
+
7
+ module Soba
8
+ module Commands
9
+ module Config
10
+ class Show
11
+ def execute(config_path: nil)
12
+ config = Soba::ConfigLoader.load(path: config_path)
13
+
14
+ puts "=== soba Configuration ==="
15
+ puts ""
16
+ puts "GitHub:"
17
+ puts " Repository: #{config.github.repository}"
18
+ puts " Token: #{mask_token(config.github.token)}"
19
+ puts ""
20
+ puts "Workflow:"
21
+ puts " Interval: #{config.workflow.interval} seconds"
22
+ puts ""
23
+ puts "Configuration loaded from: #{find_config_path(config_path)}"
24
+ rescue Soba::ConfigurationError => e
25
+ Soba.logger.error "Configuration Error: #{e.message}"
26
+ exit 1
27
+ end
28
+
29
+ private
30
+
31
+ def mask_token(token)
32
+ return "Not set" if token.blank?
33
+
34
+ if token.length > 8
35
+ "#{token[0..3]}...#{token[-4..]}"
36
+ else
37
+ "*" * token.length
38
+ end
39
+ end
40
+
41
+ def find_config_path(path)
42
+ return path if path
43
+
44
+ project_root = find_project_root
45
+ return "Not found" unless project_root
46
+
47
+ project_root.join('.soba', 'config.yml')
48
+ end
49
+
50
+ def find_project_root
51
+ current = Pathname.pwd
52
+
53
+ until current.root?
54
+ return current if current.join('.git').exist?
55
+ current = current.parent
56
+ end
57
+
58
+ Pathname.pwd
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end