beeops 0.1.6 → 0.1.9
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.
- package/bin/beeops.js +32 -3
- package/command/bo.md +65 -4
- package/contexts/en/queen.md +20 -4
- package/contexts/ja/queen.md +20 -4
- package/contexts/queen.md +6 -1
- package/package.json +1 -1
- package/skills/bo-issue-sync/SKILL.md +35 -1
package/bin/beeops.js
CHANGED
|
@@ -117,6 +117,32 @@ function checkPrerequisites() {
|
|
|
117
117
|
return allOk;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
// ── .gitignore management ──
|
|
121
|
+
|
|
122
|
+
const GITIGNORE_ENTRIES = [
|
|
123
|
+
".claude/tasks/",
|
|
124
|
+
".claude/worktrees/",
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
function updateGitignore(root) {
|
|
128
|
+
const gitignorePath = path.join(root, ".gitignore");
|
|
129
|
+
let content = "";
|
|
130
|
+
if (fs.existsSync(gitignorePath)) {
|
|
131
|
+
content = fs.readFileSync(gitignorePath, "utf8");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const lines = content.split("\n");
|
|
135
|
+
const missing = GITIGNORE_ENTRIES.filter((entry) => !lines.some((line) => line.trim() === entry));
|
|
136
|
+
|
|
137
|
+
if (missing.length === 0) return;
|
|
138
|
+
|
|
139
|
+
const block = "\n# beeops runtime artifacts\n" + missing.join("\n") + "\n";
|
|
140
|
+
fs.writeFileSync(gitignorePath, content.trimEnd() + block);
|
|
141
|
+
for (const entry of missing) {
|
|
142
|
+
console.log(` gitignore: added ${entry}`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
120
146
|
// ── Hook registration ──
|
|
121
147
|
|
|
122
148
|
function resolveSettingsFile(root, mode) {
|
|
@@ -267,16 +293,19 @@ function init(opts) {
|
|
|
267
293
|
}
|
|
268
294
|
}
|
|
269
295
|
|
|
270
|
-
// 4.
|
|
296
|
+
// 4. Update .gitignore (runtime artifacts should not be tracked)
|
|
297
|
+
updateGitignore(root);
|
|
298
|
+
|
|
299
|
+
// 5. Register hooks (UserPromptSubmit)
|
|
271
300
|
updateSettingsHook(root, opts.hookMode);
|
|
272
301
|
|
|
273
|
-
//
|
|
302
|
+
// 6. Save locale preference
|
|
274
303
|
const boDir = path.join(claudeDir, "beeops");
|
|
275
304
|
ensureDir(boDir);
|
|
276
305
|
fs.writeFileSync(path.join(boDir, "locale"), opts.locale + "\n");
|
|
277
306
|
console.log(` locale: ${opts.locale} (saved to .claude/beeops/locale)`);
|
|
278
307
|
|
|
279
|
-
//
|
|
308
|
+
// 7. Copy contexts if --with-contexts
|
|
280
309
|
if (opts.withContexts) {
|
|
281
310
|
const destContexts = path.join(claudeDir, "beeops", "contexts");
|
|
282
311
|
copyDir(CONTEXTS_SRC, destContexts);
|
package/command/bo.md
CHANGED
|
@@ -86,17 +86,78 @@ done
|
|
|
86
86
|
|
|
87
87
|
Polls for up to 120 seconds. Startup is complete when the `Claude Code` banner appears.
|
|
88
88
|
|
|
89
|
-
### Step 5:
|
|
89
|
+
### Step 5: Resolve execution mode and send initial prompt
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
Determine what instruction to send to the Queen. Priority order:
|
|
92
|
+
|
|
93
|
+
1. **`$ARGUMENTS` provided** → use it directly, skip settings/interactive
|
|
94
|
+
2. **Settings file exists** (`.claude/beeops/settings.json`) → build instruction from settings
|
|
95
|
+
3. **No arguments and no settings** → ask the user interactively
|
|
96
|
+
|
|
97
|
+
#### 5a. If `$ARGUMENTS` is non-empty
|
|
98
|
+
|
|
99
|
+
Use it directly:
|
|
92
100
|
|
|
93
101
|
```bash
|
|
94
102
|
if [ -n "$ARGUMENTS" ]; then
|
|
95
103
|
INSTRUCTION="$ARGUMENTS"
|
|
96
|
-
else
|
|
97
|
-
INSTRUCTION="Sync GitHub Issues to queue.yaml and complete all tasks."
|
|
98
104
|
fi
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### 5b. If no arguments, check for settings file
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
SETTINGS_FILE=".claude/beeops/settings.json"
|
|
111
|
+
if [ -z "$ARGUMENTS" ] && [ -f "$SETTINGS_FILE" ]; then
|
|
112
|
+
echo "Found settings: $SETTINGS_FILE"
|
|
113
|
+
cat "$SETTINGS_FILE"
|
|
114
|
+
fi
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
If the settings file exists, build the instruction based on its contents:
|
|
118
|
+
|
|
119
|
+
| Field | Type | Description |
|
|
120
|
+
|-------|------|-------------|
|
|
121
|
+
| `issues` | `number[]` | Specific issue numbers to process (e.g. `[42, 55]`) |
|
|
122
|
+
| `assignee` | `string` | `"me"` = only issues assigned to the current GitHub user, `"all"` = all open issues |
|
|
123
|
+
| `skip_review` | `boolean` | Skip review phase if true (default: false) |
|
|
124
|
+
| `priority` | `string` | Only process issues of this priority or higher (`"high"`, `"medium"`, `"low"`) |
|
|
125
|
+
| `labels` | `string[]` | Only process issues with these labels |
|
|
126
|
+
|
|
127
|
+
Build the `INSTRUCTION` string as follows:
|
|
128
|
+
- If `issues` is set: `"Sync GitHub Issues to queue.yaml and process only issues: #42, #55."`
|
|
129
|
+
- If `assignee` is `"me"`: `"Sync GitHub Issues to queue.yaml and process only issues assigned to me."`
|
|
130
|
+
- If `assignee` is `"all"` or not set: `"Sync GitHub Issues to queue.yaml and complete all tasks."`
|
|
131
|
+
- Append options: if `skip_review` is true, append `" Skip the review phase."`. If `priority` is set, append `" Only process issues with priority {priority} or higher."`. If `labels` is set, append `" Only process issues with labels: {labels}."`
|
|
132
|
+
|
|
133
|
+
#### 5c. If no arguments and no settings file, ask the user interactively
|
|
99
134
|
|
|
135
|
+
Present the following choices to the user (use AskUserQuestion or display the options and wait for input):
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
How should the Queen process issues?
|
|
139
|
+
|
|
140
|
+
1. Specify issue numbers (e.g. 42, 55, 100)
|
|
141
|
+
2. Only issues assigned to me
|
|
142
|
+
3. All open issues
|
|
143
|
+
|
|
144
|
+
Enter your choice (1/2/3):
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Based on the user's response:
|
|
148
|
+
- **Choice 1**: Ask for issue numbers, then set `INSTRUCTION="Sync GitHub Issues to queue.yaml and process only issues: #42, #55."`
|
|
149
|
+
- **Choice 2**: Set `INSTRUCTION="Sync GitHub Issues to queue.yaml and process only issues assigned to me."`
|
|
150
|
+
- **Choice 3**: Set `INSTRUCTION="Sync GitHub Issues to queue.yaml and complete all tasks."`
|
|
151
|
+
|
|
152
|
+
Optionally, after the mode is selected, ask:
|
|
153
|
+
```
|
|
154
|
+
Save this as default settings? (y/n)
|
|
155
|
+
```
|
|
156
|
+
If yes, write the corresponding `.claude/beeops/settings.json` file so the next run uses it automatically.
|
|
157
|
+
|
|
158
|
+
#### 5d. Send the instruction to the Queen
|
|
159
|
+
|
|
160
|
+
```bash
|
|
100
161
|
tmux send-keys -t "$SESSION:queen" "$INSTRUCTION"
|
|
101
162
|
sleep 0.3
|
|
102
163
|
tmux send-keys -t "$SESSION:queen" Enter
|
package/contexts/en/queen.md
CHANGED
|
@@ -70,7 +70,12 @@ Analyze the received instructions (prompt) and formulate an execution plan.
|
|
|
70
70
|
|
|
71
71
|
| Instruction Content | Action |
|
|
72
72
|
|---------------------|--------|
|
|
73
|
-
| No instructions / "Process Issues" etc. | Go directly to Phase 1 (Issue sync) |
|
|
73
|
+
| No instructions / "Process Issues" etc. | Go directly to Phase 1 (Issue sync) — process all open issues |
|
|
74
|
+
| "process only issues: #42, #55" etc. | Phase 1 with issue filter — only sync and process the specified issue numbers |
|
|
75
|
+
| "process only issues assigned to me" | Phase 1 with assignee filter — use `gh issue list --assignee @me` to fetch only assigned issues |
|
|
76
|
+
| "Only process issues with priority X or higher" | Phase 1 with priority filter — skip issues below the specified priority |
|
|
77
|
+
| "Only process issues with labels: X, Y" | Phase 1 with label filter — use `gh issue list --label X --label Y` |
|
|
78
|
+
| "Skip the review phase" | Set skip_review flag — after Leader completes, go directly to ci_checking instead of launching Review Leader |
|
|
74
79
|
| Specific work instructions present | Decompose into tasks and add to queue.yaml |
|
|
75
80
|
|
|
76
81
|
### Task Decomposition Procedure
|
|
@@ -125,6 +130,11 @@ queued -> dispatched -> leader_working -> review_dispatched -> reviewing -> done
|
|
|
125
130
|
^ |
|
|
126
131
|
+---- fixing <-- fix_required ----------------------------+
|
|
127
132
|
(max 3 loops)
|
|
133
|
+
|
|
134
|
+
(shortcut: existing PR detected)
|
|
135
|
+
review_dispatched -> reviewing -> done
|
|
136
|
+
|
|
|
137
|
+
fixing <-- fix_required
|
|
128
138
|
```
|
|
129
139
|
|
|
130
140
|
| Status | Meaning |
|
|
@@ -144,7 +154,7 @@ queued -> dispatched -> leader_working -> review_dispatched -> reviewing -> done
|
|
|
144
154
|
|
|
145
155
|
## Task Selection Rules
|
|
146
156
|
|
|
147
|
-
1. Select tasks that are `queued` and whose `depends_on` is empty (or all dependencies are `done`)
|
|
157
|
+
1. Select tasks that are `queued` or `review_dispatched` (with existing PR) and whose `depends_on` is empty (or all dependencies are `done`)
|
|
148
158
|
2. Skip tasks with a `blocked_reason` (record "Skipped: {reason}" in the log)
|
|
149
159
|
3. Priority order: high -> medium -> low
|
|
150
160
|
4. Within the same priority, process lower Issue numbers first
|
|
@@ -172,11 +182,17 @@ review_window: "review-42" # review window name
|
|
|
172
182
|
3. Execute based on the task's type and assignee:
|
|
173
183
|
|
|
174
184
|
### type: issue (or assignee: leader)
|
|
175
|
-
|
|
185
|
+
|
|
186
|
+
**First, check if the task already has a PR** (i.e. `pr` field is non-null when status is `review_dispatched`):
|
|
187
|
+
- **PR exists** → Skip Leader. Directly launch Review Leader via bo-dispatch to verify the existing PR meets the Issue requirements.
|
|
188
|
+
- **No PR** → Normal flow: launch Leader first.
|
|
189
|
+
|
|
190
|
+
After determining the starting point:
|
|
191
|
+
1. Invoke **Skill: `bo-dispatch`** to launch a Leader (or Review Leader if PR exists)
|
|
176
192
|
2. Based on the result (report content) returned by bo-dispatch:
|
|
177
193
|
- Leader completed -> update to `review_dispatched` -> launch Review Leader (invoke bo-dispatch again)
|
|
178
194
|
- Review Leader approve -> `ci_checking` -> verify CI
|
|
179
|
-
- Review Leader fix_required -> if review_count < 3, set to `fixing` -> relaunch Leader (fix mode)
|
|
195
|
+
- Review Leader fix_required -> if review_count < 3, set to `fixing` -> relaunch Leader (fix mode, using existing branch)
|
|
180
196
|
- Failure -> update to `error`
|
|
181
197
|
|
|
182
198
|
### type: adhoc, assignee: orchestrator
|
package/contexts/ja/queen.md
CHANGED
|
@@ -70,7 +70,12 @@ Phase 2: イベント駆動ループ
|
|
|
70
70
|
|
|
71
71
|
| 指示の内容 | 処理 |
|
|
72
72
|
|-----------|------|
|
|
73
|
-
| 指示なし / 「Issue を消化」等 | Phase 1(Issue 同期)に直行 |
|
|
73
|
+
| 指示なし / 「Issue を消化」等 | Phase 1(Issue 同期)に直行 — 全オープン Issue を処理 |
|
|
74
|
+
| "process only issues: #42, #55" 等 | Phase 1(Issue フィルター付き) — 指定された Issue 番号のみ同期・処理 |
|
|
75
|
+
| "process only issues assigned to me" | Phase 1(担当者フィルター付き) — `gh issue list --assignee @me` で自分担当のみ取得 |
|
|
76
|
+
| "Only process issues with priority X or higher" | Phase 1(優先度フィルター付き) — 指定優先度未満をスキップ |
|
|
77
|
+
| "Only process issues with labels: X, Y" | Phase 1(ラベルフィルター付き) — `gh issue list --label X --label Y` |
|
|
78
|
+
| "Skip the review phase" | skip_review フラグ設定 — Leader 完了後、Review Leader を飛ばして直接 ci_checking へ |
|
|
74
79
|
| 具体的な作業指示がある | タスク分解して queue.yaml に追加 |
|
|
75
80
|
|
|
76
81
|
### タスク分解の手順
|
|
@@ -125,6 +130,11 @@ queued → dispatched → leader_working → review_dispatched → reviewing →
|
|
|
125
130
|
↑ │
|
|
126
131
|
└──── fixing ←── fix_required ───────────────────────────┘
|
|
127
132
|
(最大3回ループ)
|
|
133
|
+
|
|
134
|
+
(短縮パス: 既存 PR 検出時)
|
|
135
|
+
review_dispatched → reviewing → done
|
|
136
|
+
│
|
|
137
|
+
fixing ←── fix_required
|
|
128
138
|
```
|
|
129
139
|
|
|
130
140
|
| ステータス | 意味 |
|
|
@@ -144,7 +154,7 @@ queued → dispatched → leader_working → review_dispatched → reviewing →
|
|
|
144
154
|
|
|
145
155
|
## タスク選択ルール
|
|
146
156
|
|
|
147
|
-
1. `queued`
|
|
157
|
+
1. `queued` または `review_dispatched`(既存 PR あり)かつ `depends_on` が空(または全て `done`)のタスクを選択
|
|
148
158
|
2. `blocked_reason` があるタスクはスキップ(ログに「スキップ: {理由}」を記録)
|
|
149
159
|
3. 優先度順: high → medium → low
|
|
150
160
|
4. 同一優先度内では Issue 番号が小さい方を先に
|
|
@@ -172,11 +182,17 @@ review_window: "review-42" # review window 名
|
|
|
172
182
|
3. タスクの type と assignee に応じて実行:
|
|
173
183
|
|
|
174
184
|
### type: issue(または assignee: leader)
|
|
175
|
-
|
|
185
|
+
|
|
186
|
+
**まず、タスクに既存 PR があるか確認する**(`pr` フィールドが非null かつ status が `review_dispatched`):
|
|
187
|
+
- **PR あり** → Leader をスキップ。bo-dispatch で Review Leader を直接起動し、既存 PR が Issue の要件を満たしているか検証する。
|
|
188
|
+
- **PR なし** → 通常フロー: まず Leader を起動。
|
|
189
|
+
|
|
190
|
+
開始ポイントを決定した後:
|
|
191
|
+
1. **Skill: `bo-dispatch`** を発動し、Leader(または PR 既存なら Review Leader)を起動
|
|
176
192
|
2. bo-dispatch が返す結果(レポート内容)に基づいて判定:
|
|
177
193
|
- Leader completed → `review_dispatched` に更新 → Review Leader 起動(再度 bo-dispatch)
|
|
178
194
|
- Review Leader approve → `ci_checking` → CI 確認
|
|
179
|
-
- Review Leader fix_required → review_count < 3 なら `fixing` → Leader
|
|
195
|
+
- Review Leader fix_required → review_count < 3 なら `fixing` → Leader 再起動(fix mode、既存ブランチを再利用)
|
|
180
196
|
- 失敗 → `error` に更新
|
|
181
197
|
|
|
182
198
|
### type: adhoc, assignee: orchestrator
|
package/contexts/queen.md
CHANGED
|
@@ -70,7 +70,12 @@ Analyze the received instructions (prompt) and formulate an execution plan.
|
|
|
70
70
|
|
|
71
71
|
| Instruction Content | Action |
|
|
72
72
|
|---------------------|--------|
|
|
73
|
-
| No instructions / "Process Issues" etc. | Go directly to Phase 1 (Issue sync) |
|
|
73
|
+
| No instructions / "Process Issues" etc. | Go directly to Phase 1 (Issue sync) — process all open issues |
|
|
74
|
+
| "process only issues: #42, #55" etc. | Phase 1 with issue filter — only sync and process the specified issue numbers |
|
|
75
|
+
| "process only issues assigned to me" | Phase 1 with assignee filter — use `gh issue list --assignee @me` to fetch only assigned issues |
|
|
76
|
+
| "Only process issues with priority X or higher" | Phase 1 with priority filter — skip issues below the specified priority |
|
|
77
|
+
| "Only process issues with labels: X, Y" | Phase 1 with label filter — use `gh issue list --label X --label Y` |
|
|
78
|
+
| "Skip the review phase" | Set skip_review flag — after Leader completes, go directly to ci_checking instead of launching Review Leader |
|
|
74
79
|
| Specific work instructions present | Decompose into tasks and add to queue.yaml |
|
|
75
80
|
|
|
76
81
|
### Task Decomposition Procedure
|
package/package.json
CHANGED
|
@@ -26,6 +26,22 @@ gh issue list -R "$REPO" --state open --json number,title,labels,assignees --lim
|
|
|
26
26
|
|
|
27
27
|
If 0 issues, display "No issues to process" and exit.
|
|
28
28
|
|
|
29
|
+
### 2.5. Detect Existing PRs
|
|
30
|
+
|
|
31
|
+
For each open Issue, check if a linked PR already exists:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
gh pr list -R "$REPO" --search "linked:issue:{number}" --state open --json number,url,headRefName --limit 1
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If no result, also try keyword search as fallback:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
gh pr list -R "$REPO" --search "{issue_number} in:title" --state open --json number,url,headRefName --limit 1
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Store the results (PR URL + branch name) for use in Step 4.
|
|
44
|
+
|
|
29
45
|
### 3. Load queue.yaml
|
|
30
46
|
|
|
31
47
|
If `.claude/tasks/queue.yaml` exists, read it. Otherwise initialize:
|
|
@@ -37,7 +53,9 @@ tasks: []
|
|
|
37
53
|
|
|
38
54
|
### 4. Diff Detection and Raw Addition
|
|
39
55
|
|
|
40
|
-
Add Issues not present in queue.yaml
|
|
56
|
+
Add Issues not present in queue.yaml. If an existing PR was detected in Step 2.5, start from `review_dispatched`; otherwise use `raw` status:
|
|
57
|
+
|
|
58
|
+
**No existing PR (normal flow):**
|
|
41
59
|
|
|
42
60
|
```yaml
|
|
43
61
|
- id: "ISSUE-{number}"
|
|
@@ -53,6 +71,22 @@ Add Issues not present in queue.yaml with `raw` status:
|
|
|
53
71
|
- "{ISO8601} created from gh issue"
|
|
54
72
|
```
|
|
55
73
|
|
|
74
|
+
**Existing PR detected (skip to review):**
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
- id: "ISSUE-{number}"
|
|
78
|
+
issue: {number}
|
|
79
|
+
title: "{title}"
|
|
80
|
+
status: review_dispatched
|
|
81
|
+
priority: high
|
|
82
|
+
branch: "{headRefName from PR}"
|
|
83
|
+
depends_on: []
|
|
84
|
+
review_count: 0
|
|
85
|
+
pr: "{PR URL}"
|
|
86
|
+
log:
|
|
87
|
+
- "{ISO8601} created from gh issue (existing PR #{pr_number} detected, starting from review)"
|
|
88
|
+
```
|
|
89
|
+
|
|
56
90
|
- Skip Issues already in queue.yaml (with status other than done)
|
|
57
91
|
- Update status to `done` for Issues in queue.yaml that are closed on GitHub
|
|
58
92
|
|