qwen-code/.github/scripts
Shaojin Wen 519e824dc7
fix(ci): give the macOS and Windows lanes a trigger again (#9370)
* fix(ci): give the macOS and Windows lanes a trigger again

Both lanes are gated on `merge_group`, and no merge queue is enabled on
this repository — the `main` ruleset carries only deletion,
non-fast-forward and pull_request rules, no status check is required,
and merges land as squashes. The last `merge_group` run of anything was
2026-07-02. So the gate was an off switch: the lanes reported as
"skipped" on every pull request, which reads as agreement, and nothing
ever reached them afterwards. The only signal this repository has about
a host that is not Linux with a GNU userland had been silently off for
six weeks, which is how #9220 shipped a GNU-only `realpath -m` in a
workflow guard with the suite that pinned it red on every Mac.

Three triggers now, in cost order.

A pull request whose diff a new classifier recognises as
platform-sensitive: shell scripts of every dialect, workflow and
composite-action YAML and the scripts they call, the script layer and
its tests, the test-runner configuration that decides which suites run
where, the root manifests, and source paths whose segments name a
platform-coupled subsystem. It is a net, not a proof — it cannot see a
platform assumption inside an ordinary source file, and no path rule
ever will — so every unknown answers "sensitive": an unreadable listing,
an unparsable entry, a fork pull request, a truncated file list, or the
classify job failing outright all end as "run the lanes". Only a
confident `false` skips them.

The merge queue, if it is ever enabled again, unchanged.

And a nightly run on `main` for everything the path list cannot see.
Every other job in the workflow excludes `schedule` explicitly, so a
nightly is exactly two jobs, and 'Qwen Code CI' joins the workflows the
main-failure watcher opens autofix issues for — a red lane nobody is
told about is the same silence the queue gate produced. That watcher
gains a trigger-level `branches: ['main']` filter so the CI workflow's
pull-request completions do not raise an event there just to skip.

The classifier runs in its own small hosted job rather than as a step in
`classify_pr`: that job's outputs pick the Linux runner for the whole
run, and this one needs a checkout — on a pool whose workspace other
jobs have poisoned before. It checks out the pull request's BASE commit,
never the head: it runs before any review and executes a script from the
tree it checks out. Its listing goes through the existing
classify-pr-profile.sh wrapper, extended with a mode argument, because
that wrapper's whole point is that one PR is never listed twice and
classified differently in two places.

Twelve tests pin the wiring — the triggers, the fail-safe direction of
the gate, the base-commit checkout, that a nightly stays two jobs, and
the alerting — and ten more pin the classifier itself, including the
substring traps (`Shellfish.tsx`, `cryptic.ts`, `plateauDetector.ts`
must not drag both lanes in) and every fail-safe path. Mutation-checked:
flipping the gate to `== 'true'`, dropping the schedule from a lane,
dropping the nightly guard from the ubuntu job, pointing the checkout at
the head, dropping the classifier's test from the helper list, and
removing the schedule trigger are each caught.

* fix(ci): gate the Windows lane's checkout verification per trigger

The first thing the revived triggers hit was not a test failure but the
lane's own plumbing. `test_windows` verifies its checkout with
`verify-checkout-head`, and the input was written when this lane ran in
the merge queue alone: `expected_sha: github.event.merge_group.head_sha`,
with no event gate. On a pull request that expression is empty, the
action refuses an empty SHA, and the lane went red in 63 seconds without
running a test — the first Windows run in six weeks, failing on the
trigger rather than on the code.

Give it the event-aware shape the Ubuntu gate already uses, and skip it
where there is nothing to verify: the scheduled and dispatch runs check
out a branch by name, not a head commit.

Pinned generally rather than by name: for both lanes, any step whose
inputs read a `github.event.<event>` context must be gated to that
event, in the step's own `if` or in the expression itself. Restoring the
old spelling turns that test red.

* fix(ci): close review round on the revived platform lanes (#9370)

* fix(ci): pin the Windows lane routing to the canonical trust policy (#9370)

* fix(ci): host-probe the macOS lane's bash and GNU dependencies (#9370)

The revived macOS lane ran the shared suite for the first time since the
merge queue went dark and failed on exactly three tests, identical across
three consecutive runs: the bite-check block and the baseline A/B green
path die with `mapfile: command not found` (a bash >= 4.4 builtin; macOS
ships 3.2), and the health-probe repair case trips over BSD `mktemp -u`
attempting to create where GNU's print-only `-u` just names the canary.

Both suites pin scripts that only ever execute on Linux runners —
ubuntu-latest or the Linux ECS pool — so the defects cannot exist in
production; the suites just cannot run those scripts on a macOS host.
Follow the convention #9220's fix established for the realpath case in
the same file: probe the host capability, not the platform, and skipIf
the three dependent tests where it is absent. A Mac with a newer bash or
GNU coreutils fronting PATH keeps the coverage; the Linux lane runs all
three unconditionally. The large bite-check test body is re-indented by
prettier around the new skipIf wrapper; no other token changed.

* fix(ci): stop the subsystem rule matching compounds that name something else

The platform-sensitivity classifier split a path segment on dashes and
underscores anywhere, so `packages/web-shell/**` matched the `shell`
keyword — one of this repository's largest packages, a browser UI with
no host coupling, summoning both expensive lanes on every change to it.
That is the cost the gate exists to avoid, spent on the wrong diffs.

A keyword now counts when it NAMES the thing: a whole path segment
(`src/sandbox/**`, `platform/paths.ts`, `shell.ts`) or the head of a
hyphen/underscore stem (`pty-host.ts`). Not a trailing part of a
compound, which belongs to whatever the leading word names, and still
not a substring inside a longer word.

Pinned both directions, including a directory that IS named for the
subsystem wherever it sits (`web-shell/components/shell/**` stays
sensitive). Mutation-checked: dropping either rule, or restoring the
split-anywhere spelling, turns the suite red.

Also drops a wrong issue citation in the watcher test's comment: the
nightly comes from this change, not from the wipe-guard back-port.

* test(ci): pin the gate as a disjunction and the watcher's name binding

Two mutation-survivable gaps in this PR's own tests.

The clause-presence assertions left a connective mutation alive: `||` →
`&&` between two event clauses keeps every asserted string in place and
makes the gate unsatisfiable for every trigger — both lanes silently off
again, which is the state this PR exists to end. Read the event group and
require it to be a disjunction, allowing `&&` only inside the
pull-request clause that binds to the classifier output.

And the watcher's binding to this workflow is by display name:
`workflow_run.workflows` matches the watched workflow's `name:`, so
renaming ci.yml unhooks the nightly's alerting silently. Pin both sides.

Both checked by mutation: flipping one `||` and renaming the workflow
each turn a named test red.

* fix(ci): close the classifier's CRLF gap and widen the lane step scan

Three findings from this round, all in the direction of the tests and
the parser being less clever than they claimed.

The classifier's JSONL reader split on `\n` while its sibling splits on
`/\r?\n/`. Every suffix rule here is end-anchored, so one carriage
return on a CRLF listing would leave `build.sh\r` and classify a
script-layer change as ordinary source. Matched to the sibling, with a
fixture on both the JSON and the raw-line path.

The per-trigger step scan serialized only `with:` inputs, so the same
defect wearing an `env:` or `run:` key escaped it; it now reads all
three.

And the nightly blast-radius guard tested for the MENTION of an
allowlisted event rather than the IMPOSSIBILITY of `schedule` — a job
gated `pull_request || schedule` satisfied it while running every night.
It now requires the absence of an explicit schedule clause too.

* style(ci): format the runner-routing suite

The Windows trust-policy matrix added last round left the file outside
prettier's style, which the repository's lint step fails on; main's copy
is clean. Formatting only — the nine assertions are unchanged and still
pass.

* fix(ci): gate the two mapfile-crossing gate tests on the host probe (#9370)

* fix(ci): keep pull requests off the persistent Windows pool and cover native audio (#9370)

A pull_request run executes the workflow YAML from the PR's own merge
commit, so the test_windows runs-on trust clause it evaluated could be
rewritten by any PR the lane admits. Every pull request now runs on
hosted windows-2022 unconditionally; the pool is reached only by the
post-approval merge queue, schedule and dispatch, guarded by the
kill-switch. The routing tests and the exact-line pin are re-pointed at
that enforceable shape.

Also add audio to the platform-sensitivity classifier's subsystem
keywords: packages/audio-capture is a node-gyp workspace compiled
per-host on exactly the two revived lanes, but its native sources
(.cc/.mm/.gyp) carried no rule and a PR touching only them skipped both
lanes. The workspace directory now classifies sensitive; an ordinary
.cc elsewhere stays ordinary source.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-08-25 11:53:05 +00:00
..
ci fix(ci): give the macOS and Windows lanes a trigger again (#9370) 2026-08-25 11:53:05 +00:00
dsw-swe-verified feat: chain Terminal-Bench release evaluation (#9120) 2026-08-17 05:53:06 +00:00
fixtures test(ci): stage on-disk session state in the serve A/B (#9444) 2026-08-20 14:09:03 +00:00
assign-issue-owner.mjs feat(ci): auto-assign issues to area owners from labels (#8668) 2026-08-08 23:01:03 +00:00
assign-issue-owner.test.mjs feat(ci): auto-assign issues to area owners from labels (#8668) 2026-08-08 23:01:03 +00:00
auto-minimize-spam.test.mjs fix(ci): minimize new spam comments on creation (#9266) 2026-08-17 05:12:04 +00:00
autofix-push-and-report.sh fix(ci): neutralize legacy ##[ commands in autofix stdout echoes (#9871) 2026-08-25 02:17:46 +00:00
cap-release-notes.mjs fix(release): keep notes anchored and cap the release body (#8199) 2026-07-31 09:55:38 +00:00
cap-release-notes.test.mjs fix(release): keep notes anchored and cap the release body (#8199) 2026-07-31 09:55:38 +00:00
check-autofix-contracts.sh ci(autofix): add cross-package contract verification (#7642) 2026-07-24 05:13:04 +00:00
check-settings-schema.sh ci(autofix): recover from generated-artifact CI gates and stop silent stalls (#6998) 2026-07-17 03:26:43 +00:00
check-workflow-size.sh fix(ci): scope workflow-size ratchet to the PR that grew the file (#9931) 2026-08-25 01:46:34 +00:00
ci-flaky-rerun.mjs feat(ci): auto-open a deflake fix issue for confirmed flaky tests (#7231) 2026-07-19 16:49:29 +00:00
ci-runner-routing.test.mjs fix(ci): give the macOS and Windows lanes a trigger again (#9370) 2026-08-25 11:53:05 +00:00
classify-release-notes.mjs fix(ci): route workflow label mutations through REST (#8761) 2026-08-09 15:05:15 +00:00
classify-release-notes.test.mjs fix(ci): route workflow label mutations through REST (#8761) 2026-08-09 15:05:15 +00:00
create-desktop-update-manifest.mjs feat(desktop): add Aliyun OSS release mirror (#8976) 2026-08-12 10:59:10 +00:00
create-electron-bridge-manifest.mjs fix(desktop): bridge Electron users on Windows and Linux (#9079) 2026-08-13 15:42:31 +00:00
pr-safety-precheck.mjs fix(ci): limit fork PR precheck to safety signals (#6178) 2026-07-02 20:56:41 +08:00
pr-safety-precheck.test.mjs fix(ci): limit fork PR precheck to safety signals (#6178) 2026-07-02 20:56:41 +08:00
qwen-triage-workflow.test.mjs fix(triage): compute the flake-gate diff before the env -i re-exec (#9468) 2026-08-19 14:37:44 +00:00
resanitize-git-config.sh fix(ci): make autofix verification gates hermetic to runner git config (#8961) 2026-08-13 11:39:04 +00:00
resolve-owning-packages.sh fix(autofix): resolve owning package for nested paths; report verify-failed handoffs as not pushed (#7330) 2026-07-20 14:39:56 +00:00
resolve-sandbox-image.mjs fix(autofix): bind the sandbox image to its pulled digest (#9527) 2026-08-21 06:46:52 +00:00
resolve-sandbox-image.test.mjs fix(autofix): bind the sandbox image to its pulled digest (#9527) 2026-08-21 06:46:52 +00:00
run-autofix-review-verification.sh fix(ci): neutralize legacy ##[ commands in autofix stdout echoes (#9871) 2026-08-25 02:17:46 +00:00
serve-ab-diff.mjs test(ci): stage on-disk session state in the serve A/B (#9444) 2026-08-20 14:09:03 +00:00
serve-ab-diff.test.mjs test(ci): stage on-disk session state in the serve A/B (#9444) 2026-08-20 14:09:03 +00:00
serve-ab-drive.mjs test(ci): stage on-disk session state in the serve A/B (#9444) 2026-08-20 14:09:03 +00:00
serve-ab-drive.test.mjs test(ci): stage on-disk session state in the serve A/B (#9444) 2026-08-20 14:09:03 +00:00
upsert-bot-comment.sh perf(ci): run docs-only automatic reviews at medium effort (#8648) 2026-08-07 17:00:32 +00:00
upsert-bot-comment.test.mjs perf(ci): run docs-only automatic reviews at medium effort (#8648) 2026-08-07 17:00:32 +00:00
upsert-deferred-issue.sh fix(ci): neutralize legacy ##[ commands in autofix stdout echoes (#9871) 2026-08-25 02:17:46 +00:00
web-shell-visuals-compose.mjs ci(web-shell): denoise cross-job font-AA so visual previews stop false-flagging (#7210) 2026-07-19 11:27:08 +00:00
web-shell-visuals-compose.test.mjs ci(web-shell): denoise cross-job font-AA so visual previews stop false-flagging (#7210) 2026-07-19 11:27:08 +00:00
web-shell-visuals-publish.mjs fix(ci): don't let one failing scenario sink the whole visual preview (#7511) 2026-07-23 02:34:07 +00:00
web-shell-visuals-publish.test.mjs fix(ci): don't let one failing scenario sink the whole visual preview (#7511) 2026-07-23 02:34:07 +00:00