Commit graph

5543 commits

Author SHA1 Message Date
wenshao
fe83b82dab feat(review): add "fix these issues" follow-up tip
After review with unfixed findings (autofix declined/partial/N/A),
suggest "type fix these issues" so the LLM can interactively fix
each finding using the edit tool without re-running the review.

Follow-up tips now cover the complete post-review flow:
- Unfixed findings → "fix these issues"
- PR with findings → "post comments"
- Local all clear → "commit"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 00:38:15 +08:00
wenshao
5ff22dcd4f feat(review): add commit tip for local reviews with Approve verdict
After local review with no critical issues, suggest "type commit to
commit your changes" — the follow-up system picks this up as ghost
text so users can Tab to commit.

PR reviews keep the existing "post comments" tip.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 00:36:38 +08:00
wenshao
0b290e7031 fix(review): fix comment template, build precedence, and timeout unit
- Comment template: replace **[{severity}]** with {prefix} placeholder
  so auto-fixed prefix is not dropped
- Agent 5: run exactly one build + one test command using precedence
  order to avoid duplicates (e.g., Makefile wrapping npm)
- Clarify timeout as 120000ms for run_shell_command

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 00:35:04 +08:00
wenshao
1d185a19a9 fix(review): avoid re-running review when posting PR comments
Changed the tip from "/review <number> --comment" (which re-runs the
full review) to "post comments" (which reuses existing findings in
the same conversation and jumps directly to Step 4).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 00:30:45 +08:00
wenshao
e4b8d194db fix(review): use actual PR number in --comment tip
The tip placeholder <number> was being output literally, causing the
follow-up suggestion system to generate commands with wrong PR IDs.
Now explicitly instructs the LLM to substitute the real PR number.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 00:29:11 +08:00
wenshao
d03a7aaf1a fix(review): clarify PR comment prefix template format
Replace ambiguous {prefix} placeholder with concrete examples showing
the full Markdown bold + severity tag format for normal and auto-fixed
findings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 00:07:06 +08:00
wenshao
687d0357fc fix(review): restrict low-confidence findings to terminal only
Low-confidence findings now appear only in the terminal "Needs Human
Review" section and are never posted as PR inline comments. This
resolves the contradiction between "silence > noise" and posting
uncertain findings on PRs.

Also clarified that "confirmed (low confidence)" is for issues likely
real but needing human judgment, not vague suspicions (those should
be rejected).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 00:00:56 +08:00
wenshao
a3b3cbe156 fix(review): exclude deleted files from linter target list
Deleted/renamed files in the diff would cause per-file linters to fail
on non-existent paths, producing false deterministic failures. Now uses
--diff-filter=d to exclude deletions from the changed files list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:54:46 +08:00
wenshao
71733b5dcb fix(review): fix misleading test name and comment
Rename "should use unknown when model is not available" to
"when getModel returns undefined" — the mock config does define
getModel, it just returns undefined.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:47:59 +08:00
wenshao
3ac54581a8 fix(review): address Copilot comments and fix CI build failure
- Copilot-instructions.md precedence: prefer .github/ path, do not
  load both when both exist
- Simplify getModel() call: remove unnecessary typeof guard since
  Config already defines getModel()
- Fix TS2352 type error in test: use proper mock cast pattern
- Add getModel to base mockConfig for test consistency

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:31:42 +08:00
wenshao
fab4dc5949 feat(review): add model attribution to PR review summary
Add {{model}} template variable support in BundledSkillLoader. When a
skill body contains {{model}}, it is replaced with the runtime model ID
from config.getModel(). Only skills that use the variable are affected.

The /review skill now appends a model attribution footer to PR review
summaries: "Reviewed by {model} via Qwen Code /review"

This enables cross-model review workflows (e.g., develop with model A,
review with model B) with accurate attribution in PR comments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:21:44 +08:00
wenshao
fe3d596d72 fix(review): include both staged and unstaged files in local review
Step 1.5 said "the diff output" (singular) but local reviews produce
two diffs (git diff + git diff --staged). Changed files list now
explicitly takes the union of both.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:12:23 +08:00
wenshao
48340c3acf fix(review): preserve highest severity during dedup merge
When deduplication merges findings with different severities (e.g.,
a Critical typecheck error with a Suggestion from LLM review), the
merged finding now uses the highest severity. Deterministic severity
is treated as authoritative and cannot be downgraded.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 23:01:59 +08:00
wenshao
ab0259c1a1 fix(review): restore environment on early exit paths
When PR checkout fails or incremental review finds no new changes,
restore the environment (checkout original branch, pop stash) before
stopping. Previously these early exits left the stash orphaned.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:52:10 +08:00
wenshao
710d5122c6 fix(review): address fifth round of Copilot review comments
- Fix Source vs Issue field inconsistency: deterministic findings now
  use Source field ([linter]/[typecheck]) consistently with the schema
