@qwen-code/qwen-code 0.14.2 → 0.14.3
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/bundled/qc-helper/docs/configuration/settings.md +5 -3
- package/bundled/qc-helper/docs/features/_meta.ts +2 -0
- package/bundled/qc-helper/docs/features/code-review.md +279 -0
- package/bundled/qc-helper/docs/features/commands.md +33 -20
- package/bundled/qc-helper/docs/features/followup-suggestions.md +6 -6
- package/bundled/qc-helper/docs/features/status-line.md +235 -0
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
- package/bundled/review/DESIGN.md +165 -0
- package/bundled/review/SKILL.md +358 -88
- package/cli.js +39861 -39268
- package/locales/de.js +11 -6
- package/locales/en.js +11 -5
- package/locales/ja.js +11 -6
- package/locales/pt.js +11 -6
- package/locales/ru.js +11 -6
- package/locales/zh.js +12 -5
- package/package.json +2 -2
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Status Line
|
|
2
|
+
|
|
3
|
+
> Display custom information in the footer using a shell command.
|
|
4
|
+
|
|
5
|
+
The status line lets you run a shell command whose output is displayed in the footer's left section. The command receives structured JSON context via stdin, so it can show session-aware information like the current model, token usage, git branch, or anything else you can script.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
With status line (default approval mode — 1 row):
|
|
9
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
10
|
+
│ user@host ~/project (main) ctx:34% 🔒 docker | Debug | 67% │ ← status line
|
|
11
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
12
|
+
|
|
13
|
+
With status line + non-default mode (2 rows):
|
|
14
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
15
|
+
│ user@host ~/project (main) ctx:34% 🔒 docker | Debug | 67% │ ← status line
|
|
16
|
+
│ auto-accept edits (shift + tab to cycle) │ ← mode indicator
|
|
17
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
When configured, the status line replaces the default "? for shortcuts" hint. High-priority messages (Ctrl+C/D exit prompts, Esc, vim INSERT mode) temporarily override the status line. The status line text is truncated to fit within the available width.
|
|
21
|
+
|
|
22
|
+
## Prerequisites
|
|
23
|
+
|
|
24
|
+
- [`jq`](https://jqlang.github.io/jq/) is recommended for parsing the JSON input (install via `brew install jq`, `apt install jq`, etc.)
|
|
25
|
+
- Simple commands that don't need JSON data (e.g. `git branch --show-current`) work without `jq`
|
|
26
|
+
|
|
27
|
+
## Quick setup
|
|
28
|
+
|
|
29
|
+
The easiest way to configure a status line is the `/statusline` command. It launches a setup agent that reads your shell PS1 configuration and generates a matching status line:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
/statusline
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You can also give it specific instructions:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
/statusline show model name and context usage percentage
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Manual configuration
|
|
42
|
+
|
|
43
|
+
Add a `statusLine` object under the `ui` key in `~/.qwen/settings.json`:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"ui": {
|
|
48
|
+
"statusLine": {
|
|
49
|
+
"type": "command",
|
|
50
|
+
"command": "input=$(cat); model=$(echo \"$input\" | jq -r '.model.display_name'); pct=$(echo \"$input\" | jq -r '.context_window.used_percentage'); echo \"$model ctx:${pct}%\""
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
| Field | Type | Required | Description |
|
|
57
|
+
| --------- | ----------- | -------- | ------------------------------------------------------------------------------------- |
|
|
58
|
+
| `type` | `"command"` | Yes | Must be `"command"` |
|
|
59
|
+
| `command` | string | Yes | Shell command to execute. Receives JSON via stdin, first line of stdout is displayed. |
|
|
60
|
+
|
|
61
|
+
## JSON input
|
|
62
|
+
|
|
63
|
+
The command receives a JSON object via stdin with the following fields:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"session_id": "abc-123",
|
|
68
|
+
"version": "0.14.1",
|
|
69
|
+
"model": {
|
|
70
|
+
"display_name": "qwen-3-235b"
|
|
71
|
+
},
|
|
72
|
+
"context_window": {
|
|
73
|
+
"context_window_size": 131072,
|
|
74
|
+
"used_percentage": 34.3,
|
|
75
|
+
"remaining_percentage": 65.7,
|
|
76
|
+
"current_usage": 45000,
|
|
77
|
+
"total_input_tokens": 30000,
|
|
78
|
+
"total_output_tokens": 5000
|
|
79
|
+
},
|
|
80
|
+
"workspace": {
|
|
81
|
+
"current_dir": "/home/user/project"
|
|
82
|
+
},
|
|
83
|
+
"git": {
|
|
84
|
+
"branch": "main"
|
|
85
|
+
},
|
|
86
|
+
"metrics": {
|
|
87
|
+
"models": {
|
|
88
|
+
"qwen-3-235b": {
|
|
89
|
+
"api": {
|
|
90
|
+
"total_requests": 10,
|
|
91
|
+
"total_errors": 0,
|
|
92
|
+
"total_latency_ms": 5000
|
|
93
|
+
},
|
|
94
|
+
"tokens": {
|
|
95
|
+
"prompt": 30000,
|
|
96
|
+
"completion": 5000,
|
|
97
|
+
"total": 35000,
|
|
98
|
+
"cached": 10000,
|
|
99
|
+
"thoughts": 2000
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"files": {
|
|
104
|
+
"total_lines_added": 120,
|
|
105
|
+
"total_lines_removed": 30
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"vim": {
|
|
109
|
+
"mode": "INSERT"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
| Field | Type | Description |
|
|
115
|
+
| ------------------------------------- | ---------------- | ---------------------------------------------------------------------------------- |
|
|
116
|
+
| `session_id` | string | Unique session identifier |
|
|
117
|
+
| `version` | string | Qwen Code version |
|
|
118
|
+
| `model.display_name` | string | Current model name |
|
|
119
|
+
| `context_window.context_window_size` | number | Total context window size in tokens |
|
|
120
|
+
| `context_window.used_percentage` | number | Context window usage as percentage (0–100) |
|
|
121
|
+
| `context_window.remaining_percentage` | number | Context window remaining as percentage (0–100) |
|
|
122
|
+
| `context_window.current_usage` | number | Token count from the last API call (current context size) |
|
|
123
|
+
| `context_window.total_input_tokens` | number | Total input tokens consumed this session |
|
|
124
|
+
| `context_window.total_output_tokens` | number | Total output tokens consumed this session |
|
|
125
|
+
| `workspace.current_dir` | string | Current working directory |
|
|
126
|
+
| `git` | object \| absent | Present only inside a git repository. |
|
|
127
|
+
| `git.branch` | string | Current branch name |
|
|
128
|
+
| `metrics.models.<id>.api` | object | Per-model API stats: `total_requests`, `total_errors`, `total_latency_ms` |
|
|
129
|
+
| `metrics.models.<id>.tokens` | object | Per-model token usage: `prompt`, `completion`, `total`, `cached`, `thoughts` |
|
|
130
|
+
| `metrics.files` | object | File change stats: `total_lines_added`, `total_lines_removed` |
|
|
131
|
+
| `vim` | object \| absent | Present only when vim mode is enabled. Contains `mode` (`"INSERT"` or `"NORMAL"`). |
|
|
132
|
+
|
|
133
|
+
> **Important:** stdin can only be read once. Always store it in a variable first: `input=$(cat)`.
|
|
134
|
+
|
|
135
|
+
## Examples
|
|
136
|
+
|
|
137
|
+
### Model and token usage
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"ui": {
|
|
142
|
+
"statusLine": {
|
|
143
|
+
"type": "command",
|
|
144
|
+
"command": "input=$(cat); model=$(echo \"$input\" | jq -r '.model.display_name'); pct=$(echo \"$input\" | jq -r '.context_window.used_percentage'); echo \"$model ctx:${pct}%\""
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Output: `qwen-3-235b ctx:34%`
|
|
151
|
+
|
|
152
|
+
### Git branch + directory
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"ui": {
|
|
157
|
+
"statusLine": {
|
|
158
|
+
"type": "command",
|
|
159
|
+
"command": "input=$(cat); branch=$(echo \"$input\" | jq -r '.git.branch // empty'); dir=$(basename \"$(echo \"$input\" | jq -r '.workspace.current_dir')\"); echo \"$dir${branch:+ ($branch)}\""
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Output: `my-project (main)`
|
|
166
|
+
|
|
167
|
+
> Note: The `git.branch` field is provided directly in the JSON input — no need to shell out to `git`.
|
|
168
|
+
|
|
169
|
+
### File change stats
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"ui": {
|
|
174
|
+
"statusLine": {
|
|
175
|
+
"type": "command",
|
|
176
|
+
"command": "input=$(cat); added=$(echo \"$input\" | jq -r '.metrics.files.total_lines_added'); removed=$(echo \"$input\" | jq -r '.metrics.files.total_lines_removed'); echo \"+$added/-$removed lines\""
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Output: `+120/-30 lines`
|
|
183
|
+
|
|
184
|
+
### Script file for complex commands
|
|
185
|
+
|
|
186
|
+
For longer commands, save a script file at `~/.qwen/statusline-command.sh`:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
#!/bin/bash
|
|
190
|
+
input=$(cat)
|
|
191
|
+
model=$(echo "$input" | jq -r '.model.display_name')
|
|
192
|
+
pct=$(echo "$input" | jq -r '.context_window.used_percentage')
|
|
193
|
+
branch=$(echo "$input" | jq -r '.git.branch // empty')
|
|
194
|
+
added=$(echo "$input" | jq -r '.metrics.files.total_lines_added')
|
|
195
|
+
removed=$(echo "$input" | jq -r '.metrics.files.total_lines_removed')
|
|
196
|
+
|
|
197
|
+
parts=()
|
|
198
|
+
[ -n "$model" ] && parts+=("$model")
|
|
199
|
+
[ -n "$branch" ] && parts+=("($branch)")
|
|
200
|
+
[ "$pct" != "0" ] 2>/dev/null && parts+=("ctx:${pct}%")
|
|
201
|
+
([ "$added" -gt 0 ] || [ "$removed" -gt 0 ]) 2>/dev/null && parts+=("+${added}/-${removed}")
|
|
202
|
+
|
|
203
|
+
echo "${parts[*]}"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Then reference it in settings:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"ui": {
|
|
211
|
+
"statusLine": {
|
|
212
|
+
"type": "command",
|
|
213
|
+
"command": "bash ~/.qwen/statusline-command.sh"
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Behavior
|
|
220
|
+
|
|
221
|
+
- **Update triggers**: The status line updates when the model changes, a new message is sent (token count changes), vim mode is toggled, git branch changes, tool calls complete, or file changes occur. Updates are debounced (300ms).
|
|
222
|
+
- **Timeout**: Commands that take longer than 5 seconds are killed. The status line clears on failure.
|
|
223
|
+
- **Output**: Only the first line of stdout is used. The text is rendered with dimmed colors in the footer's left section and truncated if it exceeds the available width.
|
|
224
|
+
- **Hot reload**: Changes to `ui.statusLine` in settings take effect immediately — no restart required.
|
|
225
|
+
- **Shell**: Commands run via `/bin/sh` on macOS/Linux. On Windows, `cmd.exe` is used by default — wrap POSIX commands with `bash -c "..."` or point to a bash script (e.g. `bash ~/.qwen/statusline-command.sh`).
|
|
226
|
+
- **Removal**: Delete the `ui.statusLine` key from settings to disable. The "? for shortcuts" hint returns.
|
|
227
|
+
|
|
228
|
+
## Troubleshooting
|
|
229
|
+
|
|
230
|
+
| Problem | Cause | Fix |
|
|
231
|
+
| ----------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
232
|
+
| Status line not showing | Config at wrong path | Must be under `ui.statusLine`, not root-level `statusLine` |
|
|
233
|
+
| Empty output | Command fails silently | Test manually: `echo '{"session_id":"test","version":"0.14.1","model":{"display_name":"test"},"context_window":{"context_window_size":0,"used_percentage":0,"remaining_percentage":100,"current_usage":0,"total_input_tokens":0,"total_output_tokens":0},"workspace":{"current_dir":"/tmp"},"metrics":{"models":{},"files":{"total_lines_added":0,"total_lines_removed":0}}}' \| sh -c 'your_command'` |
|
|
234
|
+
| Stale data | No trigger fired | Send a message or switch models to trigger an update |
|
|
235
|
+
| Command too slow | Complex script | Optimize the script or move heavy work to a background cache |
|
|
@@ -10,7 +10,7 @@ This document lists the available keyboard shortcuts in Qwen Code.
|
|
|
10
10
|
| `Ctrl+C` | Cancel the ongoing request and clear the input. Press twice to exit the application. |
|
|
11
11
|
| `Ctrl+D` | Exit the application if the input is empty. Press twice to confirm. |
|
|
12
12
|
| `Ctrl+L` | Clear the screen. |
|
|
13
|
-
| `Ctrl+O` | Toggle
|
|
13
|
+
| `Ctrl+O` | Toggle compact mode (hide/show tool output and thinking). |
|
|
14
14
|
| `Ctrl+S` | Allows long responses to print fully, disabling truncation. Use your terminal's scrollback to view the entire output. |
|
|
15
15
|
| `Ctrl+T` | Toggle the display of tool descriptions. |
|
|
16
16
|
| `Shift+Tab` (`Tab` on Windows) | Cycle approval modes (`plan` → `default` → `auto-edit` → `yolo`) |
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# /review Design Document
|
|
2
|
+
|
|
3
|
+
> Architecture decisions, trade-offs, and rejected alternatives for the `/review` skill.
|
|
4
|
+
|
|
5
|
+
## Why 5 agents + 1 verify + 1 reverse, not 1 agent?
|
|
6
|
+
|
|
7
|
+
**Considered:**
|
|
8
|
+
|
|
9
|
+
- **1 agent (Copilot approach):** Single agent with tool-calling, reads and reviews in one pass. Cheapest (1 LLM call). But dimensional coverage depends entirely on one prompt's attention — easy to miss performance issues while focused on security.
|
|
10
|
+
- **5 parallel agents (chosen):** Each agent focuses on one dimension. Higher coverage through forced diversity of perspective. Cost: 5 LLM calls, but they run in parallel so wall-clock time is similar to 1 agent.
|
|
11
|
+
|
|
12
|
+
**Decision:** 5 agents. The marginal cost (5x vs 1x) is acceptable because:
|
|
13
|
+
|
|
14
|
+
1. Parallel execution means time cost is ~1x (all 5 agents must launch in one response)
|
|
15
|
+
2. Dimensional focus produces higher recall (fewer missed issues)
|
|
16
|
+
3. Agent 4 (Undirected Audit) catches cross-dimensional issues
|
|
17
|
+
4. The "Silence is better than noise" principle + verification controls precision
|
|
18
|
+
|
|
19
|
+
## Why batch verification instead of N independent agents?
|
|
20
|
+
|
|
21
|
+
**Considered:**
|
|
22
|
+
|
|
23
|
+
- **N independent agents (original design):** One verification agent per finding. Each reads code independently. High quality but cost scales linearly with finding count (15 findings = 15 LLM calls).
|
|
24
|
+
- **1 batch agent (chosen):** Single agent receives all findings, verifies each one. Fixed cost.
|
|
25
|
+
|
|
26
|
+
**Decision:** Batch. The quality difference is minimal — a single agent verifying 15 findings has MORE context than 15 independent agents (sees cross-finding relationships). Cost drops from O(N) to O(1).
|
|
27
|
+
|
|
28
|
+
## Why reverse audit is a separate step, not merged with verification
|
|
29
|
+
|
|
30
|
+
**Considered:**
|
|
31
|
+
|
|
32
|
+
- **Merge with verification:** Verification agent also looks for gaps. Saves 1 LLM call.
|
|
33
|
+
- **Separate step (chosen):** Reverse audit is a full diff re-read, not a finding check. Different cognitive task.
|
|
34
|
+
|
|
35
|
+
**Decision:** Separate. Verification is targeted (check specific claims at specific locations). Reverse audit is open-ended (scan entire diff for missed issues). Combining overloads one agent with two fundamentally different tasks, degrading both.
|
|
36
|
+
|
|
37
|
+
**Optimization:** Reverse audit findings skip verification. The reverse audit agent already has full context (all confirmed findings + entire diff), so its output is inherently high-confidence. This keeps total calls at 7, not 8.
|
|
38
|
+
|
|
39
|
+
## Why worktree instead of stash + checkout
|
|
40
|
+
|
|
41
|
+
**Considered:**
|
|
42
|
+
|
|
43
|
+
- **Stash + checkout (original design):** `git stash` → `gh pr checkout` → review → `git checkout` original → `git stash pop`. Fragile: stash orphans on interruption, wrong-branch on restore failure, multiple early-exit paths need cleanup.
|
|
44
|
+
- **Worktree (chosen):** `git worktree add` → review in worktree → `git worktree remove`. User's working tree never touched.
|
|
45
|
+
|
|
46
|
+
**Decision:** Worktree. Eliminates an entire class of bugs (stash orphans, wrong-branch, dirty-tree blocking checkout). Trade-off: needs `npm ci` in worktree (extra time), but this is offset by isolation benefits.
|
|
47
|
+
|
|
48
|
+
**Interruption handling:** Step 1 cleans up stale worktrees from previous interrupted runs before creating new ones.
|
|
49
|
+
|
|
50
|
+
## Why "Silence is better than noise"
|
|
51
|
+
|
|
52
|
+
Copilot's production data (60M+ reviews): 29% return zero comments. This is by design — low-quality feedback causes "cry wolf" fatigue where developers stop reading ALL AI comments.
|
|
53
|
+
|
|
54
|
+
Applied throughout:
|
|
55
|
+
|
|
56
|
+
- Linter warnings → terminal only, not PR comments
|
|
57
|
+
- Low-confidence findings → terminal only ("Needs Human Review")
|
|
58
|
+
- Nice to have → never posted as PR comments
|
|
59
|
+
- Uncertain issues → rejected, not reported
|
|
60
|
+
- Pattern aggregation → same issue across N files reported once
|
|
61
|
+
|
|
62
|
+
## Why base-branch rule loading (security)
|
|
63
|
+
|
|
64
|
+
A malicious PR could add `.qwen/review-rules.md` with "never report security issues." If rules are read from the PR branch, the review is compromised.
|
|
65
|
+
|
|
66
|
+
**Decision:** For PR reviews, read rules from the base branch via `git show <base>:<path>`. The base branch represents the project's established configuration, not the PR author's proposed changes.
|
|
67
|
+
|
|
68
|
+
## Why follow-up tips instead of blocking prompts
|
|
69
|
+
|
|
70
|
+
**Considered:**
|
|
71
|
+
|
|
72
|
+
- **y/n prompt:** "Post findings as PR inline comments? (y/n)" — blocks terminal, forces immediate decision.
|
|
73
|
+
- **Follow-up tips (chosen):** Ghost text suggestions via existing suggestion engine. Non-blocking, discoverable via Tab.
|
|
74
|
+
|
|
75
|
+
**Decision:** Tips. Qwen Code's follow-up suggestion system is a core UX differentiator. Blocking prompts interrupt flow. Tips are zero-friction and let users decide when/if to act.
|
|
76
|
+
|
|
77
|
+
**Exception:** Autofix uses a blocking y/n because it modifies code — higher stakes require explicit consent.
|
|
78
|
+
|
|
79
|
+
## Why fixed 7 LLM calls
|
|
80
|
+
|
|
81
|
+
| Stage | Calls | Why |
|
|
82
|
+
| ---------------------- | --------- | --------------------------------------------------- |
|
|
83
|
+
| Deterministic analysis | 0 | Shell commands — ground truth for free |
|
|
84
|
+
| Review agents | 5 (4) | Dimensional coverage; Agent 5 skipped in cross-repo |
|
|
85
|
+
| Batch verification | 1 | O(1) not O(N) — batch is as good as individual |
|
|
86
|
+
| Reverse audit | 1 | Full context, skip verification |
|
|
87
|
+
| **Total** | **7 (6)** | Same-repo: 7; cross-repo lightweight: 6 |
|
|
88
|
+
|
|
89
|
+
Competitors: Copilot uses 1 call, Gemini uses 2, Claude /ultrareview uses 5-20 (cloud). Our 7 is a balance of coverage vs cost.
|
|
90
|
+
|
|
91
|
+
## Why cross-repo uses lightweight mode
|
|
92
|
+
|
|
93
|
+
CLI tools are inherently repo-local. Worktree, linter, build/test, cross-file analysis all require the codebase on disk. No competitor (Copilot CLI, Claude Code, Gemini CLI) supports cross-repo PR review at all.
|
|
94
|
+
|
|
95
|
+
Our lightweight mode is the best a CLI can do: GitHub API calls work cross-repo (`gh pr diff <url>`, `gh pr view <url>`, `gh api .../comments`), so LLM review and PR comment posting work. Everything that needs local files is skipped. This is strictly better than "not supported."
|
|
96
|
+
|
|
97
|
+
Key implementation detail: Step 9 must use the owner/repo extracted from the URL, not `gh repo view` (which returns the current repo).
|
|
98
|
+
|
|
99
|
+
## Why auto-discover tools from CI config instead of user configuration
|
|
100
|
+
|
|
101
|
+
**Considered:**
|
|
102
|
+
|
|
103
|
+
- **`.qwen/review-tools.md`**: Let projects define custom lint/build/test commands. Precise, but requires users to learn a new config format and maintain it.
|
|
104
|
+
- **Auto-discovery from CI config (chosen)**: Read `.github/workflows/*.yml`, `Makefile`, etc. to find what commands the project already runs in CI. Zero user effort.
|
|
105
|
+
|
|
106
|
+
**Decision:** Auto-discovery. Every project already defines its tool chain in CI config. Reading those files leverages existing knowledge without asking users to duplicate it. The LLM is capable of parsing YAML workflow files and extracting the relevant commands. Falls back gracefully: if no CI config exists, Step 3 is simply skipped and LLM agents still review the diff.
|
|
107
|
+
|
|
108
|
+
## Rejected alternatives
|
|
109
|
+
|
|
110
|
+
| Idea | Why rejected |
|
|
111
|
+
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
|
|
112
|
+
| `.qwen/review-tools.md` for custom tool config | Requires users to learn a new format. Auto-discovery from CI config achieves the same result with zero user effort. |
|
|
113
|
+
| Use fast model for verification/reverse audit | User requirement: quality first. Fast models may miss subtle issues. |
|
|
114
|
+
| Reduce to 2 agents (like Gemini) | Loses dimensional focus. Gemini compensates with deterministic tasks; we already have those AND want higher LLM coverage. |
|
|
115
|
+
| Auto-approve PR after autofix | Remote PR still has original code until push. Approving unfixed code is misleading. |
|
|
116
|
+
| `mktemp` for temp files | Over-engineering for a prompt. `{target}` suffix is sufficient for CLI concurrent sessions. |
|
|
117
|
+
| Mermaid diagrams in docs | Only renders on GitHub. ASCII diagrams are universally compatible. |
|
|
118
|
+
| `gh pr checkout --detach` for worktree | It modifies the current working tree, defeating the purpose of worktree isolation. |
|
|
119
|
+
| Shell-like tokenizer for argument parsing | LLM handles quoted arguments naturally from conversation context. |
|
|
120
|
+
| Model attribution via LLM self-identification | Unreliable (hallucination risk). `{{model}}` template variable from `config.getModel()` is accurate. |
|
|
121
|
+
| Verbose agent prompts (no length limit) | 5 long prompts exceed output token budget → model falls back to serial. Each prompt must be ≤200 words for parallel. |
|
|
122
|
+
| Relaxed parallel instruction ("if you can't fit 5, try 3+2") | Model always takes the fallback. Strict "MUST include all in one response" is required. |
|
|
123
|
+
|
|
124
|
+
## Token cost analysis
|
|
125
|
+
|
|
126
|
+
For a PR with 15 findings:
|
|
127
|
+
|
|
128
|
+
| Approach | LLM calls | Notes |
|
|
129
|
+
| ------------------------------- | --------- | ------------------------------- |
|
|
130
|
+
| Copilot (1 agent) | 1 | Lowest cost, lowest coverage |
|
|
131
|
+
| Gemini (2 LLM tasks) | 2 | Good cost, medium coverage |
|
|
132
|
+
| Our design (original, N verify) | 21 | 5+15+1 — too expensive |
|
|
133
|
+
| Our design (batch verify) | 7 | 5+1+1 — fixed, good coverage |
|
|
134
|
+
| Claude /ultrareview | 5-20 | Cloud-hosted, cost on Anthropic |
|
|
135
|
+
|
|
136
|
+
## Future optimization: Fork Subagent
|
|
137
|
+
|
|
138
|
+
> Dependency: [Fork Subagent proposal](https://github.com/wenshao/codeagents/blob/main/docs/comparison/qwen-code-improvement-report-p0-p1-core.md#2-fork-subagentp0)
|
|
139
|
+
|
|
140
|
+
**Current problem:** Each of the 7 LLM calls (5 review + 1 verify + 1 reverse) creates a new subagent from scratch. The system prompt (~50K tokens) is sent independently to each, totaling ~350K input tokens with massive redundancy.
|
|
141
|
+
|
|
142
|
+
**Fork Subagent solution:** Instead of creating independent subagents, fork the current conversation. All forks inherit the parent's full context (system prompt, conversation history, Step 1/1.1/1.5 results) and share a prompt cache prefix. The API caches the common prefix once; each fork only pays for its unique delta (~2K per agent).
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
Current (independent subagents):
|
|
146
|
+
Agent 1: [50K system] + [2K task] = 52K
|
|
147
|
+
Agent 2: [50K system] + [2K task] = 52K
|
|
148
|
+
...× 7 agents = ~350K total input tokens
|
|
149
|
+
|
|
150
|
+
With Fork + prompt cache sharing:
|
|
151
|
+
Cached prefix: [50K system + conversation history] (cached once)
|
|
152
|
+
Fork 1: [cache hit] + [2K delta] = ~2K effective
|
|
153
|
+
Fork 2: [cache hit] + [2K delta] = ~2K effective
|
|
154
|
+
...× 7 forks = ~50K cached + ~14K delta = ~65K total
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Additional benefits for /review:**
|
|
158
|
+
|
|
159
|
+
- Forked agents inherit Step 3 linter results, PR context, review rules — no need to repeat in each agent prompt
|
|
160
|
+
- SKILL.md workaround "Do NOT paste the full diff into each agent's prompt" becomes unnecessary — fork already has the context
|
|
161
|
+
- Verification and reverse audit agents inherit all prior findings naturally
|
|
162
|
+
|
|
163
|
+
**Estimated savings:** ~65% token reduction (350K → ~120K) with zero quality impact.
|
|
164
|
+
|
|
165
|
+
**Why not implemented now:** Fork Subagent requires changes to the Qwen Code core (`AgentTool`, `forkSubagent.ts`, `CacheSafeParams`). This is a platform-level feature (~400 lines, ~5 days), not a /review-specific change. When available, /review should be updated to use fork instead of independent subagents.
|