qwen-code/.github
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
..
actions/post-coverage-comment Upgrade GitHub Actions to latest versions (#3683) 2026-06-27 17:03:32 +00:00
assets/worktree-toggle feat(web-shell): surface worktree isolation in the new-session empty state (#7365) 2026-07-21 07:38:33 +00:00
ISSUE_TEMPLATE chore: re-organize labels for better triage results (#819) 2025-10-17 19:49:11 +08:00
scripts feat(desktop): package Web Shell as a release-ready desktop app (#8132) 2026-08-02 08:20:16 +00:00
workflows feat(ci): add repo-hygiene skill and weekly patrol workflow (#7908) 2026-08-02 09:45:38 +00:00
actionlint.yaml ci: add Windows runner smoke test (#8008) 2026-07-29 08:44:36 +00:00
CODEOWNERS chore: simplify CODEOWNERS to package-level rules (#7376) 2026-07-21 02:39:33 +00:00
dependabot.yml Limit dependabot PRs to security updates (#6657) 2025-08-20 22:24:43 +00:00
pull_request_template.md docs(agents,pr-template): add Working Principles and restructure PR template (#4496) 2026-05-25 19:15:35 +08:00
release.yml ci: auto-skip internal CI changes in release notes (#7251) 2026-07-20 11:10:55 +00:00
spam-blocklist.txt ci: auto-minimize comments from org-blocked users (#7899) 2026-07-29 23:37:42 +00:00