- Add base branch ref resolution with origin/<base> fallback and
  git fetch for fresh/non-standard checkouts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:51:27 +08:00
wenshao
cb8062f53f feat(review): add --comment tip after PR review verdict
After presenting findings for a PR review, append a tip:
"Tip: run /review <number> --comment to post these as PR inline comments."

This leverages the existing follow-up suggestion system — it will
read the tip in context and likely suggest the command as ghost text,
letting users discover the feature via Tab without blocking prompts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:47:12 +08:00
wenshao
2525791311 fix(review): address fourth round of Copilot review comments
- Add Source field to Step 2 output schema (Agents 1-4: [review],
  Agent 5: [build]/[test]) so Step 2.5 dedup can detect pre-confirmed
- Require Agent 5 to emit [build]/[test] tags explicitly
- Use grep -F (fixed-string) instead of -E regex for cross-file search
  to avoid metacharacter issues with JS symbols like $

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:40:55 +08:00
wenshao
034557a15e fix(review): address third round of Copilot review comments
- Fix golangci-lint: use ./... (package pattern) instead of file paths
- Unify PR comment prefix format: define canonical prefixes for normal,
  auto-fixed, and low-confidence findings in the template
- Stop workflow entirely on autofix commit failure (dirty tree would
  block Step 5 branch restore)
