qwen-code/scripts/tests
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
..
ai-release-notes-workflow.test.js fix(release): keep notes anchored and cap the release body (#8199) 2026-07-31 09:55:38 +00:00
audit-runtime-critical.test.js ci: keep the critical-audit gate honest when npm cannot answer (#7743) 2026-07-26 06:59:13 +00:00
build-and-publish-image-workflow.test.js ci(autofix): restore sandbox image flow (#6261) 2026-07-03 15:30:58 +00:00
check-build-status.test.js fix(review): report what the transcripts prove; build the roster in one call (#7033) 2026-07-18 00:43:57 +00:00
check-i18n.test.ts fix(cli): localize approval mode UI labels (#6592) 2026-07-11 00:07:03 +00:00
chrome-extension-package.test.js fix(ci): cover release integration regressions (#5994) 2026-06-29 11:54:11 +00:00
ci-flaky-rerun-workflow.test.js fix(ci): stop a slow patrol classifier from killing every flaky rerun (#7358) 2026-07-21 02:33:51 +00:00
ci-flaky-rerun.test.js feat(ci): auto-open a deflake fix issue for confirmed flaky tests (#7231) 2026-07-19 16:49:29 +00:00
clean-package-build-artifacts.test.js test(core): stabilize file history eviction test (#6637) 2026-07-10 06:39:52 +00:00
cli-entry.test.js fix(cli): update npm installs safely in background (#7322) 2026-07-21 06:32:24 +00:00
comment-attachment-guard-workflow.test.js fix(ci): gate the attachment guard before it allocates a runner (#8095) 2026-07-30 06:32:55 +00:00
dev.test.js fix(review): report what the transcripts prove; build the roster in one call (#7033) 2026-07-18 00:43:57 +00:00
e2e-workflow.test.js fix(ci): keep the post-merge E2E signal on main alive (#7795) 2026-07-28 11:54:52 +00:00
generate-changelog.test.js feat(release): generate AI-assisted release notes (#6756) 2026-07-12 13:00:22 +00:00
generate-release-notes.test.js fix(scripts): slim release-note model prompts and log request timing (#7941) 2026-07-28 15:32:56 +00:00
get-release-version-python-sdk.test.js feat(sdk-python): add network timeouts to release version helper (#3833) 2026-05-05 19:25:00 +08:00
get-release-version.test.js fix(release): bump preview base past published stable (#7978) 2026-07-29 23:21:00 +00:00
install-script.test.js fix(cli): avoid updating active CLI processes (#6874) 2026-07-15 00:33:17 +00:00
issue-triage-ownership-workflow.test.js fix(ci): consolidate issue triage ownership (#7180) 2026-07-19 10:58:40 +00:00
lint.test.js revert: remove local PR verification gate (#7031) 2026-07-16 11:24:38 +00:00
main-ci-failure-issue-workflow.test.js fix(ci): keep the post-merge E2E signal on main alive (#7795) 2026-07-28 11:54:52 +00:00
no-ak-integration-ci.test.js ci: gate merges on deterministic no-AK E2E (#8313) 2026-08-02 02:21:14 +00:00
package-assets.test.js fix(release): raise prepared package size limit to 96 MB (#6687) (#6691) 2026-07-11 01:01:59 +00:00
package-scripts.test.js fix(release): bump preview base past published stable (#7978) 2026-07-29 23:21:00 +00:00
pr-force-push-reminder-workflow.test.js ci(autofix): run agents on dedicated ECS runners (#6207) 2026-07-03 07:40:07 +00:00
pr-self-report-label.test.js ci: label a PR that closes an issue its own author opened (#7630) 2026-07-24 05:50:47 +00:00
qwen-autofix-workflow.test.js fix(autofix): state the primary agent budget and use the step's headroom (#8257) 2026-08-01 09:23:09 +00:00
qwen-fleet-shepherd-workflow.test.js feat(autofix): label-driven takeover and release; fix forced-dispatch green no-op (#7165) 2026-07-19 07:35:13 +00:00
qwen-pr-review-workflow.test.js fix(review): give the review retry the remaining time budget (#7852) 2026-07-28 05:29:20 +00:00
qwen-repo-hygiene-workflow.test.js feat(ci): add repo-hygiene skill and weekly patrol workflow (#7908) 2026-08-02 09:45:38 +00:00
qwen-resolve-workflow.test.js fix(ci): serialise the two workflows that push to a PR head branch (#7392) 2026-07-21 07:40:56 +00:00
qwen-triage-finalize-workflow.test.js fix(ci): rename triage status marker to avoid duplicate-guard collision (#7723) 2026-07-26 15:51:22 +00:00
qwen-triage-workflow.test.js ci: auto-update ECS runners on stable publish and harden update job (#8343) 2026-08-02 03:33:52 +00:00
release-helpers.test.js refactor: extract shared release helper utilities (#3834) 2026-05-05 10:15:17 +08:00
release-sdk-workflow.test.js fix(ci): skip empty SDK release PR (#6861) 2026-07-14 13:19:42 +00:00
release-workflow.test.js ci: auto-update ECS runners on stable publish and harden update job (#8343) 2026-08-02 03:33:52 +00:00
sandbox-command.test.js fix(scripts): avoid shell injection in sandbox command detection (#6108) 2026-07-01 16:20:40 +08:00
sdk-node-exporter-stub.test.js perf(telemetry): lazy-load the SDK and split OTLP exporter chains by protocol (#7276) 2026-07-21 07:35:30 +00:00
serve-fast-path-bundle-check.test.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
start.test.js fix(review): report what the transcripts prove; build the roster in one call (#7033) 2026-07-18 00:43:57 +00:00
test-setup.ts feat(installer): add standalone archive installation (#3776) 2026-05-11 13:25:48 +08:00
update-ecs-runner-qwen-workflow.test.js fix(ci): reconcile ECS runner updater on workflow changes (#8373) 2026-08-02 09:25:17 +00:00
upload-aliyun-oss-assets.test.js feat(installer): add standalone hosted install and uninstall flow (#3828) 2026-05-21 11:57:10 +08:00
verify-capture.test.js fix(ci): avoid verify capture color conflict (#8236) 2026-07-31 14:15:40 +00:00
vitest.config.ts refactor(auth): unify provider config in core, simplify /auth as "Connect a Provider" (#4287) 2026-05-20 23:48:52 +08:00
workspaces.test.js feat(desktop): Add desktop app package with Qwen ACP SDK integration (#3778) 2026-06-11 21:57:20 +08:00