claude-plugin-viban 1.3.13 → 1.3.14
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/bin/viban +31 -19
- package/commands/approve.md +15 -0
- package/commands/reject.md +16 -0
- package/commands/review.md +21 -0
- package/docs/CLAUDE.md +13 -10
- package/install.sh +14 -0
- package/package.json +1 -1
- package/scripts/_viban +117 -0
- package/skills/approve/SKILL.md +112 -0
- package/skills/assign/SKILL.md +25 -8
- package/skills/parallel-assign/SKILL.md +4 -16
- package/skills/reject/SKILL.md +82 -0
- package/skills/review/SKILL.md +148 -0
- package/skills/setup/SKILL.md +1 -1
package/bin/viban
CHANGED
|
@@ -118,15 +118,23 @@ case "$1" in
|
|
|
118
118
|
esac
|
|
119
119
|
|
|
120
120
|
IN_TUI=false
|
|
121
|
+
_CLEANUP_DONE=false
|
|
121
122
|
cleanup() {
|
|
123
|
+
# Guard: prevent double execution (INT/TERM fires cleanup, then exit 0 fires EXIT)
|
|
124
|
+
$_CLEANUP_DONE && return
|
|
125
|
+
_CLEANUP_DONE=true
|
|
122
126
|
# Skip cleanup in subshells — EXIT trap fires in $() command substitutions
|
|
123
127
|
[[ ${ZSH_SUBSHELL:-0} -gt 0 ]] && return
|
|
124
128
|
# Kill background sync if running
|
|
125
129
|
[[ -n "${_sync_pid:-}" ]] && kill "$_sync_pid" 2>/dev/null && wait "$_sync_pid" 2>/dev/null
|
|
130
|
+
# Release file lock if held
|
|
131
|
+
${_VIBAN_LOCK_HELD:-false} && rm -rf "${VIBAN_DATA_DIR}/.lock"
|
|
126
132
|
_stop_coproc
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
133
|
+
if $IN_TUI; then
|
|
134
|
+
printf '\033[?25h\033[0m'
|
|
135
|
+
stty echo 2>/dev/null
|
|
136
|
+
clear
|
|
137
|
+
fi
|
|
130
138
|
exit 0
|
|
131
139
|
}
|
|
132
140
|
trap cleanup INT TERM EXIT
|
|
@@ -209,27 +217,30 @@ source "$VIBAN_SCRIPT_DIR/lib/commands.zsh"
|
|
|
209
217
|
main() {
|
|
210
218
|
check_deps
|
|
211
219
|
init_json
|
|
220
|
+
# Auto-archive old done issues (skip when user explicitly runs archive)
|
|
221
|
+
[[ "${1:-}" != "archive" ]] && auto_archive
|
|
212
222
|
case "${1:-}" in
|
|
213
223
|
list) shift; cmd_list "$@";;
|
|
214
224
|
history) cmd_history;;
|
|
215
|
-
add) shift; cmd_add "$@";;
|
|
216
|
-
attach) shift; cmd_attach "$@";;
|
|
217
|
-
assign) cmd_assign "
|
|
218
|
-
review) cmd_review "
|
|
219
|
-
done) shift; cmd_done "$@";;
|
|
220
|
-
move) cmd_move "
|
|
225
|
+
add) shift; _with_lock cmd_add "$@";;
|
|
226
|
+
attach) shift; _with_lock cmd_attach "$@";;
|
|
227
|
+
assign) shift; _with_lock cmd_assign "$@";;
|
|
228
|
+
review) shift; _with_lock cmd_review "$@";;
|
|
229
|
+
done) shift; _with_lock cmd_done "$@";;
|
|
230
|
+
move) shift; _with_lock cmd_move "$@";;
|
|
221
231
|
get) cmd_get "$2";;
|
|
222
|
-
comment) shift; cmd_comment "$@";;
|
|
223
|
-
link) cmd_link "$2" "$3" "$4";;
|
|
224
|
-
unlink) shift; cmd_unlink "$@";;
|
|
225
|
-
edit) [[ -z "$2" ]] && { echo "Usage: viban edit <id>"; exit 1; }; edit_issue "$2";;
|
|
226
|
-
priority) cmd_priority "$2" "$3";;
|
|
232
|
+
comment) shift; _with_lock cmd_comment "$@";;
|
|
233
|
+
link) _with_lock cmd_link "$2" "$3" "$4";;
|
|
234
|
+
unlink) shift; _with_lock cmd_unlink "$@";;
|
|
235
|
+
edit) [[ -z "$2" ]] && { echo "Usage: viban edit <id>"; exit 1; }; _with_lock edit_issue "$2";;
|
|
236
|
+
priority) _with_lock cmd_priority "$2" "$3";;
|
|
227
237
|
stats) cmd_stats;;
|
|
228
|
-
backup) cmd_backup;;
|
|
229
|
-
restore) shift; cmd_restore "$@";;
|
|
238
|
+
backup) _with_lock cmd_backup;;
|
|
239
|
+
restore) shift; _with_lock cmd_restore "$@";;
|
|
230
240
|
changelog) cmd_changelog "$2";;
|
|
231
241
|
export) cmd_export "$2";;
|
|
232
|
-
migrate) cmd_migrate;;
|
|
242
|
+
migrate) _with_lock cmd_migrate;;
|
|
243
|
+
archive) shift; _with_lock cmd_archive "$@";;
|
|
233
244
|
sync) shift; cmd_sync "$@";;
|
|
234
245
|
--version|-v)
|
|
235
246
|
# Get version from package.json
|
|
@@ -260,8 +271,8 @@ main() {
|
|
|
260
271
|
echo " viban priority <id> <P0-P3> Set priority"
|
|
261
272
|
echo " viban assign Assign first backlog (by priority)"
|
|
262
273
|
echo " viban review → Human Review"
|
|
263
|
-
echo " viban move <id> <status>
|
|
264
|
-
echo " viban done <id> [--purge]
|
|
274
|
+
echo " viban move <id> <status> [--force] Move to status (done requires review; --force to bypass)"
|
|
275
|
+
echo " viban done <id> [--purge] [--force] Complete (requires review status; --force to bypass)"
|
|
265
276
|
echo " viban comment <id> \"msg\" Add comment to task"
|
|
266
277
|
echo " viban link <id> blocks <id> Add dependency"
|
|
267
278
|
echo " viban unlink <id> blocks <id> Remove dependency"
|
|
@@ -272,6 +283,7 @@ main() {
|
|
|
272
283
|
echo " viban restore [f] List or restore a backup"
|
|
273
284
|
echo " viban changelog [range] Generate changelog from commits"
|
|
274
285
|
echo " viban export [md|html] Export board as markdown or HTML"
|
|
286
|
+
echo " viban archive [--days N] Archive done issues older than N days (default 30)"
|
|
275
287
|
echo " viban migrate Migrate: extract type from title"
|
|
276
288
|
echo " viban sync Sync with external issue tracker (GitHub, etc.)"
|
|
277
289
|
echo " viban update Update to latest version (if available)"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Approve a reviewed issue — merge branch, cleanup, mark done"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `/viban:approve <id>` after reviewing an issue with `/viban:review`.
|
|
6
|
+
|
|
7
|
+
Usage: `/viban:approve <id>`
|
|
8
|
+
|
|
9
|
+
What it does:
|
|
10
|
+
1. Merges the issue branch (via PR squash-merge or local merge)
|
|
11
|
+
2. Cleans up worktree and branch
|
|
12
|
+
3. Marks the card as done
|
|
13
|
+
4. Restores any stashed changes from `/viban:review`
|
|
14
|
+
|
|
15
|
+
**IMPORTANT:** Never read or write `viban.json` directly — always use `viban` CLI commands.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Reject a reviewed issue — return to in_progress with feedback"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `/viban:reject <id> [feedback]` after reviewing an issue with `/viban:review`.
|
|
6
|
+
|
|
7
|
+
Usage: `/viban:reject <id> [feedback text]`
|
|
8
|
+
|
|
9
|
+
What it does:
|
|
10
|
+
1. Moves the card back to in_progress (worktree stays intact)
|
|
11
|
+
2. Records feedback as a comment on the issue (and PR if exists)
|
|
12
|
+
3. Restores any stashed changes from `/viban:review`
|
|
13
|
+
|
|
14
|
+
The agent can then pick the issue back up and address the feedback.
|
|
15
|
+
|
|
16
|
+
**IMPORTANT:** Never read or write `viban.json` directly — always use `viban` CLI commands.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Checkout a review issue's branch for IDE review"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run `/viban:review` to checkout a review-status issue's branch for IDE review.
|
|
6
|
+
|
|
7
|
+
Usage: `/viban:review [id]`
|
|
8
|
+
|
|
9
|
+
- `id`: (optional) specific issue ID. If omitted, picks the first review card.
|
|
10
|
+
|
|
11
|
+
What it does:
|
|
12
|
+
1. Detects review mode (PR / branch / main-direct)
|
|
13
|
+
2. Stashes local changes if needed
|
|
14
|
+
3. Checks out the branch via detached HEAD (worktree stays intact)
|
|
15
|
+
4. Shows diff summary
|
|
16
|
+
|
|
17
|
+
After reviewing in your IDE, run:
|
|
18
|
+
- `/viban:approve <id>` — merge and mark done
|
|
19
|
+
- `/viban:reject <id> [feedback]` — back to in_progress with feedback
|
|
20
|
+
|
|
21
|
+
**IMPORTANT:** Never read or write `viban.json` directly — always use `viban` CLI commands.
|
package/docs/CLAUDE.md
CHANGED
|
@@ -57,27 +57,30 @@ EOF
|
|
|
57
57
|
|
|
58
58
|
## Workflow Rules
|
|
59
59
|
|
|
60
|
-
###
|
|
61
|
-
-
|
|
62
|
-
-
|
|
60
|
+
### Worktree-Based Workflow
|
|
61
|
+
- 모든 이슈 작업은 `.viban/worktrees/{ID}` 에서 격리된 워크트리로 수행
|
|
62
|
+
- 메인 워크트리는 사용자 작업용으로 깨끗하게 유지
|
|
63
63
|
- 브랜치 네이밍: `issue-{ISSUE_ID}` (예: `issue-78`)
|
|
64
64
|
|
|
65
|
-
### Branch-Based Workflow
|
|
66
65
|
```bash
|
|
67
|
-
# 1.
|
|
68
|
-
git
|
|
69
|
-
git
|
|
66
|
+
# 1. 워크트리 생성
|
|
67
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
68
|
+
git worktree add -b issue-{ISSUE_ID} "$REPO_ROOT/.viban/worktrees/{ISSUE_ID}" origin/main
|
|
70
69
|
|
|
71
|
-
# 2. 작업 후 push
|
|
70
|
+
# 2. 워크트리 안에서 작업 후 push
|
|
71
|
+
cd "$REPO_ROOT/.viban/worktrees/{ISSUE_ID}"
|
|
72
72
|
git push -u origin issue-{ISSUE_ID}
|
|
73
73
|
|
|
74
74
|
# 3. PR 생성
|
|
75
75
|
gh pr create --title "..." --body "..."
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
- 워크트리는 `/viban:approve`가 merge 후 정리
|
|
79
|
+
- `/viban:reject` 시 워크트리 유지 (재작업용)
|
|
80
|
+
|
|
78
81
|
### Base Branch Sync
|
|
79
|
-
- Before
|
|
80
|
-
- Before PR push: `git fetch origin main && git rebase origin/main`
|
|
82
|
+
- Before worktree creation: `git fetch origin main`
|
|
83
|
+
- Before PR push: `git fetch origin main && git rebase origin/main` (inside worktree)
|
|
81
84
|
- Resolve conflicts if any before pushing
|
|
82
85
|
|
|
83
86
|
## Shell Script Rules
|
package/install.sh
CHANGED
|
@@ -169,6 +169,20 @@ npm install -g claude-plugin-viban
|
|
|
169
169
|
echo ""
|
|
170
170
|
echo -e "${GREEN}✓${NC} viban installed globally"
|
|
171
171
|
|
|
172
|
+
# Install zsh completion
|
|
173
|
+
VIBAN_COMP_SRC="$(npm root -g)/claude-plugin-viban/scripts/_viban"
|
|
174
|
+
if [[ -f "$VIBAN_COMP_SRC" ]]; then
|
|
175
|
+
COMP_DIR="${HOME}/.zsh/completions"
|
|
176
|
+
mkdir -p "$COMP_DIR"
|
|
177
|
+
cp "$VIBAN_COMP_SRC" "$COMP_DIR/_viban"
|
|
178
|
+
if ! grep -q 'fpath.*\.zsh/completions' "${HOME}/.zshrc" 2>/dev/null; then
|
|
179
|
+
# shellcheck disable=SC2016
|
|
180
|
+
echo 'fpath=(~/.zsh/completions $fpath)' >> "${HOME}/.zshrc"
|
|
181
|
+
echo 'autoload -Uz compinit && compinit' >> "${HOME}/.zshrc"
|
|
182
|
+
fi
|
|
183
|
+
echo -e "${GREEN}✓${NC} zsh completion installed (restart shell to activate)"
|
|
184
|
+
fi
|
|
185
|
+
|
|
172
186
|
# Register Claude Code plugin
|
|
173
187
|
echo ""
|
|
174
188
|
echo -e "${BOLD}Registering Claude Code plugin...${NC}"
|
package/package.json
CHANGED
package/scripts/_viban
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#compdef viban
|
|
2
|
+
# zsh completion for viban - Kanban board CLI
|
|
3
|
+
|
|
4
|
+
_viban_issue_ids() {
|
|
5
|
+
local -a ids
|
|
6
|
+
if [[ -f "${VIBAN_DATA_DIR:-${PWD}/.viban}/viban.json" ]]; then
|
|
7
|
+
local json="${VIBAN_DATA_DIR:-${PWD}/.viban}/viban.json"
|
|
8
|
+
ids=(${(f)"$(jq -r '.issues[] | select(.status != "done") | "#\(.id) [\(.priority)] \(.title)"' "$json" 2>/dev/null)"})
|
|
9
|
+
_describe 'issue' ids
|
|
10
|
+
fi
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
_viban() {
|
|
14
|
+
local -a commands=(
|
|
15
|
+
'list:Show board'
|
|
16
|
+
'history:Show completed issues'
|
|
17
|
+
'add:Add task'
|
|
18
|
+
'attach:Attach files to task'
|
|
19
|
+
'assign:Assign first backlog issue'
|
|
20
|
+
'review:Move to review'
|
|
21
|
+
'done:Complete task'
|
|
22
|
+
'move:Move to status'
|
|
23
|
+
'get:Get task details'
|
|
24
|
+
'comment:Add comment'
|
|
25
|
+
'link:Add dependency'
|
|
26
|
+
'unlink:Remove dependency'
|
|
27
|
+
'edit:Edit task in editor'
|
|
28
|
+
'priority:Set priority'
|
|
29
|
+
'stats:Show statistics'
|
|
30
|
+
'archive:Archive old done issues'
|
|
31
|
+
'backup:Snapshot viban.json'
|
|
32
|
+
'restore:Restore a backup'
|
|
33
|
+
'changelog:Generate changelog'
|
|
34
|
+
'export:Export board'
|
|
35
|
+
'migrate:Migrate data'
|
|
36
|
+
'sync:Sync with GitHub'
|
|
37
|
+
'update:Update to latest version'
|
|
38
|
+
'help:Show help'
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
local -a statuses=('backlog' 'in_progress' 'review' 'done')
|
|
42
|
+
local -a priorities=('P0:Critical' 'P1:High' 'P2:Medium' 'P3:Low')
|
|
43
|
+
local -a types=('bug' 'feat' 'chore' 'refactor')
|
|
44
|
+
|
|
45
|
+
if (( CURRENT == 2 )); then
|
|
46
|
+
_describe 'command' commands
|
|
47
|
+
return
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
case "${words[2]}" in
|
|
51
|
+
done|get|edit|review|comment|attach|priority)
|
|
52
|
+
if (( CURRENT == 3 )); then
|
|
53
|
+
_viban_issue_ids
|
|
54
|
+
fi
|
|
55
|
+
;;
|
|
56
|
+
move)
|
|
57
|
+
if (( CURRENT == 3 )); then
|
|
58
|
+
_viban_issue_ids
|
|
59
|
+
elif (( CURRENT == 4 )); then
|
|
60
|
+
_describe 'status' statuses
|
|
61
|
+
fi
|
|
62
|
+
;;
|
|
63
|
+
link|unlink)
|
|
64
|
+
if (( CURRENT == 3 )); then
|
|
65
|
+
_viban_issue_ids
|
|
66
|
+
elif (( CURRENT == 4 )); then
|
|
67
|
+
local -a rels=('blocks')
|
|
68
|
+
_describe 'relation' rels
|
|
69
|
+
elif (( CURRENT == 5 )); then
|
|
70
|
+
_viban_issue_ids
|
|
71
|
+
fi
|
|
72
|
+
;;
|
|
73
|
+
priority)
|
|
74
|
+
if (( CURRENT == 3 )); then
|
|
75
|
+
_viban_issue_ids
|
|
76
|
+
elif (( CURRENT == 4 )); then
|
|
77
|
+
_describe 'priority' priorities
|
|
78
|
+
fi
|
|
79
|
+
;;
|
|
80
|
+
list)
|
|
81
|
+
_arguments \
|
|
82
|
+
'--status[Filter by status]:status:(backlog in_progress review done)' \
|
|
83
|
+
'--priority[Filter by priority]:priority:(P0 P1 P2 P3)' \
|
|
84
|
+
'--type[Filter by type]:type:(bug feat chore refactor)' \
|
|
85
|
+
'--search[Search text]:text:'
|
|
86
|
+
;;
|
|
87
|
+
export)
|
|
88
|
+
if (( CURRENT == 3 )); then
|
|
89
|
+
local -a formats=('md:Markdown' 'html:HTML')
|
|
90
|
+
_describe 'format' formats
|
|
91
|
+
fi
|
|
92
|
+
;;
|
|
93
|
+
add)
|
|
94
|
+
_arguments \
|
|
95
|
+
'--parent[Parent issue ID]:id:_viban_issue_ids' \
|
|
96
|
+
'--type[Issue type]:type:(bug feat chore refactor)' \
|
|
97
|
+
'--priority[Priority]:priority:(P0 P1 P2 P3)' \
|
|
98
|
+
'--desc[Description]:text:'
|
|
99
|
+
;;
|
|
100
|
+
archive)
|
|
101
|
+
_arguments \
|
|
102
|
+
'--days[Days threshold]:days:' \
|
|
103
|
+
'--dry-run[Preview changes]'
|
|
104
|
+
;;
|
|
105
|
+
sync)
|
|
106
|
+
_arguments \
|
|
107
|
+
'--init[Initialize sync]' \
|
|
108
|
+
'--dry-run[Preview changes]' \
|
|
109
|
+
'--push-new[Push local issues]' \
|
|
110
|
+
'--pull-only[Pull only]' \
|
|
111
|
+
'--push-only[Push only]' \
|
|
112
|
+
'--auto[Silent auto-sync]'
|
|
113
|
+
;;
|
|
114
|
+
esac
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
_viban "$@"
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: approve
|
|
3
|
+
description: "Approve a reviewed issue — merge branch, cleanup worktree, mark done"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /approve
|
|
7
|
+
|
|
8
|
+
Approve a review-status issue after IDE review. Merges the branch, cleans up the worktree, and marks the card done.
|
|
9
|
+
|
|
10
|
+
> **CLI only** (no direct viban.json access)
|
|
11
|
+
|
|
12
|
+
**Input**: `$ARGUMENTS` (required: issue ID)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Output Rules
|
|
17
|
+
|
|
18
|
+
- **Do NOT output any preamble.**
|
|
19
|
+
- Start executing Step 1 immediately.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 1: Validate
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
viban get $ID
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Confirm the issue is in `review` status. If not, tell the user and exit.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
33
|
+
BRANCH="issue-$ID"
|
|
34
|
+
PREV_BRANCH=$(git branch --show-current)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If `$PREV_BRANCH` is empty (detached HEAD from `/viban:review`), determine the main branch:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
PREV_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
|
|
41
|
+
[ -z "$PREV_BRANCH" ] && PREV_BRANCH="main"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Step 2: Return to main branch
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
git checkout "$PREV_BRANCH"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Step 3: Merge
|
|
55
|
+
|
|
56
|
+
### If PR exists
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
PR_NUM=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If PR found:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
gh pr merge "$PR_NUM" --squash --delete-branch
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Clean up worktree if it still exists:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
WT_DIR="$REPO_ROOT/.viban/worktrees/$ID"
|
|
72
|
+
[ -d "$WT_DIR" ] && git worktree remove "$WT_DIR" --force 2>/dev/null
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### If no PR (branch only)
|
|
76
|
+
|
|
77
|
+
Remove worktree to free the branch:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
WT_DIR="$REPO_ROOT/.viban/worktrees/$ID"
|
|
81
|
+
[ -d "$WT_DIR" ] && git worktree remove "$WT_DIR" --force 2>/dev/null
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Merge locally:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
git merge "$BRANCH" --no-ff -m "Merge issue-$ID: <title>"
|
|
88
|
+
git branch -d "$BRANCH"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If merge conflicts: help user resolve.
|
|
92
|
+
|
|
93
|
+
### If no branch (main-direct work)
|
|
94
|
+
|
|
95
|
+
Nothing to merge. Proceed to Step 4.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Step 4: Complete
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
viban done $ID
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Restore stash if one was created during `/viban:review`:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
STASH=$(git stash list | grep "viban-review: before reviewing #$ID" | head -1 | cut -d: -f1)
|
|
109
|
+
[ -n "$STASH" ] && git stash pop "$STASH"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Report: "Issue #$ID approved and merged."
|
package/skills/assign/SKILL.md
CHANGED
|
@@ -59,32 +59,46 @@ Assess whether the issue description provides enough context to start working.
|
|
|
59
59
|
- **Clear** → **proceed directly to Step 4. Do NOT ask the user for confirmation. Do NOT ask "should I start?". Just start.**
|
|
60
60
|
- **Unclear** → interview the user with AskUserQuestion to gather missing context, then proceed to Step 4 immediately.
|
|
61
61
|
|
|
62
|
-
## Step 4:
|
|
62
|
+
## Step 4: Locate Worktree
|
|
63
|
+
|
|
64
|
+
`viban assign` automatically creates a worktree. Locate it:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
68
|
+
WT_DIR="$REPO_ROOT/.viban/worktrees/$ISSUE_ID"
|
|
69
|
+
BRANCH="issue-$ISSUE_ID"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**All subsequent work MUST happen inside `$WT_DIR`.**
|
|
73
|
+
|
|
74
|
+
## Step 5: Execute Workflow
|
|
63
75
|
|
|
64
76
|
Follow the workflow from Step 0. If no workflow was found, use this default pipeline:
|
|
65
77
|
|
|
66
|
-
###
|
|
78
|
+
### 5.1 Analyze
|
|
67
79
|
- Explore the codebase to understand the issue
|
|
68
80
|
- Identify root cause and scope of change
|
|
69
81
|
|
|
70
|
-
###
|
|
71
|
-
-
|
|
82
|
+
### 5.2 Implement
|
|
83
|
+
- Work inside the worktree: `cd $WT_DIR`
|
|
72
84
|
- Make the fix/feature changes
|
|
73
85
|
- Write or update tests as appropriate
|
|
74
86
|
|
|
75
|
-
###
|
|
76
|
-
- Run build and tests to confirm the fix works
|
|
87
|
+
### 5.3 Verify
|
|
88
|
+
- Run build and tests inside the worktree to confirm the fix works
|
|
77
89
|
- Verify no regressions
|
|
78
90
|
|
|
79
|
-
###
|
|
91
|
+
### 5.4 Ship (MANDATORY — execute ALL 4 commands in sequence)
|
|
80
92
|
|
|
81
93
|
```bash
|
|
94
|
+
cd $WT_DIR
|
|
95
|
+
|
|
82
96
|
# 1. Commit
|
|
83
97
|
git add -A
|
|
84
98
|
git commit -m "fix: {description} (#$ISSUE_ID)"
|
|
85
99
|
|
|
86
100
|
# 2. Push
|
|
87
|
-
git push -u origin
|
|
101
|
+
git push -u origin $BRANCH
|
|
88
102
|
|
|
89
103
|
# 3. Create PR (REQUIRED — do NOT skip)
|
|
90
104
|
gh pr create --title "fix: {description}" --body "Resolves #$ISSUE_ID
|
|
@@ -100,17 +114,20 @@ viban review $ISSUE_ID
|
|
|
100
114
|
```
|
|
101
115
|
|
|
102
116
|
**If any command fails**: fix the error and retry. Do NOT skip any step.
|
|
117
|
+
**Do NOT remove the worktree** — it stays for the review/approve/reject flow.
|
|
103
118
|
|
|
104
119
|
### Completion Checklist (ALL must be true before you stop)
|
|
105
120
|
|
|
106
121
|
- [ ] PR created (you have a PR URL)
|
|
107
122
|
- [ ] `viban review` called (issue status is "review")
|
|
123
|
+
- [ ] Worktree preserved at `.viban/worktrees/$ISSUE_ID`
|
|
108
124
|
- [ ] Completion message includes PR URL
|
|
109
125
|
|
|
110
126
|
```
|
|
111
127
|
Issue #{id} resolved → review
|
|
112
128
|
Title: {title}
|
|
113
129
|
PR: {pr_url}
|
|
130
|
+
Worktree: .viban/worktrees/{id}
|
|
114
131
|
```
|
|
115
132
|
|
|
116
133
|
**If you don't have a PR URL or haven't called `viban review`, you are NOT done. Go back and do it.**
|
|
@@ -190,19 +190,7 @@ REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
|
190
190
|
cd "$REPO_ROOT"
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
-
### 3.1
|
|
194
|
-
|
|
195
|
-
Worktree removal does NOT delete the branch or its commits — they remain in the local repo.
|
|
196
|
-
|
|
197
|
-
```bash
|
|
198
|
-
for entry in "${ISSUES[@]}"; do
|
|
199
|
-
ID="${entry%%|*}"
|
|
200
|
-
WT_DIR="$REPO_ROOT/.viban/worktrees/$ID"
|
|
201
|
-
git worktree remove "$WT_DIR" --force
|
|
202
|
-
done
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### 3.2 Verify Local Branches
|
|
193
|
+
### 3.1 Verify Local Branches
|
|
206
194
|
|
|
207
195
|
Confirm each branch has commits from the agent:
|
|
208
196
|
|
|
@@ -215,7 +203,7 @@ done
|
|
|
215
203
|
|
|
216
204
|
If a branch has no new commits (agent failed), skip it and report.
|
|
217
205
|
|
|
218
|
-
### 3.
|
|
206
|
+
### 3.2 Push Branches & Create PRs
|
|
219
207
|
|
|
220
208
|
For each branch with commits, push from the main repo and create a PR:
|
|
221
209
|
|
|
@@ -237,7 +225,7 @@ for entry in "${ISSUES[@]}"; do
|
|
|
237
225
|
done
|
|
238
226
|
```
|
|
239
227
|
|
|
240
|
-
### 3.
|
|
228
|
+
### 3.3 Verify PRs Exist
|
|
241
229
|
|
|
242
230
|
```bash
|
|
243
231
|
for entry in "${ISSUES[@]}"; do
|
|
@@ -303,7 +291,7 @@ Worktrees cleaned up. All PRs ready for human review.
|
|
|
303
291
|
|
|
304
292
|
> 1. **NEVER read or write `viban.json` directly** — always use `viban` CLI commands. Direct JSON access causes race conditions and data corruption.
|
|
305
293
|
> 2. **NEVER exit with any issue still in `in_progress`.** For every assigned issue, ensure `viban review {ID}` has been called.
|
|
306
|
-
> 3. **
|
|
294
|
+
> 3. **Do NOT remove worktrees** after PRs are created. Worktrees stay at `.viban/worktrees/{ID}` for the review flow (`/viban:approve` cleans up).
|
|
307
295
|
|
|
308
296
|
## CLI Reference
|
|
309
297
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reject
|
|
3
|
+
description: "Reject a reviewed issue — return to in_progress with feedback"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /reject
|
|
7
|
+
|
|
8
|
+
Reject a review-status issue and move it back to in_progress. The worktree stays intact so the agent can address feedback.
|
|
9
|
+
|
|
10
|
+
> **CLI only** (no direct viban.json access)
|
|
11
|
+
|
|
12
|
+
**Input**: `$ARGUMENTS` (required: issue ID, optional: feedback text)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Output Rules
|
|
17
|
+
|
|
18
|
+
- **Do NOT output any preamble.**
|
|
19
|
+
- Start executing Step 1 immediately.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 1: Validate
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
viban get $ID
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Confirm the issue is in `review` status. If not, tell the user and exit.
|
|
30
|
+
|
|
31
|
+
Parse `$ARGUMENTS`: first token is `$ID`, rest is `$FEEDBACK`.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Step 2: Return to main branch
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
PREV_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@')
|
|
39
|
+
[ -z "$PREV_BRANCH" ] && PREV_BRANCH="main"
|
|
40
|
+
git checkout "$PREV_BRANCH"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Step 3: Move back to in_progress
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
viban move $ID in_progress
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Step 4: Record feedback
|
|
54
|
+
|
|
55
|
+
If `$FEEDBACK` is provided:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
viban comment $ID "$FEEDBACK"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Also comment on PR if one exists:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
BRANCH="issue-$ID"
|
|
65
|
+
PR_NUM=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null)
|
|
66
|
+
[ -n "$PR_NUM" ] && gh pr comment "$PR_NUM" --body "$FEEDBACK"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
If no feedback provided, ask the user: "Any feedback for the developer?"
|
|
70
|
+
- If provided → store as comment
|
|
71
|
+
- If none → skip
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Step 5: Restore stash
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
STASH=$(git stash list | grep "viban-review: before reviewing #$ID" | head -1 | cut -d: -f1)
|
|
79
|
+
[ -n "$STASH" ] && git stash pop "$STASH"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Report: "Issue #$ID rejected and moved to in_progress. Worktree is intact for the agent to continue."
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review
|
|
3
|
+
description: "Checkout a review issue's branch for IDE review"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /review
|
|
7
|
+
|
|
8
|
+
Checkout a review-status issue's branch into the main working directory so the user can review changes in their IDE.
|
|
9
|
+
|
|
10
|
+
> **CLI only** (no direct viban.json access)
|
|
11
|
+
|
|
12
|
+
**Input**: `$ARGUMENTS` (optional: issue ID)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Output Rules
|
|
17
|
+
|
|
18
|
+
- **Do NOT output any preamble.** No "Your Task:", "I'll now...", "Let me...", or task summaries before starting work.
|
|
19
|
+
- Start executing Step 1 immediately and silently.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Step 1: Find Review Card
|
|
24
|
+
|
|
25
|
+
If `$ARGUMENTS` contains an issue ID, use it. Otherwise find the first review card:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
viban list --status review
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
If no review cards exist, tell the user and exit.
|
|
32
|
+
|
|
33
|
+
Extract the issue ID. Store as `$ID`.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
viban get $ID
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Show the user a one-line summary: `#ID [PRIORITY] Title`.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Step 2: Detect Review Mode
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
REPO_ROOT=$(git rev-parse --show-toplevel)
|
|
47
|
+
BRANCH="issue-$ID"
|
|
48
|
+
WT_DIR="$REPO_ROOT/.viban/worktrees/$ID"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Check in priority order — first match wins:
|
|
52
|
+
|
|
53
|
+
### Mode W: Worktree exists
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
[ -d "$WT_DIR" ]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If worktree exists → **Worktree mode**.
|
|
60
|
+
|
|
61
|
+
### Mode A: PR exists (no worktree)
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
gh pr list --head "$BRANCH" --json number,url --jq '.[0]' 2>/dev/null
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
If PR found → **PR mode**.
|
|
68
|
+
|
|
69
|
+
### Mode B: Branch exists (no PR, no worktree)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git rev-parse --verify "$BRANCH" 2>/dev/null
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
If branch exists → **Branch mode**.
|
|
76
|
+
|
|
77
|
+
### Mode C: No branch
|
|
78
|
+
|
|
79
|
+
No branch → **Commit mode**.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Step 3: Present for Review
|
|
84
|
+
|
|
85
|
+
### Mode W (worktree exists)
|
|
86
|
+
|
|
87
|
+
Show changes against main:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
git -C "$WT_DIR" log main.."$BRANCH" --oneline
|
|
91
|
+
git -C "$WT_DIR" diff main..."$BRANCH" --stat
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Check if PR exists:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
PR_INFO=$(gh pr list --head "$BRANCH" --json number,url --jq '.[0]' 2>/dev/null)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Mode A / B (no worktree, branch exists)
|
|
101
|
+
|
|
102
|
+
Stash if dirty:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
git status --porcelain
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
If dirty, ask user: "You have uncommitted changes. Stash them to proceed?"
|
|
109
|
+
- Yes → `git stash push -m "viban-review: before reviewing #$ID"`
|
|
110
|
+
- No → exit
|
|
111
|
+
|
|
112
|
+
Detached HEAD checkout:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
PREV_BRANCH=$(git branch --show-current)
|
|
116
|
+
git checkout --detach "$BRANCH"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Show changes:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
git log "$PREV_BRANCH".."$BRANCH" --oneline
|
|
123
|
+
git diff "$PREV_BRANCH"..."$BRANCH" --stat
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Mode C (no branch)
|
|
127
|
+
|
|
128
|
+
Show recent commits:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git log --oneline -10
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Step 4: Report and Exit
|
|
137
|
+
|
|
138
|
+
Tell the user:
|
|
139
|
+
|
|
140
|
+
**Mode W**: "Issue #$ID worktree is at `$WT_DIR`. Open it in your IDE to review. {PR #N link if PR exists.} Run `/viban:approve $ID` or `/viban:reject $ID` when ready."
|
|
141
|
+
|
|
142
|
+
**Mode A**: "PR #N for issue #$ID is checked out. Review in your IDE. Run `/viban:approve $ID` or `/viban:reject $ID` when ready."
|
|
143
|
+
|
|
144
|
+
**Mode B**: "Branch `issue-$ID` is checked out. Review in your IDE. Run `/viban:approve $ID` or `/viban:reject $ID` when ready."
|
|
145
|
+
|
|
146
|
+
**Mode C**: "Issue #$ID was worked on main directly. Run `/viban:approve $ID` or `/viban:reject $ID` when ready."
|
|
147
|
+
|
|
148
|
+
**Done.** Do not wait for user input. The skill exits here.
|
package/skills/setup/SKILL.md
CHANGED
|
@@ -415,7 +415,7 @@ If build/test fails: fix errors, return to Phase 3.
|
|
|
415
415
|
|
|
416
416
|
- Issue tracking: {FROM Q2: "Yes" = synced with external tracker via `viban sync`, "No — auto-number" = auto-increment (viban default), "No — manual IDs" = ask for external ID via `--ext-id` flag}
|
|
417
417
|
- Test evidence: include test output in PR body
|
|
418
|
-
- Post-merge:
|
|
418
|
+
- Post-merge: handled by `/viban:approve` (merges PR, runs `viban done {id}`, deletes branch)
|
|
419
419
|
|
|
420
420
|
---
|
|
421
421
|
|