- Accept broader .gitignore patterns like .qwen/* for cache/reviews dirs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:32:02 +08:00
wenshao
7dd346647c fix(review): add edit tool to allowedTools for autofix
The autofix step (Step 3.5) needs targeted text replacement to apply
fixes safely. Without the edit tool, only full-file rewrites via
write_file would be available, which is risky for partial fixes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:21:26 +08:00
wenshao
54f80a413f fix(review): address second round of Copilot review comments
- Fix Step 1.5 intro: clarify whole-project vs per-file tool handling
  and filter-then-report approach
- Fix dedup + deterministic finding ambiguity: merged findings with any
  deterministic source are pre-confirmed and skip verification
- Fix autofix stash orphan: stop and let user handle commit failure
  instead of silently stashing (which Step 5 wouldn't pop)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:15:49 +08:00
wenshao
9a583c9c85 fix(review): address Copilot review comments
- Fix filter-then-truncate ordering: capture full linter output first,
  filter to changed files, then truncate (not head before filter)
- Record informational notes for skipped checks instead of silent skip
- Agent 5: capture full build/test output, keep first 50 + last 100
  lines instead of tail-only (preserves error context)
- Fix [Needs Review] vs severity tag contradiction: use both
  [Needs Review][Suggestion] format

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:07:28 +08:00
chiga0
1d639c97fa fix: revert default to verbose mode (true) and force-show on Error status
Per maintainer review (tanzhenxin): default verboseMode reverted to true
to preserve existing behavior — compact mode is opt-in via Ctrl+O.

Also addresses wenshao's security concern: in compact mode, tool groups
now force-expand on Error status (in addition to existing Confirming
handling), and ToolMessage force-shows result for both Confirming and
Error statuses so users always see diffs before approval and error
details for debugging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:04:31 +08:00
wenshao
1cbffa43b6 fix(review): address review feedback on /review skill
- Add tsc --incremental flag to speed up repeated type checks
- Increase type checker timeout to 120s (linters remain 60s)
- Improve cross-file grep patterns to cover .functionName, import { functionName }
- Don't truncate Critical pattern groups — list all locations
- Clarify pre-commit hook as a commit failure scenario in autofix

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 22:00:23 +08:00
wenshao
d75d17678b feat(review): enhance /review with deterministic analysis, build/test, autofix, and security hardening
Comprehensive improvements to the /review skill based on competitive analysis
of Copilot Code Review, Claude Code /ultrareview, and Gemini CLI async-pr-review.

Key changes (all prompt-only, no TypeScript code changes):

- P0: Integrate linter/typecheck (Step 1.5) — run project tools before LLM agents,
  with error/warning severity distinction
- P1: Add Agent 5 for build & test verification with env/code failure distinction
- P1: Cross-file impact analysis for Agents 1-4 with 10-symbol prioritization limit
- P1: Project custom review rules (.qwen/review-rules.md, copilot-instructions.md,
  AGENTS.md, QWEN.md) with base-branch reading for PR security
- P2: Autofix with user confirmation, PR branch commit, and verdict split
  (terminal vs PR submission)
- P2: Pattern aggregation for same-type findings across locations
- P2: Confidence levels (high/low) with "Needs Human Review" section
- P2: Skip "Nice to have" from PR inline comments to reduce noise
- P3: Incremental review via .qwen/review-cache/ with rebase fallback
- P3: Report persistence to .qwen/reviews/ with timestamp filenames

Security hardening:
- PR description prompt injection defense (untrusted DATA marker)
- Base-branch rule loading prevents review-bypass injection
- Concurrency-safe temp file paths with {target} suffix
- Safe git stash handling (conditional pop)
- Argument disambiguation (integer vs URL vs file path)

Audited through 14 rounds of undirected review with 40 issues found and fixed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 21:46:08 +08:00
wenshao
0e9c3610c5 fix: use explicit Agent tool wording in /statusline prompt
"Use the Agent tool with subagent_type" is more direct than
"Create an Agent", reducing ambiguity for the model.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:31:08 +08:00
wenshao
f8071186a9 docs: use sh -c in troubleshooting test command
Inline shell snippets need sh -c to execute via pipe, matching how
child_process.exec() runs the configured command.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:22:25 +08:00
wenshao
f67c9c5d78 fix: clarify footer comment and add Windows shell note to docs
- Footer comment now accurately states only the "? for shortcuts"
  hint is suppressed, not all left-section items
- Docs now note that Windows uses cmd.exe by default and suggest
  wrapping commands with bash -c or using a bash script

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:10:52 +08:00
wenshao
e4e3c215e8 fix: handle PS1 newlines in statusline-setup agent prompt
PS1 \n should be removed or replaced with a space since the status
line only displays the first line of stdout. Also added a guideline
that commands must produce exactly one line of output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:03:50 +08:00
wenshao
3aa246a829 docs: quote $input in inline command examples
Use echo "$input" instead of echo $input for proper shell variable
quoting, consistent with the script file example.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:54:06 +08:00
wenshao
2e089cce71 fix(docs): fix mode count and update plan example in approval-mode docs
- Fix "three distinct permission modes" → "four" (Plan was always listed)
- Update refactor example to use /plan command instead of /approval-mode
- Fix grammar in example description

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:51:22 +08:00
wenshao
5b9c94b436 docs: fix jsonc trailing commas that break settings parser
The settings parser uses stripJsonComments + JSON.parse, which does
not support trailing commas. Changed the config example from jsonc
to json and removed trailing commas so users can copy-paste safely.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:48:25 +08:00
wenshao
813d863e7c docs: guard division by zero in script example
Add size > 0 check before computing context percentage to prevent
division by zero when context_window_size is unavailable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:46:15 +08:00
wenshao
12e1ef4594 docs: add prerequisites, hot-reload note, fix troubleshooting test JSON
- Add jq prerequisite section
- Clarify that settings changes take effect without restart
- Provide complete JSON in troubleshooting test command
- Move script filename out of code block to avoid shebang confusion

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:41:41 +08:00
wenshao
b1af941713 docs: add status line user documentation
Covers configuration, JSON stdin fields, examples (model+tokens,
git branch, script file), behavior details, and troubleshooting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:35:46 +08:00
wenshao
ee8fcc9230 docs: add /plan command usage to approval mode documentation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:28:27 +08:00
wenshao
e038ce9958 fix(core): only suppress ENOENT in loadPlan, rethrow other errors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 18:05:36 +08:00
wenshao
7a2f5887b9 fix(core): use optional field syntax for prePlanMode declaration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 17:52:27 +08:00
wenshao
b8e81c02b4 feat(core): add plan file persistence to disk
Save approved plans to ~/.qwen/plans/{sessionId}.md so they can be
referenced later in the session or reviewed outside the CLI.

Changes:
- Storage: add getPlansDir() and getPlanFilePath()
- Config: add savePlan(), loadPlan(), getPlanFilePath() methods
- ExitPlanModeTool: persist plan to disk when user approves
- Tests: 4 new Config tests, 2 new ExitPlanModeTool assertions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 17:50:01 +08:00
wenshao
c597847bc3 feat(core): add prePlanMode tracking to restore previous approval mode
When entering plan mode, Config now saves the previous approval mode
(e.g. AUTO_EDIT, YOLO) so it can be restored when exiting. Previously,
/plan execute and ExitPlanModeTool both hardcoded a return to DEFAULT,
losing the user's prior mode.

Changes:
- Config: add prePlanMode field, getPrePlanMode(), auto-track in
  setApprovalMode()
- planCommand: /plan execute restores prePlanMode instead of DEFAULT
- ExitPlanModeTool: ProceedOnce restores prePlanMode instead of DEFAULT
- Tests: 4 new Config tests, 1 new planCommand test, 1 new
  ExitPlanModeTool test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 17:39:13 +08:00
chiga0
8d1866ca55 fix: address PR #2770 review feedback for verbose/compact mode toggle
- Fix default value: compact mode (verboseMode=false) is now the default,
  matching PR description and intended UX
- Extract shared ToolStatusIndicator component to eliminate duplicate
  status icon rendering between ToolMessage and CompactToolGroupDisplay
- Memoize VerboseModeProvider context value to prevent unnecessary
  re-renders of all consumer components
- Clear frozenSnapshot on WaitingForConfirmation state to ensure tool
  confirmation UI remains interactive during mid-stream toggle
- Replace magic string 'Shell' with SHELL_NAME constant in ToolMessage
- Remove unused i18n translation keys (verbose/compact mode messages)
- Update snapshots for Footer and ToolGroupMessage tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:07:59 +08:00
wenshao
9bba05bad3 fix: add ASK_USER_QUESTION to statusline-setup agent, clear debounce on command change
- Agent can now ask for clarification when PS1 is not found
- Clear pending debounce timer before immediate doUpdate on command
  change to prevent redundant second execution

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:46:02 +08:00
wenshao
4c4e63888a fix: kill child process when statusLine config is removed
When statusLineCommand becomes undefined (user removes the setting),
kill any in-flight child process, bump generation counter, and clear
the debounce timer so stale callbacks cannot resurrect the output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 14:21:28 +08:00
wenshao
1a985bb02e fix: exec cwd, output trimming, and status line alignment
- Set cwd to config.getTargetDir() so commands like pwd/git run in the
  correct workspace directory
- Strip only trailing newline instead of trim() to preserve intentional
  leading/trailing whitespace in command output
- Match footer's marginLeft/marginRight on the status line row so it
  aligns with the rest of the footer content

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:45:49 +08:00
wenshao
24251db4ef fix: track vimEnabled changes in status line triggers
When vim mode is toggled off, vimMode stays the same but the status
line should stop including vim data. Use effectiveVim (undefined when
disabled) as the tracked value instead of raw vimMode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:39:25 +08:00
wenshao
c219f7c4ac fix: address review feedback from Copilot
- Validate padding is finite number >= 0 instead of blind cast
- Initialize prevStateRef with current values to prevent double exec on mount
- Kill previous child process before starting new one; kill on unmount
- Fix agent prompt: settings path is ui.statusLine, not root-level
- Fix agent prompt: remove multi-cat examples, stdin can only be read once
- Update Footer left-section comment to reflect new behavior

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:34:47 +08:00
wenshao
be13adb6e7 fix: add SettingsContext to Footer tests
useStatusLine hook requires SettingsContext, which was missing from
the test render wrapper, causing all Footer tests to crash.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 11:32:21 +08:00
wenshao
959690b897 fix: regenerate settings.schema.json via generate:settings-schema
The hand-edited schema didn't match the auto-generated output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 08:19:03 +08:00
wenshao
8d85492913 feat(ui): rewrite customizable status line
Rewrite the status line feature (originally by Gemini 3.1 Pro) to align
with the upstream design:

- Settings: change from plain string to object `{ type, command, padding? }`
- Hook: event-driven with 300ms debounce instead of 5s polling; pass
  structured JSON context (session, model, tokens, vim) via stdin;
  generation counter to ignore stale exec callbacks; EPIPE guard on stdin
- Footer: render status line as dedicated row with dimColor + truncate;
  suppress "? for shortcuts" hint when status line is active
- Add `/statusline` slash command that delegates to a statusline-setup agent
- Add `statusline-setup` built-in agent with PS1 conversion instructions
- Remove unrelated changes (whitespace, formatting, package-lock, test file)
- Fix copyright headers (Google LLC → Qwen)
- Fix config path references (~/.qwen-code → ~/.qwen)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 08:04:20 +08:00
wenshao
09ccc1b896 fix(docs): add /plan <task> usage example to commands table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 07:11:25 +08:00
wenshao
6784f0c02c feat(ui): add customizable status line
Allow users to configure a custom shell command to display in the UI footer status line.
2026-04-06 07:10:50 +08:00