revspec 0.2.2 → 0.4.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.
- package/CLAUDE.md +10 -2
- package/README.md +86 -29
- package/bin/revspec.ts +2 -1
- package/docs/superpowers/plans/2026-03-15-ui-refactor.md +1025 -0
- package/package.json +1 -1
- package/scripts/install-skill.sh +20 -0
- package/scripts/release.sh +5 -6
- package/skills/revspec/SKILL.md +137 -0
- package/src/protocol/live-events.ts +3 -2
- package/src/tui/app.ts +198 -310
- package/src/tui/comment-input.ts +145 -144
- package/src/tui/confirm.ts +29 -43
- package/src/tui/help.ts +33 -57
- package/src/tui/pager.ts +162 -82
- package/src/tui/search.ts +6 -6
- package/src/tui/status-bar.ts +77 -34
- package/src/tui/thread-list.ts +28 -54
- package/src/tui/ui/dialog.ts +106 -0
- package/src/tui/ui/hint-bar.ts +20 -0
- package/src/tui/ui/keybinds.ts +104 -0
- package/src/tui/ui/markdown.ts +251 -0
- package/src/tui/ui/theme.ts +49 -0
- package/test/tui/ui/keybinds.test.ts +71 -0
- package/src/tui/theme.ts +0 -34
package/package.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# Install/sync the revspec Claude Code skill to ~/.claude/skills/revspec/
|
|
5
|
+
# Run this after cloning the repo or pulling updates.
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
REPO_SKILL="$SCRIPT_DIR/../skills/revspec"
|
|
9
|
+
LOCAL_SKILL="$HOME/.claude/skills/revspec"
|
|
10
|
+
|
|
11
|
+
if [ ! -f "$REPO_SKILL/SKILL.md" ]; then
|
|
12
|
+
echo "Error: skill not found at $REPO_SKILL/SKILL.md"
|
|
13
|
+
exit 1
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
mkdir -p "$LOCAL_SKILL"
|
|
17
|
+
cp "$REPO_SKILL/SKILL.md" "$LOCAL_SKILL/SKILL.md"
|
|
18
|
+
|
|
19
|
+
echo "Installed revspec skill to $LOCAL_SKILL"
|
|
20
|
+
echo "Use /revspec in Claude Code to launch spec reviews."
|
package/scripts/release.sh
CHANGED
|
@@ -34,18 +34,17 @@ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
|
34
34
|
exit 0
|
|
35
35
|
fi
|
|
36
36
|
|
|
37
|
-
# Tag if
|
|
38
|
-
|
|
39
|
-
git tag "v$VERSION"
|
|
40
|
-
fi
|
|
37
|
+
# Tag current commit (force-update if tag exists)
|
|
38
|
+
git tag -f "v$VERSION"
|
|
41
39
|
|
|
42
40
|
# Publish to npm
|
|
43
41
|
echo ""
|
|
44
42
|
echo "Publishing to npm..."
|
|
45
43
|
npm publish
|
|
46
44
|
|
|
47
|
-
# Push
|
|
48
|
-
git push
|
|
45
|
+
# Push commit and tag (force-update remote tag if it exists)
|
|
46
|
+
git push
|
|
47
|
+
git push origin "v$VERSION" --force
|
|
49
48
|
|
|
50
49
|
echo ""
|
|
51
50
|
echo "Released v$VERSION"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: revspec
|
|
3
|
+
description: Launch revspec to review a spec document with real-time AI feedback. Use when the user says /revspec, "review the spec", "let me review this", or after generating a spec/design document that needs human review. Also use when a brainstorming or writing-plans skill produces a markdown spec file.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Revspec — Live Spec Review
|
|
7
|
+
|
|
8
|
+
Launch revspec to let the human review a spec document with real-time AI conversation. The reviewer comments on specific lines, you reply instantly, and the discussion continues until the spec is approved.
|
|
9
|
+
|
|
10
|
+
## When to Use
|
|
11
|
+
|
|
12
|
+
- After writing or updating a spec/design document
|
|
13
|
+
- When the user explicitly asks to review a spec
|
|
14
|
+
- After the brainstorming or writing-plans skill produces a `.md` file
|
|
15
|
+
|
|
16
|
+
## How It Works
|
|
17
|
+
|
|
18
|
+
You and the human communicate through revspec's CLI:
|
|
19
|
+
- `revspec watch <file.md>` — blocks until the reviewer adds comments, then returns them
|
|
20
|
+
- `revspec reply <file.md> <threadId> "<text>"` — sends your reply (appears in the TUI instantly)
|
|
21
|
+
|
|
22
|
+
The reviewer stays in the revspec TUI for the entire session. You run the watch/reply loop.
|
|
23
|
+
|
|
24
|
+
## Step 1: Find the Spec File
|
|
25
|
+
|
|
26
|
+
Detect which spec was recently created or modified in this conversation. Look for:
|
|
27
|
+
- Files written to `docs/superpowers/specs/*.md`
|
|
28
|
+
- The last `.md` file you created or edited
|
|
29
|
+
- If ambiguous, ask the user which file to review
|
|
30
|
+
|
|
31
|
+
## Step 2: Launch Revspec
|
|
32
|
+
|
|
33
|
+
Check if running inside tmux:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
echo $TMUX
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**If tmux is available:**
|
|
40
|
+
```bash
|
|
41
|
+
tmux split-window -v "revspec <spec-file>"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**If no tmux:**
|
|
45
|
+
Tell the user: "Please run in another terminal: `revspec <spec-file>`"
|
|
46
|
+
|
|
47
|
+
## Step 3: Run the Watch/Reply Loop
|
|
48
|
+
|
|
49
|
+
Start watching for reviewer comments:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
revspec watch <spec-file>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This blocks until the reviewer adds comments. When it returns, you'll see output like:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
--- New threads ---
|
|
59
|
+
|
|
60
|
+
[t1] line 14 (new):
|
|
61
|
+
Context:
|
|
62
|
+
12: The system uses polling...
|
|
63
|
+
>14: it sends a notification via webhook.
|
|
64
|
+
16: resource state.
|
|
65
|
+
Comment: "this is unclear"
|
|
66
|
+
|
|
67
|
+
To reply: revspec reply spec.md <threadId> "<your response>"
|
|
68
|
+
When done replying, run: revspec watch spec.md
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**For each comment:** Read the context, understand the concern, and reply thoughtfully:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
revspec reply <spec-file> t1 "Good point. I'll clarify — it uses polling to detect changes, then sends a webhook notification to downstream services."
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
After replying to all comments, run `revspec watch` again to wait for the next batch.
|
|
78
|
+
|
|
79
|
+
**If watch returns "Session ended. Reviewer exited revspec."** — the reviewer closed the TUI. Check the review JSON for resolved threads that require spec changes (see Step 4). If no resolved threads, stop and wait — the user can invoke `/revspec` again later to resume.
|
|
80
|
+
|
|
81
|
+
**Important:** Your replies should be substantive — address the concern, explain your reasoning, or acknowledge the change you'll make. Don't just say "noted" or "will fix."
|
|
82
|
+
|
|
83
|
+
## Step 4: Handle Session End or Approval
|
|
84
|
+
|
|
85
|
+
The watch loop ends in one of two ways:
|
|
86
|
+
|
|
87
|
+
### Session ended (reviewer exited with `:q`)
|
|
88
|
+
|
|
89
|
+
Read the review JSON and check for **resolved threads**. Resolved = the reviewer acknowledged your reply and wants you to make that change.
|
|
90
|
+
|
|
91
|
+
**If resolved threads with actionable feedback exist:**
|
|
92
|
+
1. Rewrite the spec incorporating the feedback from resolved threads
|
|
93
|
+
2. Commit the updated spec
|
|
94
|
+
3. Append a round marker to the JSONL:
|
|
95
|
+
```bash
|
|
96
|
+
echo '{"type":"round","author":"owner","round":2,"ts":'$(date +%s000)'}' >> <spec-file>.review.live.jsonl
|
|
97
|
+
```
|
|
98
|
+
4. Launch a new revspec session (go back to Step 2) so the reviewer can verify the changes
|
|
99
|
+
|
|
100
|
+
**If no resolved threads (or only open/pending threads):**
|
|
101
|
+
The reviewer left without resolving anything — stop and wait. The user can invoke `/revspec` again later.
|
|
102
|
+
|
|
103
|
+
### Approved (reviewer pressed `a`)
|
|
104
|
+
|
|
105
|
+
Watch returns:
|
|
106
|
+
```
|
|
107
|
+
Review approved.
|
|
108
|
+
Review file: <path-to-review.json>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The spec is finalized. Report: "Spec approved and finalized at `<spec-file>`. Ready to proceed with implementation."
|
|
112
|
+
|
|
113
|
+
## Thread Status Meanings
|
|
114
|
+
|
|
115
|
+
- **Open** — under discussion, AI replied, reviewer hasn't responded yet
|
|
116
|
+
- **Pending** — owner replied, waiting for reviewer to read
|
|
117
|
+
- **Resolved** — reviewer acknowledged the plan, AI should make the change
|
|
118
|
+
- **Approve** — spec is final, proceed to implementation
|
|
119
|
+
|
|
120
|
+
## Loop Summary
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
1. Launch revspec on spec file
|
|
124
|
+
2. Watch for comments
|
|
125
|
+
3. Reply to each comment
|
|
126
|
+
4. Watch again (repeat 2-3 until session-end or approval)
|
|
127
|
+
5. On session-end: check for resolved threads
|
|
128
|
+
6. If resolved threads need spec changes: rewrite spec, launch new round (go to 1)
|
|
129
|
+
7. On approval: spec is finalized, done
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Tips
|
|
133
|
+
|
|
134
|
+
- Read the full thread history in the watch output before replying — the reviewer may have added context across multiple messages
|
|
135
|
+
- When rewriting the spec after approval, address every resolved thread — the reviewer trusted you to incorporate their feedback
|
|
136
|
+
- Keep replies concise but complete — the reviewer can see them instantly and will follow up if needed
|
|
137
|
+
- If a comment is about a section you're unsure about, say so honestly — "I'm not sure about the best approach here. Options are X or Y — which do you prefer?"
|
|
@@ -29,6 +29,7 @@ const VALID_LIVE_EVENT_TYPES: readonly LiveEventType[] = [
|
|
|
29
29
|
"approve",
|
|
30
30
|
"delete",
|
|
31
31
|
"round",
|
|
32
|
+
"session-end",
|
|
32
33
|
];
|
|
33
34
|
|
|
34
35
|
export function isValidLiveEvent(value: unknown): value is LiveEvent {
|
|
@@ -47,8 +48,8 @@ export function isValidLiveEvent(value: unknown): value is LiveEvent {
|
|
|
47
48
|
if (typeof v.ts !== "number") return false;
|
|
48
49
|
if (typeof v.author !== "string") return false;
|
|
49
50
|
|
|
50
|
-
// threadId required for all except approve and
|
|
51
|
-
if (v.type !== "approve" && v.type !== "round") {
|
|
51
|
+
// threadId required for all except approve, round, and session-end
|
|
52
|
+
if (v.type !== "approve" && v.type !== "round" && v.type !== "session-end") {
|
|
52
53
|
if (typeof v.threadId !== "string") return false;
|
|
53
54
|
}
|
|
54
55
|
|