qwen-code/scripts
Zqc 07e35bf02f
feat(ci): add repo-hygiene skill and weekly patrol workflow (#7908)
* feat(ci): add repo-hygiene skill and weekly patrol workflow

Add .qwen/skills/repo-hygiene (SKILL.md + scripts/run-agent.mjs) and the corresponding GitHub Actions workflow that runs a weekly scan-and-fix patrol every Monday 03:00 UTC.

The skill defines a single scan-and-fix mode that scans the repo for small, certain docs/test/code hygiene issues (broken Markdown emphasis, test coverage truthfulness, contract mismatches, real boundary conditions), batches up to 8 fixes as individual Conventional Commits on ONE branch, and writes findings.json + bilingual report-only.md + PR body. High-risk paths (packages/core/src/**, auth/providers/models/config/tools/services) are report-only — they go to the PR comment, never the diff.

The workflow implements the trust split: agent never holds GitHub credentials; only the workflow publishes. Includes dedup (skip when a hygiene PR is already open), PAT identity verification, an independent verification gate (build/typecheck/lint + per-package vitest --changed), and a structural gate (commit cap, total diff cap, report-only path assertion).

Closes #7383.

* docs(repo-hygiene): expand judgment scans to six parallel search angles

Port the richer search-angle taxonomy from the operator's interactive loop-hygiene prompt into the SKILL.md.

Section B (judgment scans) now enumerates six explicit angles — test-coverage truthfulness, implementation/contract mismatch, resource lifecycle, real boundary conditions, user-visible configuration/API, and docs-as-secondary-scan — each with a grep/code-reference evidence requirement. The previous three-bullet version collapsed resource lifecycle and user-visible config/API into adjacent items, which meant the agent under-scanned AbortController/finally/iterator-return/stream-cleanup gaps and config-vs-schema disagreements in practice.

Also makes the subagent workflow explicit: subagents report candidates only and never touch the working tree; the main agent deduplicates and decides. This matches the operator prompt's 'retrieval subagent only reports, never modifies' constraint.

* refactor(repo-hygiene): drop deterministic-docs section, fold its principles into the scan loop

Section A (Deterministic docs patterns) was too narrow: it gave two specific rg commands that dated quickly and duplicated the docs-as-secondary-scan rule already present in the judgment-scan taxonomy. Remove the section and promote Section B to the only scan-targets list.

Two of Section A's cross-cutting principles are preserved by folding them into the scan loop's opening paragraph and the Docs bullet:
- 'a pattern hit is a lead, not a finding' — now applies to rg, grep, and any other scanner
- 'broken-but-rendering-fine emphasis stays untouched' — now part of the Docs bullet's exclusion list

* refactor(repo-hygiene): partition the scan into nine parallel subagents

The previous Scan Targets section dispatched subagents by search angle (six parallel scans of the whole monorepo). Each subagent ended up with a shallow read of every file it touched — it couldn't hold a module's contract graph in context, so findings tended to be one-line-deep (docs-vs-code, rendering bugs, dead-code hints).

Switch to partition-first dispatch: one subagent per of nine module boundaries (cli/config, cli/runtime, cli/ui, core, extensions, sdk-typescript, sdk-python-java, ui-apps, docs). Each subagent owns its partition, finds the package's own entry points/schemas/registries, then applies the six search angles inside that scope. The main agent deduplicates across partitions afterward.

A subagent must stay inside its partition; cross-partition findings are marked crossPartition:true for the main agent to merge or drop. Reading lists are intentionally not prescribed — the subagent picks the partition's own sources of truth.

* refactor(repo-hygiene): allow cross-partition tracing, drop anti-padding bullets

Two simplifications:

1. Replace 'subagent must stay inside its partition; crossPartition:true' with 'partition is a starting boundary, not a fence'. A subagent may now follow a call chain, import graph, or contract reference into another partition to build evidence. When a finding's evidence lands in a report-only path (core/*, auth/*, providers, models, config, tools, services, cross-package contracts), it goes to reportOnly — never into fixes. This replaces the previous crossPartition handoff machinery with one uniform rule that already exists in Scope Limits.

2. Drop two anti-padding bullets from Scope Limits ('do not batch trivial fixes to reach quota', 'do not manufacture findings to fill the run'). The Shared Rules' 'no speculative edits / keep changes minimal and scoped' already covers the same behavior; restating it here was noise.

* docs(repo-hygiene): fix stale 'scans A and B' reference in scan-and-fix mode

The A/B section split was collapsed into a single Scan Targets section two commits ago, but step 1 of Mode: scan-and-fix still said 'Run scans A and B'. Reword to describe the actual dispatch: nine partition subagents, six angles inside each, collect and deduplicate across partitions.

* refactor(repo-hygiene): switch report-only rule from path to impact scope

Drop the path-based report-only whitelist (packages/core/src/**, */src/auth/**, providers/models/config/tools/services/**, cross-package contracts). The report-only trigger is now impact scope: a finding whose minimal fix touches more than three files or more than one hundred lines of production code is report-only.

Rationale: the path list was a proxy for 'high-impact area' that over-blocked trivial, certain fixes inside those paths and under-blocked sprawling fixes outside them. The file/line threshold measures impact directly. Scope Limits already caps each fix at 20 lines of production diff, so anything past 100 lines is an order of magnitude beyond that — past the four-file mark is past the single-root-cause test.

* docs(repo-hygiene): expand each partition with package layout and correctness criteria

The previous Nine-partitions section was a one-line scope pointer per partition. Each partition is now a mini architecture block naming the package path, what the package does, its key subdirectories, and what 'correct' looks like inside the partition. Directory names verified against the current tree (cli/src/{commands,serve,acp-integration,services,remoteInput,dualOutput,startup,i18n,utils,core,export}, cli/src/ui/{agent-view,arena,extensions,mcp,hooks,subagents,background-view,shared,messages,contexts,themes,state,layouts,voice,selection,editors,daemon,models,noninteractive}, core/src/{agents,models,providers,tools,services,prompts,utils,hooks,memory,skills,subagents,permissions,confirmation-bus,mcp,lsp,ide,goals,resources,followup,extension,config,telemetry,output,qwen}, desktop/apps/{electron,viewer}, web-shell/client).

* refactor(ci): replace path-based gate with per-commit impact-scope check

The workflow gate previously rejected any branch touching core/src or
auth/providers/models/config/tools/services paths. This conflicted with
the SKILL.md's impact-scope rule (>3 files or >100 lines = report-only).

Replace with a per-commit check: each commit must touch ≤3 files and
have ≤100 diff lines. This aligns the deterministic gate with the
agent's report-only threshold.

* chore(ci): allow repo-hygiene workflow on fork for testing

* refactor(repo-hygiene): remove fix cap, file report-only as consolidated issue

- Remove MAX_FIXES (8) and MAX_TOTAL_DIFF_LINES (150) caps from workflow gate
- SKILL.md: no limit on fixes per run, only per-commit scope threshold
- Add workflow step to create single GitHub issue for all report-only findings
- Issue is deduplicated against existing open hygiene issues
- Per-commit impact-scope gate (≤3 files, ≤100 lines) remains unchanged

* fix(repo-hygiene): per-fix typecheck prompt + auto-revert on verification failure

- SKILL.md: require typecheck after each individual fix, not batched
- Workflow: typecheck runs first with auto-revert loop; bad commits are
  dropped while good ones survive, then full build+lint+test runs
- Prevents one bad fix from killing the entire patrol run

* fix(repo-hygiene): forbid retrying failed fixes to avoid loop detection

Agent got stuck retrying typecheck fixes repeatedly, hitting the
per-turn tool-call cap. Explicitly instruct to accept failures as
report-only and move on without retrying.

* fix(repo-hygiene): use only existing labels, structured failure handling

- Remove HYGIENE_LABEL env var; PR dedup by title+author search instead
- Issue uses 'bug' label (always exists); dedup by title search
- Remove label creation step
- SKILL.md: give agent concrete 3-step failure protocol (checkout,
  move to reportOnly, continue) instead of vague 'don't retry'

* fix(repo-hygiene): remove failure protocol, add anti-loop instruction

- Remove 3-step failure handling protocol (was over-engineered)
- Restore original 'write failure.md' behavior for failed verification
- Add: never re-issue identical tool calls (prevents loop detection)

* feat(repo-hygiene): add scan/fix split mode for two-phase execution

- SKILL.md: add Mode: scan-only and Mode: fix-only sections
- Workflow: add mode input (scan-and-fix/scan/fix) + scan_run_id input
- run-agent.mjs: add scan and fix specs with proper inputs/outputs
- Scan mode: only scans, uploads findings as artifact (~15min)
- Fix mode: downloads previous scan findings, only fixes (~25min)
- Gate/verify/push skipped for scan-only mode
- Branch name resolution skipped for scan-only mode

* refactor(repo-hygiene): split into scan + fix jobs in one workflow

Two-phase design within single workflow run:
- scan job: read-only, dispatches subagents, writes findings.json (~15min)
- fix job: depends on scan, downloads findings, fixes + verifies + pushes (~25min)

Benefits:
- Each phase stays within model's tool-call budget
- Scan failures don't waste fix-phase budget
- Fix failures don't require re-scanning
- phase input: both (default), scan, fix (with scan_run_id)

* simplify(repo-hygiene): remove phase/mode inputs, always scan then fix

Users just trigger the workflow. Scan and fix jobs run in sequence
automatically. No need for phase selection or scan_run_id.

* simplify(repo-hygiene): remove Mode sections from SKILL.md

- Replace three Mode sections with single 'Execution Steps' heading
- Step 1: scan phase (stop after findings.json)
- Step 2: fix phase (read findings, fix, verify, write PR)
- run-agent.mjs: invocation now tells agent which phase it's in
  using plain English instead of slash commands

* fix(repo-hygiene): use plain expression in job-level if condition

Remove ${{ }} wrapper from job-level if conditions to avoid
potential YAML parsing issues.

* fix(repo-hygiene): configure git remote with PAT before push

Checkout uses persist-credentials: false, so git push needs explicit
authentication via remote URL with x-access-token.

* fix(repo-hygiene): use single quotes for all if conditions

yamllint requires single-quoted strings. Changed all double-quoted
${{ }} expressions to single-quoted with escaped inner quotes.

* feat(repo-hygiene): gate drops oversized commits instead of failing

- Collect oversized commits during scan loop
- Capture commit messages before rebase
- Use git rebase -i to drop only the bad commits
- Move dropped findings from fixes to reportOnly in findings.json
- Continue with remaining commits instead of aborting the run

* refactor(repo-hygiene): split SKILL.md into per-phase documents

- SKILL.md keeps only shared content: rules, scope limits,
  findings.json format, output contract
- scan.md: scan targets (9 partitions, 6 angles) + scan steps
- fix.md: fix steps
- run-agent.mjs concatenates SKILL.md + phase doc by mode, so each
  phase's prompt contains only what that phase needs
- Drop the unused scan-and-fix mode

* refactor(repo-hygiene): move phase docs into references/ per skill convention

Match the triage/docs-audit skill layout: SKILL.md is the entry with
shared rules and a Workflow routing section; phase details live in
references/scan.md and references/fix.md. The CI runner still injects
the right phase doc into the prompt; interactive invocations follow
the routing section instead.

* refactor(repo-hygiene): adopt references/ progressive-disclosure layout

Match the triage skill convention: SKILL.md is the single entry with
shared rules and a Workflow routing section; phase details live in
references/scan.md and references/fix.md which the model reads itself.
The runner now sends only SKILL.md plus a one-line phase invocation.

* docs(repo-hygiene): drop redundant duplicate-tool-call rule

Loop guard already covers real loop scenarios; forbidding same-arg
calls at the SKILL layer added no value for a 9-subagent scan with
independent budgets and a state-heavy fix phase.

* fix(repo-hygiene): enable agent tool for scan and preserve partial findings

Scan settings never whitelisted the agent tool, so the nine-subagent
dispatch was impossible and the model scanned serially, blowing the
50-minute budget with zero output. Add agent to scan coreTools, teach
the serial fallback to write findings.json incrementally after each
partition, and upload agent.log/failure.md so failed scans can be
diagnosed.

* chore(repo-hygiene): drop fork-only repository guard

* chore: drop unrelated advisor design draft from branch

* fix(repo-hygiene): harden gate, dedup, and verification semantics

- Zero-fix runs are now green: fix phase stops silently instead of
  writing failure.md when the fixes array is empty
- PR dedup matches by hygiene/ branch prefix instead of trusting the
  agent-written title to contain 'repo-hygiene'
- Gate drops oversized commits in one rebase, removing the implicit
  newest-first ordering dependency of sequential rebases
- Dropped and reverted commits are appended as notes to pr-body.md so
  the PR description matches what is actually in the branch
- Scan job timeout raised to 75min (agent 50min cap + ~10min setup left
  a negative margin); typecheck output no longer suppressed

* fix(repo-hygiene): raise agent timeout for nine-partition scans

The v4 local run timed out at the 50-minute default while the v5 run
completed successfully but close to the limit. Nine parallel subagents
need more headroom, especially on slower CI runners.

- run-agent.mjs default: 50min → 70min
- Scan phase explicit QWEN_TIMEOUT_MS: 65min (job limit 75min)
- Fix phase explicit QWEN_TIMEOUT_MS: 75min (job limit 90min)

* fix(ci): use full SHAs in gate rebase and document typecheck-only revert

* fix(ci): skip push when verification reverts every hygiene commit

* fix(ci): route dropped and reverted findings into reportOnly

* fix(ci): correlate dropped commits to findings by bracketed id

* fix(ci): label hygiene PRs with autofix/repo-hygiene

* docs(skill): correct scan partition facts and skip empty report-only sentinel

* fix(skill): stop requiring report-only.md as a run-agent output

* fix(skill): settle the run-agent promise when the log stream errors

* fix(ci): gate the fix job on a scan-phase failure.md and validate findings JSON

* fix(ci): make the push gate's success dependency explicit

* fix(ci): keep dry runs from filing real report-only issues

* fix(ci): drop unregistered read_many_files and grant git clean for reverts

* fix(ci): count only production files and lines in the size gate

* perf(ci): skip the scan phase while a hygiene PR is still open

* docs(skill): resolve failure-handling and schema-regen contradictions

* fix(ci): apply review fixes to hygiene gates, runner signals, and skill docs

* docs(skill): align scan paths, reportOnly schema, and drop dispositions

- Document intentionally excluded packages in scan.md
- Fix cli/ui subpackage paths to include components/ prefix
- Add optional status field to reportOnly schema in SKILL.md
- Carry status in workflow gate/verify node scripts
- Give fix.md step 4b the same reportOnly drop path as 4a/4c

* fix(ci): add fork guard to repo-hygiene dedup job (#7908)

* fix(ci): surface surviving hygiene findings when verification fails (#7908)

A post-typecheck failure (build/lint/settings-schema/test) exited the verify
step non-zero without moving the surviving committed findings to reportOnly,
so the consolidated report-only issue never listed them and a persistent
failure silently discarded the same findings every week. Mirror the revert
path: an ERR trap now moves every remaining fix to reportOnly (status
failed-verify) before the step exits non-zero.

Also resolve a Scope Limits contradiction in the skill docs: the <=20-line
per-fix rule read as a hard cap while scan.md and the workflow gate enforce
only the 100-line/3-file report-only threshold. Make <=20 an explicit target
and document the new failed-verify status.

* fix(ci): salvage committed findings on failure, append to existing report-only issue, and incremental parallel scan writes (#7908)

* fix(ci): address review — contracts gate, sandbox image, gate salvage, revert labeling (#7908)

* fix(ci): enforce shell allowlist via auto-edit and salvage rebase conflicts (#7908)

* fix(ci): address review — scan mkdir allowlist, rg sandbox note, write deny rules (#7908)

* fix(ci): deny write_file to .git and persistence vectors in fix agent (#7908)

* fix(ci): deny write_file to executable configs and node_modules in fix agent (#7908)

* fix(ci): sandbox verification execution and isolate the PAT-bearing push (#7908)

* fix(ci): clarify verification sandbox flags harden, not mirror, the CLI defaults (#7908)

* fix(ci): sandbox resolve-owning-packages, re-stage gates, deny lockfile writes (#7908)

* fix(ci): make hygiene graceful-failure reachable, gate findings schema, scope artifacts (#7908)

* fix(ci): disable core.fsmonitor in gate, deny vite.config writes, align scanner wording (#7908)

* test(ci): add a repo-hygiene workflow test suite (#7908)

* fix(ci): match test assertions to workflow YAML quoting style (#7908)

* fix(ci): use double-quoted YAML if-conditions to match test assertions (#7908)

* fix(ci): mount hygiene WORKDIR read-only during sandboxed verification (#7908)

---------

Co-authored-by: 俊良 <zzj542558@alibaba-inc.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
2026-08-02 09:45:38 +00:00
..
installation fix(packaging): bundle clipboard addon in standalone builds (#6708) 2026-07-11 15:18:24 +00:00
lib feat(core): support QWEN_HOME env var to customize config directory (#2953) 2026-05-09 15:51:52 +08:00
tests feat(ci): add repo-hygiene skill and weekly patrol workflow (#7908) 2026-08-02 09:45:38 +00:00
acp-http-smoke.mjs feat(daemon): merge daemon-mode feature batch into main (#4490) 2026-06-12 00:34:49 +08:00
audit-runtime-critical.js ci: keep the critical-audit gate honest when npm cannot answer (#7743) 2026-07-26 06:59:13 +00:00
benchmark-api-latency.mjs feat(cli): add API preconnect to reduce first-call latency (#3318) 2026-04-27 06:54:55 +08:00
build-hosted-installation-assets.js fix(installer): auto-detect SYSTEM account and default PATH scope to machine (#4903) 2026-06-10 21:02:10 +08:00
build-standalone-release.js fix(packaging): bundle clipboard addon in standalone builds (#6708) 2026-07-11 15:18:24 +00:00
build.js feat(channels): GitHub polling adapter with notification-as-wakeup architecture (#7632) 2026-07-25 09:31:50 +00:00
build_package.js fix(build): clean stale outputs before tsc --build to prevent TS5055 (#4453) 2026-05-23 23:06:31 +08:00
build_sandbox.js fix(sandbox): fall back to 'latest' tag when image name has no colon (#2962) 2026-04-18 09:07:05 +08:00
build_vscode_companion.js Sync upstream Gemini-CLI v0.8.2 (#838) 2025-10-23 09:27:04 +08:00
check-build-status.js fix(review): report what the transcripts prove; build the roster in one call (#7033) 2026-07-18 00:43:57 +00:00
check-desktop-isolation.js feat(desktop): package Web Shell as a release-ready desktop app (#8132) 2026-08-02 08:20:16 +00:00
check-i18n.ts fix(cli): localize approval mode UI labels (#6592) 2026-07-11 00:07:03 +00:00
check-lockfile.js Sync upstream Gemini-CLI v0.8.2 (#838) 2025-10-23 09:27:04 +08:00
check-serve-fast-path-bundle.js feat(ci): fail the startup bundle check when the CLI entry is hoisted into a chunk (#8203) 2026-07-31 08:57:57 +00:00
clean-package-build-artifacts.js feat(channels): GitHub polling adapter with notification-as-wakeup architecture (#7632) 2026-07-25 09:31:50 +00:00
clean.js feat(desktop): Add desktop app package with Qwen ACP SDK integration (#3778) 2026-06-11 21:57:20 +08:00
cli-entry.js perf(cli): Propagate compile cache to ACP children (#7594) 2026-07-24 04:06:14 +00:00
copy_bundle_assets.js feat(core): add dataviz bundled skill (#6198) 2026-07-03 01:06:39 +00:00
copy_files.js revert: remove unused script modifications 2026-02-10 14:34:36 +08:00
create-standalone-package.js fix(cli): avoid updating active CLI processes (#6874) 2026-07-15 00:33:17 +00:00
create_alias.sh fix: ambiguous literals (#461) 2025-08-27 15:23:21 +08:00
daemon-dev.js fix(scripts): allow multiple dev:daemon instances by probing Vite port (#7212) 2026-07-19 12:49:47 +00:00
desktop-openwork-sync.ts feat(acp): support desktop qwen integration (#4728) 2026-06-09 19:09:44 +08:00
dev.js fix(review): report what the transcripts prove; build the roster in one call (#7033) 2026-07-18 00:43:57 +00:00
esbuild-shims.js perf(cli): code-split lowlight to cut startup V8 parse cost (#4070) 2026-05-15 17:26:18 +08:00
generate-changelog.js feat(release): generate AI-assisted release notes (#6756) 2026-07-12 13:00:22 +00:00
generate-git-commit-info.js # 🚀 Sync Gemini CLI v0.2.1 - Major Feature Update (#483) 2025-09-01 14:48:55 +08:00
generate-release-notes.js fix(release): raise model timeouts and shrink batch size for slow networks (#8007) 2026-07-29 22:38:35 +00:00
generate-settings-schema.ts revert: remove local PR verification gate (#7031) 2026-07-16 11:24:38 +00:00
get-release-version.js fix(release): bump preview base past published stable (#7978) 2026-07-29 23:21:00 +00:00
lint.js revert: remove local PR verification gate (#7031) 2026-07-16 11:24:38 +00:00
local_telemetry.js Merge tag 'v0.3.0' into chore/sync-gemini-cli-v0.3.0 2025-09-11 16:26:56 +08:00
measure-flicker.mjs fix(cli): bound SubAgent display by visual height to prevent flicker (#3721) 2026-04-29 22:34:55 +08:00
pre-commit.js Sync upstream Gemini-CLI v0.8.2 (#838) 2025-10-23 09:27:04 +08:00
prepare-package.js feat(core): add full-resolution image zoom tool (#7809) 2026-07-27 23:40:26 +00:00
prepare.js feat(web-shell): git status chip, visual working-tree diff, and sidebar git status (#7054) 2026-07-18 10:06:07 +00:00
release-script-utils.js feat(installer): add standalone hosted install and uninstall flow (#3828) 2026-05-21 11:57:10 +08:00
run-java-daemon-sdk-e2e.ts fix(sdk-java): Harden daemon transport reliability (#7603) 2026-07-24 04:22:05 +00:00
sandbox_command.js fix(scripts): avoid shell injection in sandbox command detection (#6108) 2026-07-01 16:20:40 +08:00
sdk-node-exporter-stub.js perf(telemetry): lazy-load the SDK and split OTLP exporter chains by protocol (#7276) 2026-07-21 07:35:30 +00:00
sign-release.sh feat(cli): add standalone auto-update support (#4629) 2026-06-04 22:53:12 +08:00
start.js fix(review): report what the transcripts prove; build the roster in one call (#7033) 2026-07-18 00:43:57 +00:00
sync-computer-use-schemas.ts feat(computer-use): configurable screenshot max dimension (setting + env) (#5122) 2026-06-15 15:25:27 +08:00
telemetry.js feat(core): support QWEN_HOME env var to customize config directory (#2953) 2026-05-09 15:51:52 +08:00
telemetry_gcp.js fix(mcp): update OAuth client names and improve MCP commands 2026-02-08 10:46:48 +08:00
telemetry_utils.js feat(core): support QWEN_HOME env var to customize config directory (#2953) 2026-05-09 15:51:52 +08:00
test-rewind-e2e.sh fix(test): update rewind E2E Test 1 assertion after isRealUserTurn fix (#3622) 2026-04-26 06:49:42 +08:00
test-windows-paths.js chore: consistently import node modules with prefix (#3013) 2025-08-25 20:11:27 +00:00
unused-keys-only-in-locales.json feat: add /diff command and git diff statistics utility (#3491) 2026-05-10 11:15:59 +08:00
upload-aliyun-oss-assets.js fix(release): move constants above entry point to avoid TDZ error (#4398) 2026-05-23 22:21:33 +08:00
verify-capture.mjs fix(ci): avoid verify capture color conflict (#8236) 2026-07-31 14:15:40 +00:00
verify-installation-release.js feat(installer): verify release assets + switch public docs to standalone entrypoint (#3855) 2026-06-04 17:23:04 +08:00
version.js fix(release): pin channel-base dep to exact version during release bump (#7953) 2026-07-28 16:58:28 +00:00
workspaces.js feat(desktop): Add desktop app package with Qwen ACP SDK integration (#3778) 2026-06-11 21:57:20 +08:00