claude-plugin-viban 1.1.2 → 1.2.1
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/.claude-plugin/plugin.json +1 -1
- package/README.md +69 -8
- package/bin/viban +75 -20
- package/commands/add.md +56 -51
- package/commands/assign.md +96 -115
- package/commands/parallel-assign.md +15 -0
- package/commands/sync.md +1 -1
- package/docs/CLAUDE.md +3 -4
- package/package.json +1 -1
- package/scripts/providers/github.sh +3 -2
- package/scripts/sync.sh +38 -1
- package/scripts/sync_create.sh +68 -0
- package/skills/add/SKILL.md +56 -51
- package/skills/assign/SKILL.md +96 -115
- package/skills/parallel-assign/SKILL.md +297 -0
- package/skills/setup/SKILL.md +43 -21
- package/skills/sync/SKILL.md +1 -1
package/commands/assign.md
CHANGED
|
@@ -4,71 +4,64 @@ description: "Assign and resolve first backlog issue from viban board through to
|
|
|
4
4
|
|
|
5
5
|
# /assign
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
First backlog issue → Resolve → PR completion
|
|
8
8
|
|
|
9
|
-
> **
|
|
10
|
-
> **No Worktree** - Work directly on branch in main repo
|
|
11
|
-
> **Workflow**: Read `.viban/workflow.md` first, then CLAUDE.md fallback
|
|
9
|
+
> **CLI only** (no direct viban.json access) | **No worktree** (branch in main repo)
|
|
12
10
|
|
|
13
11
|
---
|
|
14
12
|
|
|
15
|
-
## Phase 0:
|
|
13
|
+
## Phase 0: SETUP
|
|
16
14
|
|
|
17
|
-
### 0.1 Read
|
|
15
|
+
### 0.1 Read Workflow (CRITICAL)
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
**Priority 1: `.viban/workflow.md`** (dedicated workflow file)
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
[ -f ".viban/workflow.md" ] && cat ".viban/workflow.md"
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**Priority 2: CLAUDE.md** (legacy fallback)
|
|
28
|
-
|
|
29
|
-
Only if `.viban/workflow.md` does NOT exist:
|
|
17
|
+
Check in priority order — first match wins, follow it exactly:
|
|
30
18
|
|
|
19
|
+
1. `.viban/workflow.md` → `[ -f ".viban/workflow.md" ] && cat ".viban/workflow.md"`
|
|
20
|
+
2. CLAUDE.md (legacy, only if no workflow.md):
|
|
31
21
|
```bash
|
|
32
22
|
for path in "./CLAUDE.md" "./.claude/CLAUDE.md" "../CLAUDE.md"; do
|
|
33
23
|
[ -f "$path" ] && cat "$path"
|
|
34
24
|
done
|
|
35
25
|
```
|
|
26
|
+
Look for `Issue Resolution Workflow` or `Workflow` section.
|
|
27
|
+
3. Default workflow (Phase 1 below)
|
|
36
28
|
|
|
37
|
-
|
|
29
|
+
### 0.2 Git Setup & Assign
|
|
38
30
|
|
|
39
|
-
|
|
31
|
+
```bash
|
|
32
|
+
# Check uncommitted changes → AskUserQuestion if dirty
|
|
33
|
+
[ -n "$(git status --porcelain)" ] && echo "Warning: Uncommitted changes"
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
- If `.viban/workflow.md` exists -> MUST follow it exactly (all phases)
|
|
43
|
-
- Else if CLAUDE.md has a workflow section -> MUST follow it exactly
|
|
44
|
-
- If no workflow found -> Use default workflow (Phase 1 below)
|
|
35
|
+
git checkout main && git fetch origin main && git reset --hard origin/main
|
|
45
36
|
|
|
46
|
-
|
|
37
|
+
ISSUE_ID=$(viban assign 2>&1 | tail -1)
|
|
38
|
+
[[ -z "$ISSUE_ID" || "$ISSUE_ID" == "No backlog" ]] && echo "No issues in backlog" && exit 0
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 0.3 Detect Sync & Create Branch
|
|
47
42
|
|
|
48
43
|
```bash
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
ISSUE_JSON=$(viban get $ISSUE_ID)
|
|
45
|
+
EXT_ID=$(echo "$ISSUE_JSON" | jq -r '.external_id // ""')
|
|
46
|
+
SYNC_ACTIVE=false; EXTERNAL_NUM=""
|
|
47
|
+
|
|
48
|
+
if [ -n "$EXT_ID" ] && [ "$EXT_ID" != "null" ]; then
|
|
49
|
+
SYNC_ACTIVE=true
|
|
50
|
+
EXTERNAL_NUM="${EXT_ID##*:}" # "github:42" -> "42"
|
|
51
|
+
TITLE=$(echo "$ISSUE_JSON" | jq -r '.title' | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | head -c 40)
|
|
52
|
+
git checkout -b "issue-${EXTERNAL_NUM}-${TITLE}"
|
|
53
|
+
else
|
|
54
|
+
git checkout -b issue-$ISSUE_ID
|
|
53
55
|
fi
|
|
56
|
+
```
|
|
54
57
|
|
|
55
|
-
|
|
56
|
-
git checkout main
|
|
57
|
-
git fetch origin main
|
|
58
|
-
git reset --hard origin/main
|
|
59
|
-
|
|
60
|
-
# 3. Assign issue
|
|
61
|
-
ISSUE_ID=$(viban assign 2>&1 | tail -1)
|
|
62
|
-
if [ -z "$ISSUE_ID" ] || [ "$ISSUE_ID" = "No backlog" ]; then
|
|
63
|
-
echo "No issues in backlog"
|
|
64
|
-
exit 0
|
|
65
|
-
fi
|
|
58
|
+
### 0.4 Load Plan (if available)
|
|
66
59
|
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
```bash
|
|
61
|
+
[ -f ".viban/plans/${ISSUE_ID}.md" ] && cat ".viban/plans/${ISSUE_ID}.md"
|
|
69
62
|
```
|
|
70
63
|
|
|
71
|
-
If
|
|
64
|
+
If plan exists: use as primary guide for Phase 1, skip redundant analysis, but verify plan is still current.
|
|
72
65
|
|
|
73
66
|
---
|
|
74
67
|
|
|
@@ -78,102 +71,105 @@ If backlog is empty: Notify user and exit
|
|
|
78
71
|
viban get $ISSUE_ID
|
|
79
72
|
```
|
|
80
73
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
Follow the project's exact steps.
|
|
84
|
-
|
|
85
|
-
### Default Workflow (if no project workflow):
|
|
86
|
-
|
|
87
|
-
1. **Understand**: Read the issue, understand the problem
|
|
88
|
-
2. **Locate**: Find relevant code files
|
|
89
|
-
3. **Analyze**: Determine root cause
|
|
90
|
-
4. **Implement**: Make minimal, focused changes
|
|
74
|
+
**With project workflow**: follow its exact steps.
|
|
75
|
+
**Default** (no workflow): Understand → Locate → Analyze root cause → Implement minimal changes.
|
|
91
76
|
|
|
92
77
|
---
|
|
93
78
|
|
|
94
79
|
## Phase 2: VERIFY
|
|
95
80
|
|
|
96
|
-
Manual verification
|
|
97
|
-
|
|
98
|
-
### Verification Methods (use what's appropriate):
|
|
81
|
+
Manual verification — do NOT run build/test here (Phase 3).
|
|
99
82
|
|
|
100
|
-
| Type | Tool |
|
|
101
|
-
|
|
102
|
-
| Web UI | Playwright MCP
|
|
103
|
-
| API | WebFetch |
|
|
104
|
-
| CLI | Bash |
|
|
105
|
-
| Visual | Read
|
|
106
|
-
| Browser | Chrome DevTools MCP |
|
|
83
|
+
| Type | Tool |
|
|
84
|
+
|------|------|
|
|
85
|
+
| Web UI | Playwright MCP (`browser_navigate`, `browser_snapshot`, `browser_click`) |
|
|
86
|
+
| API | WebFetch |
|
|
87
|
+
| CLI | Bash |
|
|
88
|
+
| Visual | Read (screenshot files) |
|
|
89
|
+
| Browser | Chrome DevTools MCP |
|
|
107
90
|
|
|
108
|
-
|
|
91
|
+
Steps: identify what proves the fix → execute → confirm behavior → document evidence.
|
|
109
92
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
93
|
+
Examples:
|
|
94
|
+
- Web feature: navigate to page, take snapshot, verify element exists
|
|
95
|
+
- API fix: fetch endpoint, check response status and body
|
|
96
|
+
- CLI change: run command, verify output format
|
|
97
|
+
- UI bug: navigate, interact, confirm no error
|
|
114
98
|
|
|
115
|
-
|
|
116
|
-
- Web feature: Navigate to page, take snapshot, verify element exists
|
|
117
|
-
- API fix: Fetch endpoint, check response status and body
|
|
118
|
-
- CLI change: Run command, verify output format
|
|
119
|
-
- UI bug: Navigate, interact, confirm no error
|
|
120
|
-
|
|
121
|
-
If verification fails: Return to Phase 1, fix the issue, re-verify.
|
|
99
|
+
If verification fails: return to Phase 1.
|
|
122
100
|
|
|
123
101
|
---
|
|
124
102
|
|
|
125
103
|
## Phase 3: SHIP
|
|
126
104
|
|
|
127
|
-
### 3.1
|
|
105
|
+
### 3.1 Build & Test
|
|
128
106
|
|
|
129
|
-
|
|
130
|
-
# Run project's build/test commands
|
|
131
|
-
# Example: npm run build && npm test
|
|
132
|
-
# Example: pytest
|
|
133
|
-
# Example: cargo build && cargo test
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
If build/test fails: Fix errors, return to Phase 2 for re-verification.
|
|
107
|
+
Run project's build/test commands. If fail: fix → return to Phase 2.
|
|
137
108
|
|
|
138
109
|
### 3.2 Rebase
|
|
139
110
|
|
|
140
111
|
```bash
|
|
141
|
-
git fetch origin main
|
|
142
|
-
git rebase origin/main
|
|
112
|
+
git fetch origin main && git rebase origin/main
|
|
143
113
|
# On conflict: resolve -> git add -> git rebase --continue
|
|
144
114
|
```
|
|
145
115
|
|
|
146
116
|
### 3.3 Commit & Push
|
|
147
117
|
|
|
148
118
|
```bash
|
|
119
|
+
BRANCH=$(git branch --show-current)
|
|
149
120
|
git add -A
|
|
150
|
-
|
|
121
|
+
|
|
122
|
+
# Sync mode: "Closes #NUM" | Default: "Resolves: viban-ID"
|
|
123
|
+
if [ "$SYNC_ACTIVE" = true ]; then
|
|
124
|
+
git commit -m "fix: issue title summary
|
|
125
|
+
|
|
126
|
+
- Root cause: ...
|
|
127
|
+
- Solution: ...
|
|
128
|
+
|
|
129
|
+
Closes #$EXTERNAL_NUM"
|
|
130
|
+
else
|
|
131
|
+
git commit -m "fix: issue title summary
|
|
151
132
|
|
|
152
133
|
- Root cause: ...
|
|
153
134
|
- Solution: ...
|
|
154
135
|
|
|
155
|
-
Resolves:
|
|
136
|
+
Resolves: #$ISSUE_ID"
|
|
137
|
+
fi
|
|
156
138
|
|
|
157
|
-
git push -u origin
|
|
139
|
+
git push -u origin "$BRANCH"
|
|
158
140
|
```
|
|
159
141
|
|
|
160
142
|
### 3.4 Create PR
|
|
161
143
|
|
|
162
144
|
```bash
|
|
163
|
-
EXISTING_PR=$(gh pr list --head
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
145
|
+
EXISTING_PR=$(gh pr list --head "$BRANCH" --json number -q '.[0].number')
|
|
146
|
+
|
|
147
|
+
if [ -z "$EXISTING_PR" ]; then
|
|
148
|
+
if [ "$SYNC_ACTIVE" = true ]; then
|
|
149
|
+
gh pr create --title "fix: title" \
|
|
150
|
+
--body "## Changes
|
|
151
|
+
- ...
|
|
152
|
+
|
|
153
|
+
Closes #$EXTERNAL_NUM
|
|
154
|
+
|
|
155
|
+
## Verification
|
|
156
|
+
- [ ] Manual verification completed
|
|
157
|
+
- [ ] Build passing
|
|
158
|
+
- [ ] Tests passing (if applicable)" --base main
|
|
159
|
+
else
|
|
160
|
+
gh pr create --title "fix: title" \
|
|
161
|
+
--body "## Changes
|
|
167
162
|
- ...
|
|
168
163
|
|
|
169
164
|
## Verification
|
|
170
165
|
- [ ] Manual verification completed
|
|
171
166
|
- [ ] Build passing
|
|
172
|
-
- [ ] Tests passing (if applicable)"
|
|
173
|
-
|
|
167
|
+
- [ ] Tests passing (if applicable)" --base main
|
|
168
|
+
fi
|
|
169
|
+
fi
|
|
174
170
|
```
|
|
175
171
|
|
|
176
|
-
### 3.5
|
|
172
|
+
### 3.5 Move to Review
|
|
177
173
|
|
|
178
174
|
```bash
|
|
179
175
|
viban review $ISSUE_ID
|
|
@@ -184,18 +180,9 @@ viban review $ISSUE_ID
|
|
|
184
180
|
## Phase 4: HANDOFF
|
|
185
181
|
|
|
186
182
|
```
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
PR: gh pr view viban-$ISSUE_ID --web
|
|
192
|
-
|
|
193
|
-
Verification complete:
|
|
194
|
-
- Manual verification done with available tools
|
|
195
|
-
- Build passing
|
|
196
|
-
- Project workflow followed
|
|
197
|
-
|
|
198
|
-
After approval: Delete issue from viban TUI
|
|
183
|
+
Issue #$ISSUE_ID → review | PR: gh pr view --web
|
|
184
|
+
Verification: manual + build + workflow followed
|
|
185
|
+
After approval: delete issue from viban TUI
|
|
199
186
|
```
|
|
200
187
|
|
|
201
188
|
---
|
|
@@ -204,7 +191,7 @@ After approval: Delete issue from viban TUI
|
|
|
204
191
|
|
|
205
192
|
```
|
|
206
193
|
[ ] Read .viban/workflow.md (or CLAUDE.md fallback) for project workflow
|
|
207
|
-
[ ] Working on
|
|
194
|
+
[ ] Working on issue-$ISSUE_ID branch
|
|
208
195
|
[ ] Implementation complete
|
|
209
196
|
[ ] Manual verification passed (using appropriate tools)
|
|
210
197
|
[ ] Build & tests passing
|
|
@@ -217,13 +204,7 @@ After approval: Delete issue from viban TUI
|
|
|
217
204
|
|
|
218
205
|
## CRITICAL: Status Transition Rule
|
|
219
206
|
|
|
220
|
-
> **NEVER
|
|
221
|
-
>
|
|
222
|
-
> Before exiting — whether you completed all phases or stopped early due to errors:
|
|
223
|
-
> ```bash
|
|
224
|
-
> viban review $ISSUE_ID
|
|
225
|
-
> ```
|
|
226
|
-
> This is MANDATORY. If you skip this, the board becomes stale and misleading.
|
|
207
|
+
> **NEVER exit with issue still in `in_progress`.** Always run `viban review $ISSUE_ID` before exiting — whether completed or stopped early.
|
|
227
208
|
|
|
228
209
|
## CLI Reference
|
|
229
210
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Assign and resolve multiple independent backlog issues in parallel using git worktrees and coordinated agents"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `/viban:parallel-assign` to process multiple backlog issues simultaneously.
|
|
6
|
+
|
|
7
|
+
Usage: `/viban:parallel-assign [count]`
|
|
8
|
+
|
|
9
|
+
- `count`: Number of issues to process in parallel (default: 3, max: 5)
|
|
10
|
+
|
|
11
|
+
Examples:
|
|
12
|
+
- `/viban:parallel-assign` — resolve up to 3 backlog issues in parallel
|
|
13
|
+
- `/viban:parallel-assign 5` — resolve up to 5 backlog issues in parallel
|
|
14
|
+
|
|
15
|
+
Each issue gets its own opus agent working in an isolated git worktree. After all agents finish, PRs are created, local branches are preserved, and worktrees are cleaned up.
|
package/commands/sync.md
CHANGED
|
@@ -16,7 +16,7 @@ Sync the viban board with an external issue tracker. Currently supports GitHub I
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
# Check if sync is already configured
|
|
19
|
-
if [ -f "
|
|
19
|
+
if [ -f ".viban/sync.json" ]; then
|
|
20
20
|
echo "Sync configured"
|
|
21
21
|
viban sync --status
|
|
22
22
|
else
|
package/docs/CLAUDE.md
CHANGED
|
@@ -285,12 +285,11 @@ viban help # Show help
|
|
|
285
285
|
|
|
286
286
|
### Data Location
|
|
287
287
|
|
|
288
|
-
Issues are stored in `viban.json`
|
|
288
|
+
Issues are stored in `viban.json` in the `.viban/` directory:
|
|
289
289
|
|
|
290
290
|
```bash
|
|
291
|
-
#
|
|
292
|
-
|
|
293
|
-
# → .git/viban.json (or ../../.git/viban.json in worktrees)
|
|
291
|
+
# Default location
|
|
292
|
+
.viban/viban.json
|
|
294
293
|
```
|
|
295
294
|
|
|
296
295
|
**Custom location:**
|
package/package.json
CHANGED
|
@@ -130,7 +130,7 @@ provider_fetch_issues() {
|
|
|
130
130
|
local repo="$1"
|
|
131
131
|
|
|
132
132
|
local issues
|
|
133
|
-
issues=$(gh issue list --repo "$repo" --state
|
|
133
|
+
issues=$(gh issue list --repo "$repo" --state all --json number,title,body,labels,state,updatedAt --limit 200 2>/dev/null) || {
|
|
134
134
|
echo "Error: Failed to fetch issues from $repo"
|
|
135
135
|
return 1
|
|
136
136
|
}
|
|
@@ -141,7 +141,8 @@ provider_fetch_issues() {
|
|
|
141
141
|
title: .title,
|
|
142
142
|
description: (.body // ""),
|
|
143
143
|
status: (
|
|
144
|
-
if
|
|
144
|
+
if .state == "closed" then "done"
|
|
145
|
+
elif ([.labels[].name] | any(. == "review")) then "review"
|
|
145
146
|
elif ([.labels[].name] | any(. == "in-progress")) then "in_progress"
|
|
146
147
|
else "backlog"
|
|
147
148
|
end
|
package/scripts/sync.sh
CHANGED
|
@@ -149,7 +149,12 @@ sync_pull() {
|
|
|
149
149
|
'.issues[] | select(.external_id == $eid)' "$VIBAN_JSON" 2>/dev/null)
|
|
150
150
|
|
|
151
151
|
if [[ -z "$viban_card" || "$viban_card" == "null" ]]; then
|
|
152
|
-
# New remote issue -> import
|
|
152
|
+
# New remote issue -> import (skip already-closed issues)
|
|
153
|
+
if [[ "$status" == "done" ]]; then
|
|
154
|
+
echo " == ${ext_id} \"${title}\" (closed, skipped)"
|
|
155
|
+
((unchanged++))
|
|
156
|
+
continue
|
|
157
|
+
fi
|
|
153
158
|
if [[ "$dry_run" == "true" ]]; then
|
|
154
159
|
echo " <- ${ext_id} \"${title}\" (new card to create)"
|
|
155
160
|
else
|
|
@@ -189,6 +194,24 @@ sync_pull() {
|
|
|
189
194
|
viban_id=$(echo "$viban_card" | jq -r '.id')
|
|
190
195
|
viban_updated=$(echo "$viban_card" | jq -r '.updated_at')
|
|
191
196
|
|
|
197
|
+
# Remote issue closed -> remove card from viban
|
|
198
|
+
if [[ "$status" == "done" ]]; then
|
|
199
|
+
if [[ "$dry_run" == "true" ]]; then
|
|
200
|
+
echo " <- ${ext_id} \"${title}\" (closed remotely, will remove card)"
|
|
201
|
+
else
|
|
202
|
+
jq --argjson id "$viban_id" 'del(.issues[]|select((.id|tonumber)==$id))' \
|
|
203
|
+
"$VIBAN_JSON" > "${VIBAN_JSON}.tmp" && mv "${VIBAN_JSON}.tmp" "$VIBAN_JSON"
|
|
204
|
+
# Remove sync metadata for this card
|
|
205
|
+
local meta_tmp
|
|
206
|
+
meta_tmp=$(read_sync_meta)
|
|
207
|
+
meta_tmp=$(echo "$meta_tmp" | jq --arg vid "$viban_id" 'del(.issues[$vid])')
|
|
208
|
+
write_sync_meta "$meta_tmp"
|
|
209
|
+
echo " <- ${ext_id} \"${title}\" (closed remotely, card removed)"
|
|
210
|
+
fi
|
|
211
|
+
((pulled++))
|
|
212
|
+
continue
|
|
213
|
+
fi
|
|
214
|
+
|
|
192
215
|
# Get last known sync timestamps
|
|
193
216
|
local meta
|
|
194
217
|
meta=$(get_issue_meta "$viban_id")
|
|
@@ -461,6 +484,7 @@ main() {
|
|
|
461
484
|
local push_new=false
|
|
462
485
|
local pull_only=false
|
|
463
486
|
local push_only=false
|
|
487
|
+
local auto_mode=false
|
|
464
488
|
local repo_override=""
|
|
465
489
|
|
|
466
490
|
while [[ $# -gt 0 ]]; do
|
|
@@ -471,6 +495,7 @@ main() {
|
|
|
471
495
|
--push-new) push_new=true; shift ;;
|
|
472
496
|
--pull-only) pull_only=true; shift ;;
|
|
473
497
|
--push-only) push_only=true; shift ;;
|
|
498
|
+
--auto) auto_mode=true; shift ;;
|
|
474
499
|
--repo) repo_override="$2"; shift 2 ;;
|
|
475
500
|
--provider) shift 2 ;; # Already handled by bin/viban
|
|
476
501
|
*) echo "Unknown option: $1"; exit 1 ;;
|
|
@@ -515,6 +540,18 @@ main() {
|
|
|
515
540
|
exit 1
|
|
516
541
|
fi
|
|
517
542
|
|
|
543
|
+
# Auto mode: silent pull-only for TUI background use
|
|
544
|
+
if [[ "$auto_mode" == "true" ]]; then
|
|
545
|
+
sync_pull "$repo" false >/dev/null 2>&1
|
|
546
|
+
local now
|
|
547
|
+
now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
548
|
+
local meta
|
|
549
|
+
meta=$(read_sync_meta)
|
|
550
|
+
meta=$(echo "$meta" | jq --arg now "$now" '.last_sync_at = $now')
|
|
551
|
+
write_sync_meta "$meta"
|
|
552
|
+
exit 0
|
|
553
|
+
fi
|
|
554
|
+
|
|
518
555
|
# Execute sync
|
|
519
556
|
if [[ "$pull_only" == "true" ]]; then
|
|
520
557
|
echo "Pulling from $(provider_name) ($repo)..."
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# viban sync_create - Create a remote issue from a viban card
|
|
3
|
+
# Called by cmd_add when sync is configured.
|
|
4
|
+
#
|
|
5
|
+
# Usage: sync_create.sh <card_id>
|
|
6
|
+
# Output: external_id string (e.g., "github:42") on success, empty on failure
|
|
7
|
+
#
|
|
8
|
+
# Environment variables (set by caller):
|
|
9
|
+
# VIBAN_JSON - Path to viban.json
|
|
10
|
+
# VIBAN_DATA_DIR - Path to viban data directory
|
|
11
|
+
# VIBAN_PROVIDER - Provider name (e.g., "github")
|
|
12
|
+
# VIBAN_SCRIPT_DIR - Path to viban install directory
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
card_id="$1"
|
|
17
|
+
SYNC_JSON="${VIBAN_DATA_DIR}/sync.json"
|
|
18
|
+
PROVIDER_SCRIPT="${VIBAN_SCRIPT_DIR}/scripts/providers/${VIBAN_PROVIDER}.sh"
|
|
19
|
+
|
|
20
|
+
# Load provider
|
|
21
|
+
if [[ ! -f "$PROVIDER_SCRIPT" ]]; then
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
source "$PROVIDER_SCRIPT"
|
|
25
|
+
|
|
26
|
+
# Read card from viban.json
|
|
27
|
+
card=$(jq --argjson id "$card_id" '.issues[] | select((.id|tonumber)==$id)' "$VIBAN_JSON" 2>/dev/null) || exit 1
|
|
28
|
+
if [[ -z "$card" || "$card" == "null" ]]; then exit 1; fi
|
|
29
|
+
|
|
30
|
+
# Get repo from sync config
|
|
31
|
+
repo=$(jq -r '.provider_config.repo' "$SYNC_JSON" 2>/dev/null) || exit 1
|
|
32
|
+
if [[ -z "$repo" || "$repo" == "null" ]]; then exit 1; fi
|
|
33
|
+
|
|
34
|
+
# Check provider auth (silent)
|
|
35
|
+
provider_check_deps &>/dev/null || exit 1
|
|
36
|
+
provider_check_auth &>/dev/null || exit 1
|
|
37
|
+
|
|
38
|
+
# Create remote issue (split pipeline to avoid SIGPIPE with pipefail)
|
|
39
|
+
issue_json=$(echo "$card" | jq '{
|
|
40
|
+
title: .title,
|
|
41
|
+
description: (.description // ""),
|
|
42
|
+
status: .status,
|
|
43
|
+
priority: (.priority // "P3"),
|
|
44
|
+
type: (.type // "")
|
|
45
|
+
}') || exit 1
|
|
46
|
+
new_remote_id=$(echo "$issue_json" | provider_create_issue "$repo" 2>/dev/null) || exit 1
|
|
47
|
+
|
|
48
|
+
if [[ -z "$new_remote_id" ]]; then exit 1; fi
|
|
49
|
+
|
|
50
|
+
# Build external_id
|
|
51
|
+
provider_prefix="$(provider_name):"
|
|
52
|
+
ext_id="${provider_prefix}${new_remote_id}"
|
|
53
|
+
|
|
54
|
+
# Update card with external_id
|
|
55
|
+
now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
56
|
+
jq --argjson vid "$card_id" --arg eid "$ext_id" --arg now "$now" \
|
|
57
|
+
'(.issues[] | select((.id|tonumber)==$vid)) |= . + {external_id: $eid, updated_at: $now}' \
|
|
58
|
+
"$VIBAN_JSON" > "${VIBAN_JSON}.tmp" && mv "${VIBAN_JSON}.tmp" "$VIBAN_JSON"
|
|
59
|
+
|
|
60
|
+
# Record sync metadata
|
|
61
|
+
sync_meta=$(cat "$SYNC_JSON")
|
|
62
|
+
sync_meta=$(echo "$sync_meta" | jq --arg vid "$card_id" --arg rid "$new_remote_id" \
|
|
63
|
+
--arg now "$now" \
|
|
64
|
+
'.issues[$vid] = {remote_id: $rid, remote_updated_at: $now, viban_updated_at: $now}')
|
|
65
|
+
echo "$sync_meta" > "${SYNC_JSON}.tmp" && mv "${SYNC_JSON}.tmp" "$SYNC_JSON"
|
|
66
|
+
|
|
67
|
+
# Output external_id for caller
|
|
68
|
+
echo "$ext_id"
|
package/skills/add/SKILL.md
CHANGED
|
@@ -5,78 +5,54 @@ description: "Register a problem as a viban issue"
|
|
|
5
5
|
|
|
6
6
|
# /add - Register Issue
|
|
7
7
|
|
|
8
|
-
Register a problem as a viban issue.
|
|
8
|
+
Register a problem as a viban issue. No codebase exploration, no solutions — symptoms only.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**Input**: `$ARGUMENTS`
|
|
11
11
|
|
|
12
|
-
##
|
|
12
|
+
## Step 1: Clarify (only if vague)
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
If clear enough (who/what/where), skip to Step 2. Otherwise, one AskUserQuestion:
|
|
15
|
+
- header: "Problem", question: "Can you describe the symptom more specifically?"
|
|
16
|
+
- options: context-appropriate (e.g. "Error/crash", "Feature not working", "Performance issue", "Let me describe")
|
|
15
17
|
|
|
16
|
-
## Step
|
|
18
|
+
## Step 2: Priority & Type
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
Infer from description. Don't ask unless truly ambiguous.
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
| Priority | Condition | Type | When |
|
|
23
|
+
|----------|-----------|------|------|
|
|
24
|
+
| P0 | System down, data loss | bug | Something broken |
|
|
25
|
+
| P1 | Feature broken, errors | feat | New functionality |
|
|
26
|
+
| P2 | Performance, warnings | chore | Maintenance, config |
|
|
27
|
+
| P3 | Improvements, refactoring | refactor | Code restructuring |
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
- question: "Can you describe the symptom more specifically?"
|
|
24
|
-
- options based on context, e.g.:
|
|
25
|
-
- "Error/crash on specific action"
|
|
26
|
-
- "Feature not working as expected"
|
|
27
|
-
- "Performance issue"
|
|
28
|
-
- "Let me describe"
|
|
29
|
-
- multiSelect: false
|
|
30
|
-
|
|
31
|
-
Goal: get a **one-sentence symptom** clear enough for an assignee to understand.
|
|
32
|
-
|
|
33
|
-
## Step 2: Determine Priority & Type
|
|
34
|
-
|
|
35
|
-
Infer from the description. Do NOT ask unless truly ambiguous.
|
|
36
|
-
|
|
37
|
-
| Condition | Priority |
|
|
38
|
-
|-----------|----------|
|
|
39
|
-
| System down, data loss | P0 |
|
|
40
|
-
| Feature broken, errors | P1 |
|
|
41
|
-
| Performance, warnings | P2 |
|
|
42
|
-
| Improvements, refactoring | P3 |
|
|
43
|
-
|
|
44
|
-
| Type | When |
|
|
45
|
-
|------|------|
|
|
46
|
-
| bug | Something is broken |
|
|
47
|
-
| feat | New functionality |
|
|
48
|
-
| chore | Maintenance, config |
|
|
49
|
-
| refactor | Code restructuring |
|
|
50
|
-
|
|
51
|
-
## Step 3: Check Workflow for Issue Numbering
|
|
29
|
+
## Step 3: Issue Numbering
|
|
52
30
|
|
|
53
31
|
```bash
|
|
54
32
|
[ -f ".viban/workflow.md" ] && cat ".viban/workflow.md"
|
|
55
33
|
```
|
|
56
34
|
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
35
|
+
- Workflow says **Manual** → ask user for external ID (e.g. `PROJ-42`)
|
|
36
|
+
- **Auto** or no workflow → let viban auto-assign
|
|
37
|
+
- ID in `$ARGUMENTS` → use it regardless
|
|
60
38
|
|
|
61
39
|
## Step 4: Register
|
|
62
40
|
|
|
63
|
-
Write the description to a temp file, then register:
|
|
64
|
-
|
|
65
41
|
```bash
|
|
66
42
|
cat > /tmp/viban-desc.md <<'VIBAN_EOF'
|
|
67
43
|
## Symptoms
|
|
68
|
-
{
|
|
69
|
-
{additional context
|
|
44
|
+
{one-sentence symptom}
|
|
45
|
+
{additional context, if any}
|
|
70
46
|
VIBAN_EOF
|
|
71
47
|
|
|
72
48
|
# Auto numbering (default)
|
|
73
49
|
viban add "{title}" --desc-file /tmp/viban-desc.md --priority {priority} --type {type}
|
|
74
50
|
|
|
75
|
-
# Manual numbering (when workflow specifies
|
|
51
|
+
# Manual numbering (when workflow specifies)
|
|
76
52
|
viban add "{title}" --desc-file /tmp/viban-desc.md --priority {priority} --type {type} --ext-id "{external_id}"
|
|
77
53
|
```
|
|
78
54
|
|
|
79
|
-
|
|
55
|
+
Use `<<'VIBAN_EOF'` (quoted) to prevent shell interpretation.
|
|
80
56
|
|
|
81
57
|
## Step 5: Report
|
|
82
58
|
|
|
@@ -87,9 +63,38 @@ Issue #{id} registered
|
|
|
87
63
|
Status: backlog
|
|
88
64
|
```
|
|
89
65
|
|
|
90
|
-
##
|
|
66
|
+
## Step 6: Suggest Plan Mode
|
|
67
|
+
|
|
68
|
+
**Skip** for trivial issues (typo, one-liner config, simple copy edit).
|
|
69
|
+
**Recommend** for everything else. Use AskUserQuestion:
|
|
70
|
+
|
|
71
|
+
- header: "Next step", question: "Want to start planning the solution now?"
|
|
72
|
+
- options:
|
|
73
|
+
- "Plan now (Recommended)" — Enter plan mode to analyze and design a solution
|
|
74
|
+
- "Later" — Just register, work on it later
|
|
75
|
+
|
|
76
|
+
**"Plan now"**: `EnterPlanMode` → after approval, save to `.viban/plans/{issue-id}.md`:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
mkdir -p .viban/plans
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
# Plan: {issue title}
|
|
84
|
+
> Issue #{id} | {priority} | {type} | Created: {timestamp}
|
|
85
|
+
|
|
86
|
+
{full plan content}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Report: `Plan saved to .viban/plans/{issue-id}.md — /viban:assign will auto-load it.`
|
|
90
|
+
|
|
91
|
+
**"Later"**: end skill.
|
|
92
|
+
|
|
93
|
+
> **Bias towards planning.** When in doubt, suggest plan mode.
|
|
94
|
+
|
|
95
|
+
## Rules
|
|
91
96
|
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
97
|
+
- No codebase exploration — assignee does that in `/viban:assign`
|
|
98
|
+
- No solution proposals — symptoms only
|
|
99
|
+
- Check duplicates first: `viban list`
|
|
100
|
+
- P0 is system-down only
|