Commit graph

88 commits

Author SHA1 Message Date
DennisYu07
1b5c36ce15
ci: add isolated DSW SWE-bench release pipeline (#7656)
* ci: add isolated DSW SWE release pipeline

* ci: bootstrap branch-only DSW full-suite test

* Revert "ci: bootstrap branch-only DSW full-suite test"

This reverts commit 76c64c162a.

* ci: fix prerelease full-suite bootstrap

* ci: use REST API for DSW release writeback

* ci: grant DSW runner access to model config

* ci: dispatch DSW release benchmarks asynchronously

* ci: remove synchronous DSW runner path

* docs: record completed DSW full-suite validation

* Add benchmark cache preparation and retry backoff

* fix(ci): validate DSW cache permissions before dispatch

* fix(ci): gate release benchmarks by minor version

* docs: define bounded benchmark publication gate

* docs: score valid grader results

* fix(ci): address DSW benchmark review feedback

---------

Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-29 06:35:58 +00:00
qwen-code-dev-bot
a7b1150816
fix(ci): clean stale .qwen/ before checkout to prevent Permission denied (#7977)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 1/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 2/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker - shard 3/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 1/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 2/3 (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none - shard 3/3 (push) Waiting to run
E2E Tests / E2E Test - macOS - shard 1/2 (push) Waiting to run
E2E Tests / E2E Test - macOS - shard 2/2 (push) Waiting to run
E2E Tests / cron-interactive E2E (nightly) (push) Waiting to run
E2E Tests / web-shell Browser Regression (push) Waiting to run
SDK Java / ubuntu-latest / Java 11 (push) Waiting to run
SDK Java / ubuntu-latest / Java 17 (push) Waiting to run
SDK Java / macos-latest / Java 21 (push) Waiting to run
SDK Java / ubuntu-latest / Java 21 (push) Waiting to run
SDK Java / windows-latest / Java 21 (push) Waiting to run
SDK Java / Real daemon E2E / Java 11 (push) Waiting to run
On reused GitHub-hosted runners, a previous job (e.g. verify/tmux on
the same runner pool) can leave .qwen/ files with restrictive
permissions (chmod -R a-w). The next job's checkout step then fails
with "error: unable to unlink old '.qwen/...': Permission denied"
because git cannot delete the read-only files during workspace
cleanup.

Add a pre-checkout step that chmods .qwen/ writable and removes it
before the checkout action runs. This is a no-op on fresh runners
where .qwen/ doesn't exist yet.

Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: 易良 <1204183885@qq.com>
2026-07-29 02:32:17 +00:00
Shaojin Wen
43c35e533b
fix(ci): keep the post-merge E2E signal on main alive (#7795)
* fix(ci): stop cancelling in-progress E2E runs on main

Merges land on main roughly every 18 minutes (median) while a full E2E run takes about 40, so cancelling the in-flight run on every push starved the suite: across the last 100 push runs, 67 were cancelled and only 25 ever reported a result. The nightly regression was the only reliable signal, and each cancelled run still burned roughly 10 minutes on three runners before dying.

Turning cancellation off for main hands the coalescing to GitHub's concurrency queue, which keeps at most one pending run per group and cancels the previously pending one. The queue therefore collapses to the newest tree on its own while the in-flight run always finishes, so every result covers the batch of commits merged since the last one — bisect that range when it goes red. Dev branches keep cancelling superseded runs, where only the latest push matters.

* fix(ci): dedupe main CI failure issues by failing test

The autofix issue for a red main was deduped on the commit SHA, so a standing failure opened a brand new issue on every merge: one broken E2E test on 2026-07-26 produced six duplicate issues in twelve hours, each pointing the autofix agent at an unrelated commit.

The failing tests are now identified from the logs of the failed jobs and used as the dedupe key, with one marker per test so a failure set that grows still matches the issue that already tracks part of it. Later commits hitting the same failure are appended to that issue as recurrences (bounded, newest first) instead of opening another one, and notes written by a human or the agent are preserved when the machine-owned trailer is refreshed. Runs with no identifiable test — an install or build break — keep the previous per-commit behaviour.

* fix(ci): keep the failure analysis out of the bot-PAT job

Identifying the failing tests means running a helper from the repository, and the workflow deliberately checked out nothing so that the job holding the bot PAT could never execute repository code — an invariant its own test enforces.

Rather than weaken it, the work is split: a read-only job checks out the tree, reads the failed run's logs, finds any issue that already tracks the failure and renders the title and body, handing both over as outputs. The job with the PAT keeps checking out nothing and only writes what it was given. The invariant test now asserts that separation — the PAT job runs no repository code and holds only issue write — instead of banning checkout everywhere in the file.

* fix(ci): harden main CI failure dedupe per review (#7795)

- Match the `[run <id>]` link text instead of the run URL when deduping
  recurrences: `/301` is a substring of `/3010`, so the URL match silently
  deleted an unrelated run's line.
- Rebuild the machine-owned "## Also failing" section from the live failure
  set on every merge so a test that has since been fixed drops out instead of
  being listed forever.
- Assert the analyze checkout is SHA-pinned with persist-credentials disabled
  and pin the failed-job log-download paths in the workflow test.
- Add an e2e workflow test guarding the cancel-in-progress expression that
  keeps in-progress runs on main from being cancelled.

* fix(ci): bound the issue body and randomize the heredoc delimiter (#7795)

* fix(ci): test the runCli --existing merge path (#7795)

* fix(ci): address review feedback on e2e signal PR (#7795)

- Assert the full cancel-in-progress expression including && so a
  mutation to || is caught by the e2e-workflow test
- Filter the capped-summary line from missingTests so it is not
  rendered as a fake bullet under Also failing

---------

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>
Co-authored-by: Qwen Code Bot <qwen-code-bot@users.noreply.github.com>
2026-07-28 11:54:52 +00:00
Shaojin Wen
f8014652a5
test(triage): regression-guard the triage workflow, and make the git cleanup an allowlist (#7660)
Guards the security-critical invariants of qwen-triage.yml that broke silently
once already — the `settings_json:` input name was wrong, so the action dropped
it and the review agent ran with the full default toolset and no deny list.
A new `node:test` suite (wired into the shared HELPER_TESTS list both CI paths
run) asserts: the `settings:` input name (never `settings_json:`), the
tools.core registration whitelist and the deny list, the fork-PR runner routing
invariants, and the git exec-vector cleanup.

It also flips that cleanup from a best-effort denylist — which kept missing new
families (pager, filter.*, includeIf subsections, url.*, credential…) — to a
keep-known-safe allowlist: unset every local config key that isn't plumbing
actions/checkout needs (repo format, remote, branch, fetch/gc/pack/index,
safe.directory, extensions, submodule url/active/branch — not submodule.*.update,
which can be `!cmd`). This closes the whole exec-vector class, including knobs
not yet enumerated. The harness runs the workflow's actual allowlist pattern
against a scratch repo to prove it unsets every exec family and preserves the
checkout plumbing.

Co-authored-by: verify <verify@local>
2026-07-24 11:02:19 +00:00
易良
8fe1f926e9
ci: auto-skip internal CI changes in release notes (#7251)
* ci: auto-skip internal CI changes in release notes

* ci: harden release note classifier

* fix(ci): close release note classifier review gaps

* fix(ci): close release classifier review gaps

* fix(ci): avoid release classifier label loop

* test(ci): cover release classifier test path variants
2026-07-20 11:10:55 +00:00
Shaojin Wen
1ec80b10d1
chore(vscode-ide-companion): sync third-party notices and guard against future drift (#7161)
* chore(vscode-ide-companion): regenerate NOTICES.txt and sync package-lock.json

NOTICES.txt had drifted out of sync with the dependency tree. It was
missing the third-party licenses pulled in transitively through
@qwen-code/core (notably @anthropic-ai/sdk and its dependencies), which
the notices generator reaches by following workspace links. Regenerated
from a clean install so it once again covers every resolved dependency.

Also sync the lockfile's ink spec to 7.0.3 to match
packages/cli/package.json, which pinned it without a caret but was never
reflected in package-lock.json.

* ci(vscode-ide-companion): guard NOTICES.txt against drift

Add a CI check that regenerates the companion notices and fails if the
committed file is stale, mirroring the existing settings-schema guard.
This stops the notices from silently rotting whenever a dependency
changes without a regeneration.

Also drop the validate:notices script entry, which pointed at a
non-existent file and was never functional.

* fix(vscode-ide-companion): make notices license lookup case-insensitive

The license-file lookup matched a fixed-case candidate list via fs.stat,
which resolves a `License` file on macOS's case-insensitive filesystem
but misses it on Linux's case-sensitive one. That made the generated
NOTICES.txt platform-dependent and broke the new CI up-to-date guard.
Scan the directory and compare lowercased names so the output is
identical on every platform.

* fix(vscode-ide-companion): match more license filename variants in notices

Extend the license-file candidate list with `LICENSE-MIT` and the
British-spelled `LICENCE.md` so packages that ship those (e.g. ignore,
bignumber.js) no longer emit a spurious "License text not found." in the
generated notices. Regenerates NOTICES.txt to include their licenses.

* test(vscode-ide-companion): cover case-insensitive notices license lookup

The Linux-only CI drift guard regenerates and compares on the same
case-sensitive filesystem, so a future revert to case-sensitive license
matching would produce consistent-but-wrong output and still pass. Extract
the lookup into an exported findLicenseFile() and add a regression test that
resolves a mixed-case `License` file regardless of platform.

---------

Co-authored-by: wenshao <wenshao@example.com>
2026-07-18 15:32:32 +00:00
Shaojin Wen
ddaf3aa548
ci(web-shell): before/after visual previews, showing only changed views (#6963)
* ci(web-shell): before/after visual previews, showing only changed views

The visual-preview bot posted the same fixed set of canned screenshots
on every web-shell PR, so it could not show what a PR actually changed
(a mermaid/split feature was invisible) and added noise on PRs that
touch the UI only trivially.

Render each scenario against BOTH the PR base (`main`) and the PR head,
pixel-diff them, and post a stitched "main | this PR" composite for only
the views that CHANGED. A PR with no visual impact composites nothing →
"no visual change". This makes the preview feature-aware with no per-PR
understanding: the diff finds exactly the surface the PR moved (and it
subsumes the backend-PR noise #6959 pre-filtered, at the content level).

- web-shell-visuals-compose.mjs: pixel-diff (canvas) + stitch a labelled
  composite; pure helpers (parseShot/isChanged/planWork) unit-tested.
- web-shell-visuals.yml: also render the base — trusted `main` via
  pull_request.base.sha, so no secret exposure in the untrusted-PR job —
  then compose; composites replace the raw after-shots (same
  `<view>-<theme>.png` name the publisher already expects).
- publish buildComment: list composites; "no visual change" when none.

Verified locally by overlaying #6881's real changes onto main + a new
mermaid scenario: the compositor flagged the mermaid view 6.5% changed
(its new zoom controls) and correctly skipped the unchanged transcript.

* ci(web-shell): address before/after review — lazy import, merge-base, robustness

Addresses the /review findings on the before/after preview:
- Lazy the @playwright/test import in the compositor so the pure exports
  (parseShot/isChanged/planWork) load dependency-free, and wire
  web-shell-visuals-compose.test.mjs into the github_ci_only test step —
  it was never actually running in CI. (finding 1)
- Diff against the MERGE-BASE, not the base-branch tip, so a PR branch
  behind main doesn't render others' already-landed changes reversed as
  this PR's diff. (finding 2)
- continue-on-error on the base checkout + install so a flaky base
  degrades to after-only instead of sinking the job; compose likewise
  degrades to the raw after-shots on failure. (finding 3)
- timeout 20->30 (the job ~doubled) and scope the base render to
  screenshots.spec.ts, skipping the discarded flow videos. (finding 4)
- diffPct: add img.onerror so a corrupt/truncated baseline PNG can't hang
  page.evaluate to the job timeout. (finding 5)
- Lower CHANGED_PCT_THRESHOLD 0.1 -> 0.02 (~205px at 1280x800) so an icon
  swap or one-word label change isn't classified "no change". (finding 6)
- Nits: correct the stdout comment, esc() the burned-in labels, and scope
  the comment wording to "screenshots" (flows are always head-only).

* ci(web-shell): address before/after review round 2 (yiliang114)

- diffPct: a dimension change IS a visual change — comparing only the
  overlapping rectangle hid it (a taller viewport with unchanged top
  pixels read 0%). Short-circuit any size mismatch to changed. (Critical)
- Composite/comment label: "PR base (before)" not "main" — the workflow
  also runs for release/**, whose base is not main. (Critical)
- Merge-base resolve: retry the compare API, then emit an EMPTY sha and
  SKIP the base render (after-only) rather than falling back to the
  base-branch tip, which reintroduces the reversed-diff bug. (Critical)
- Base steps get ids; the before render runs only when the base checkout
  AND install both succeeded — else base/ (nested under head) resolves
  node_modules up to head's and produces a hybrid before. (Critical)
- Publisher: a zero-change run now UPDATES the marker comment (image-less
  "no screenshot changes") instead of exiting, so a prior preview's stale
  images + SHA do not linger. (Critical)

Finding 6 (helper tests skip full CI) is a pre-existing repo-wide gap for
every .github/scripts test; left for a focused follow-up.

* ci(web-shell): close the compositor browser in a finally (leak on error)

A mid-loop rejection in diffPct (evaluate timeout / CDP disconnect on a
corrupt or oversized PNG) exited composeCli via the exception and skipped
browser.close(), leaking a ~200 MB Chromium child for the rest of the CI
job. Wrap the page + loop in try/finally so the browser always closes.

Also drop the stale "main (before)" labels from the docstring (the
composite/comment say "PR base" now, since the workflow also runs for
release/**).

* ci(web-shell): catch the compositor CLI promise for a clean exit

An unhandled composeCli() rejection (e.g. a missing @playwright/test)
printed an UnhandledPromiseRejectionWarning and exited without a
meaningful code; add a .catch that writes the error and exits 1.

* ci: run .github/scripts helper tests in full CI + test planWork nullish guards

- Finding 6: the compositor/publisher helper tests ran only in the
  github_ci_only profile, which a `full` PR skips (and vitest test:ci
  doesn't collect node:test files) — so a compositor change could pass CI
  without its regression tests. Run them in the full ubuntu Test job too.
- Cover planWork's `?? []` guards with null/undefined inputs.

* ci: extract HELPER_TESTS list so both CI profiles share one source of truth

Round-3 F6 fix duplicated the .github/scripts node:test list across the
github_ci_only and full-profile steps; a missed edit would silently drop
coverage in one path. Hoist it to a workflow-level env var both reference.

---------

Co-authored-by: wenshao <wenshao@example.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
2026-07-16 01:54:20 +00:00
Shaojin Wen
51026d4d06
ci(serve): daemon A/B before/after preview on response-surface PRs (#6975)
* ci(serve): daemon A/B before/after preview on response-surface PRs

The daemon analog of the web-shell visual before/after bot. For PRs that
touch the qwen serve response surface, build the CLI from BOTH the PR
base (main) and head, drive a fixed set of endpoints against each daemon,
and diff the JSON responses into a before/after field table posted on the
PR. A PR with no response change -> "no change".

- serve-ab-diff.mjs: structural JSON diff (set-aware arrays, volatile-
  field masking) -> before/after table; buildComment assembles all
  scenarios. Pure helpers unit-tested (12 tests).
- serve-ab-drive.mjs: boots the built daemon, drives GET /health,
  /health?deep=1, /capabilities (no model -- dummy creds), captures JSON.
- serve-ab.yml / serve-ab-publish.yml: capture (untrusted, no secrets) +
  privileged workflow_run publisher (validate+bind PR, dedup, TOCTOU),
  mirroring the web-shell split.

Verified locally: real daemon boot + capture, the engine diffing real
capabilities -> the before/after table, and no-change detection. The
workflow wiring (2x build + drive in CI) is exercised on the next serve PR.

* ci(serve): address before/after review — merge-base, base fail-safe, CI-wire tests

Applies the transferable web-shell before/after review findings to the
daemon A/B:
- Diff against the MERGE-BASE, not the base-branch tip, so a PR branch
  behind main doesn't show others' already-landed daemon changes reversed
  as this PR's diff.
- continue-on-error on the base checkout so a flaky base degrades to
  after-only instead of sinking the job (the base build/drive already was).
- Wire serve-ab-diff.test.mjs into the github_ci_only test step — it uses
  only node builtins, so it runs there dependency-free (no npm ci needed).

* feat(serve): add a create-session deep-health A/B scenario

Add a `health-deep-with-session` scenario: the drive harness gains
setup-request support, creates one session (POST /session), then probes
GET /health?deep=1 — exercising the session lifecycle + cross-workspace
session aggregation (#6961's exact case). Broaden the volatile mask to
cover lastActivityAt/idleSinceMs/sessionId/clientId/workspaceCwd so the
capture is deterministic, while the meaningful counts (sessions,
activePrompts, pendingPermissions, connectedClients, channelAlive) stay
diffable.

Verified against the real daemon: two runs of the same build diff to "no
change" (deterministic), and a sessions 1->2 change surfaces as a
before/after table row.

* ci(serve): address review — narrow trigger, degraded-base marker, test the entrypoint

- Narrow the trigger from packages/core/src/** (~1100 mostly-unrelated
  files) to packages/cli/src/serve/** — the daemon's actual response
  surface (core has no serve/health subtree). (Suggestion)
- diffCaptureDirs signals baselineMissing when head captures exist but the
  base build/drive produced none, so the comment says "diff skipped"
  rather than misreporting every field as added or "no change". (Suggestion)
- Export + test diffCaptureDirs (the function the CI `comment` subcommand
  actually invokes) with temp-fixture dirs, covering the diff + degraded
  path. (Suggestion)
- Wording: "PR base" not "main" (the workflow also runs for release/**).

* ci(serve): address review round 2 — escape table values, guard setup/baseline/daemon

- fmt escapes `|` and backtick so an arbitrary daemon value can't split a
  GFM table cell or close the code span.
- diffCaptureDirs surfaces base-only (removed/failed-to-capture) scenarios
  instead of silently dropping them — otherwise a broken scenario lowers the
  "across N" count and masks the regression.
- The drive checks each setup request's status and throws on non-2xx, so a
  failed POST /session can't let health-deep-with-session capture wrong
  state (0 sessions) and fake/mask a diff.
- The drive awaits daemon exit after SIGTERM (SIGKILL after 5s) so a hung
  daemon can't linger.

* ci(serve): clear-error JSON parse for both capture sides

The after-side JSON.parse was unguarded while the before-side wasn't; a
readJson helper now gives a 'invalid JSON capture at <path>' error for
either side instead of a raw SyntaxError.

* ci(serve): review round 3 — merge-base skip, surface malformed base, escape path, kill dead stdout

- serve-ab.yml: retry the merge-base compare then SKIP the before build
  (after-only) instead of falling back to the base-branch tip; gate the
  base checkout/build on a resolved sha + successful checkout.
- diffCaptureDirs: an existing-but-malformed base capture now surfaces
  (existsSync + readJson) instead of a bare catch treating it as {} (which
  reported every field as "added"); covered by a new test.
- renderTable: escape backticks in the path field too (fmt already did for
  values).
- Drop the dead stdout + its misleading "workflow reads it" comment (the
  publisher posts whenever body.md exists); log the count to stderr.

* ci(serve): renderTable label 'PR base' not 'main' (release/** provenance)

buildComment already said 'PR base', but the per-scenario table header +
no-change line still said 'main'; align them (the workflow also runs for
release/**, whose base is not main).

---------

Co-authored-by: wenshao <wenshao@example.com>
2026-07-16 00:58:52 +00:00
Shaojin Wen
02c79beb62
feat(web-shell): auto-post visual previews (screenshots + flow GIFs) on PRs (#6880)
* feat(web-shell): auto-post visual previews (screenshots + flow GIFs) on PRs

PRs that touch the web-shell UI now get an auto-updated comment with
light/dark screenshots of key views (transcript, slash menu, model/theme
dialogs, permission panel) and short GIF recordings of common flows,
rendered against the existing mock daemon — no real backend, no secrets.

Split into two workflows for security, since capture runs untrusted PR code:

- web-shell-visuals.yml (pull_request): checks out the PR head, builds and
  renders it with Playwright, captures PNGs + webm, converts webm->GIF with
  ffmpeg, and uploads an artifact. `contents: read` only, references no
  secrets — fork PRs run with a read-only token and no secrets.
- web-shell-visuals-publish.yml (workflow_run): downloads the artifact,
  binds it to its real PR by requiring the PR head SHA to equal the run's
  authenticated head SHA, hosts the images on a per-PR `pr-assets/*` branch
  (referenced by immutable commit SHA), and posts/updates one inline
  comment. Never checks out or runs PR code; the write token lives only here.

Capture infra is self-contained in packages/web-shell
(playwright.visuals.config.ts + client/e2e/visuals/*), reusing the mock
daemon harness. Run locally with:
`npm run test:e2e:visuals --workspace=packages/web-shell`.

* fix(web-shell): guard empty gh api response in visuals publish

Addresses review feedback on #6880: if `gh api` returns empty (network
error / rate limit), jq on empty stdin errors and `set -e` kills the
publish job. Skip gracefully instead.

* fix(web-shell): address review nits on visuals capture

- harness recordFlow: wrap video saveAs/delete in try/catch so a video
  I/O error (e.g. drive failed before navigation) can't mask the real
  driveError.
- capture workflow: drop the unused head_sha.txt artifact field; the
  publish job binds to the authenticated workflow_run.head_sha, and an
  artifact-sourced SHA would be untrusted.

* fix(web-shell): address second review round on visuals capture

- context.close() in recordFlow's finally is now best-effort (try/catch)
  so a close/crash error can't mask the real driveError.
- add a flows spec that asserts a throwing drive propagates its own error.
- trigger the capture workflow on playwright.visuals.config.ts changes too.

* fix(web-shell): address third review round on visuals capture

- harness: log (don't silently swallow) a video save/null when drive
  succeeded; keep masking-suppression only when driveError is set.
- publish: HTML-escape interpolated values in the comment builder (defense
  in depth, independent of the upstream filename sanitization); fix the
  stale 'single pr-assets branch' comment and key concurrency on source
  repo+branch so different PRs (incl. same-named fork branches) parallelize.
- capture: bump checkout to v6.0.3 (repo standard); surface ffmpeg's stderr
  on GIF-conversion failure instead of discarding it.

* fix(web-shell): harden visuals publish/capture (review round 4)

Publish (privileged workflow_run):
- CRITICAL: capture basename before `tr` so its trailing newline isn't
  turned into `_` (which broke the .png/.gif filter -> empty preview).
- dedup only against the bot's OWN comment (author + marker), not any
  marker-bearing comment a participant can post.
- bound the pr-assets branch: force-push a single orphan snapshot per run
  (previous snapshot GC'd) instead of appending unbounded untrusted content;
  this also removes the rebase/retry path.
- cap EXAMINED candidates (not just accepted) before validation; tighten
  per-file (3MiB) and accepted-image (14) caps.
- re-validate PR open + head-SHA immediately before the comment write
  (TOCTOU); retry the comment listing and abort rather than POST a duplicate
  when listing fails.
- esc() the runUrl for consistency with the self-defending HTML.

Capture (pull_request):
- upload raw recordings as a SEPARATE artifact the publisher never downloads,
  so an untrusted multi-GB video can't exhaust the privileged job.
- also trigger on packages/webui/src and packages/sdk-typescript/src (the
  visuals dev server aliases them).
- create screenshots/gifs dirs before the metadata counts (defensive).

Harness recordFlow:
- track drive failure with an explicit boolean (handles `throw undefined`);
  discard the recording on failure so a failed flow leaves no bogus webm.

* refactor(web-shell): extract + unit-test the visuals publish staging/comment

Addresses the review's testability gap (the class of bug that let the
filename sanitizer break the whole preview slip through green CI). The image
validation (magic bytes, filename sanitization, examined/accepted/size caps)
and the comment builder (light/dark pairing, flow labels, HTML escaping) move
from inline workflow bash/node into .github/scripts/web-shell-visuals-publish
.mjs, covered by web-shell-visuals-publish.test.mjs (run in ci.yml's
node --test line). The publish workflow sparse-checks-out and calls the
script instead. Behaviour is unchanged; it just gained a test surface.

* fix(web-shell): retry the visuals asset force-push; drop stale comment

Round-4 switched hosting to a force-push but left a comment referencing a
'push-retry loop' that no longer existed, and the force-push was a single
call that set -e would abort on a transient failure. Add a bounded retry and
correct the comment.

* fix(web-shell): harden visuals publish/capture (review round 6)

Script (unit-tested):
- flow labels: own-property lookup so `toString.gif`/`constructor.gif` can't
  leak Object.prototype members into the comment.
- per-kind image caps (screenshots vs gifs) so a large screenshot set can't
  silently starve the flow GIFs from the preview.
- tests for both, plus the per-kind cap.

Publish:
- bind the artifact PR number to the run's authenticated head repo+branch
  (not just head SHA), rejecting a sibling PR that shares the same commit.
- re-validate before the force-push and again right before the comment write
  (close the download/stage/lookup TOCTOU windows).

Capture:
- bound artifact contents before upload (drop oversized / excess files) so an
  untrusted spec can't bloat the published or video artifact.
- trigger on the capture workflow file itself.

- new close-trigger cleanup workflow deletes a PR's asset branch on close, so
  pr-assets/* refs don't accumulate without bound.
- single-source the capture viewport (constants.ts) shared by config + harness.
- model-switch flow asserts the daemon model request actually fired.

* fix(web-shell): stricter visuals error handling (review round 7)

Harness recordFlow:
- when the drive SUCCEEDS, a failed context.close() or video.saveAs() (or a
  missing recording) now FAILS the flow instead of a swallowed console.warn —
  a silent pass with no .webm makes the downstream GIF step fail confusingly.
  A drive FAILURE still discards the partial video and rethrows the original
  error (unchanged).

Publish:
- validate_pr distinguishes a transient API failure (empty after retries ->
  exit 1, re-triggerable) from a genuine invalid state (closed / head mismatch
  -> skip), via a `gate` wrapper used at all three checkpoints.
- add a 2s backoff between comment-listing retries (matching the push retry).

---------

Co-authored-by: wenshao <wenshao@example.com>
2026-07-15 06:48:52 +00:00
易良
344c006122
fix(ci): avoid apt on self-hosted Playwright smoke (#6865)
* fix(ci): isolate web-shell Playwright smoke runner

* fix(ci): avoid apt on ECS Playwright smoke

* fix(ci): enable manual ecs smoke validation

* fix(ci): repair manual runner input parsing

* docs(ci): clarify self-hosted playwright deps

* test(ci): fix Playwright runner assertion
2026-07-14 13:19:40 +00:00
易良
d454d0e744
fix(cli,core): Restore default debug log file output (#6605)
* fix(cli,core): restore default debug log file output

* fix(cli): preserve debug log sandbox opt-out

* test(cli): stabilize flaky UI tests

* fix(cli): scope default debug log to debug mode

* fix(core): scope debug log default to --debug mode per #6600

Revert isDebugLogFileEnabled() guard from `value === undefined` back to
`!value` so the non-debug default stays opt-in as prescribed in #6600.
The --debug scoping in config.ts already sets QWEN_DEBUG_LOG_FILE=1 when
in debug mode, making the global default flip unnecessary.

Also adds a regression test for the opt-out edge case
(QWEN_DEBUG_LOG_FILE='0' + --debug should not overwrite).

* test(cli): remove unused voice keyterms import

* test(cli): isolate cli entry fallback test

* ci: avoid web-shell smoke port collisions

---------

Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-10 09:58:41 +00:00
易良
55311c3b51
ci: route full CI follow-up jobs to selected runner (#6608)
* ci: route coverage comment job to selected runner

Resolves #6604

* ci: route web-shell smoke job to selected runner

Updates #6604

* ci: harden selected-runner follow-up jobs

* ci: route assigned autofix issues

* ci(autofix): preserve issue assignment gates

---------

Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-10 01:47:00 +00:00
ermin.zem
5c82857fea
Add harness infrastructure for web-shell package (#6517)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
E2E Tests / web-shell Browser Regression (push) Waiting to run
* test(web-shell): add browser and lint harness

* test(web-shell): harden browser smoke harness

* fix(web-shell): guard mock daemon model state

* test(web-shell): remove unused scenario harness

* fix(web-shell): remove stale lint disables

* test(web-shell): make matchMedia stub writable

* fix(web-shell): exclude tests from package typecheck

* test(web-shell): tighten mock daemon route contract

* Update packages/web-shell/client/e2e/utils/mockDaemon.ts

Co-authored-by: qwen-code-ci-bot <qwen-code-ci@service.alibaba.com>

* test(web-shell): clear stale SSE connections

* ci(web-shell): gate smoke on full CI profile

---------

Co-authored-by: ermin.zem <ermin.zem@alibaba-inc.com>
Co-authored-by: qwen-code-ci-bot <qwen-code-ci@service.alibaba.com>
Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
Co-authored-by: 易良 <1204183885@qq.com>
2026-07-09 08:11:58 +00:00
Salman Chishti
df6be035e1
Upgrade GitHub Actions for Node 24 compatibility (#5157)
* Upgrade GitHub Actions for Node 24 compatibility

Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>

* ci: update remaining checkout pins

---------

Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: 易良 <1204183885@qq.com>
Co-authored-by: yiliang114 <effortyiliang@gmail.com>
2026-07-07 12:17:22 +00:00
易良
e1fc45d508
ci(autofix): restore sandbox image flow (#6261)
* ci(autofix): restore sandbox image flow

* test(ci): update autofix workflow assertions

* ci(autofix): restore tracked output before review checkout

* test(ci): clarify autofix workspace assertion

* style(ci): format sandbox image resolver

* ci(autofix): address sandbox review feedback

* test(ci): cover sandbox image publish gating

* ci(autofix): validate sandbox image config

* ci(autofix): address workflow review comments
2026-07-03 15:30:58 +00:00
易良
183ad54b11
ci: add lightweight PR profiles (#6186)
* ci: add lightweight PR profiles

* fix(ci): harden lightweight profile classification

* fix(ci): harden lightweight profile edge cases

* fix(ci): report classifier invocation failures

* fix(ci): tighten docs-only path matching

* ci: restrict light profiles to same-repo PRs

---------

Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
2026-07-03 07:40:25 +00:00
易良
b16baf1ffc
ci(release): optimize validation steps (#6133)
* ci(release): optimize validation steps

* fix(ci): address release validation review comments

* fix(ci): document prepare skip contract

* test(ci): cover prepare failure exit

* fix(ci): prefix prepare error logs

* fix(ci): keep release quality build artifacts

* fix(ci): address release validation comments

* fix(ci): preserve release publish hooks

* test(ci): cover prepare failure paths

* fix(ci): disable release coverage safely
2026-07-02 23:53:08 +00:00
易良
9031d09af3
ci: persist npm cache on self-hosted runners (#6130) 2026-07-01 19:56:07 +00:00
易良
1287ac10ca
ci: stabilize actionlint on self-hosted runners (#6113) 2026-07-01 09:25:42 +00:00
Gaurav
fc184f20e5
fix(deps): clear critical runtime audit findings (#6065)
* fix(deps): clear critical runtime audit findings

* fix(core): allow intentional worktree hooks path setup
2026-07-01 05:28:32 +00:00
易良
c5fb9fd1e7
fix(ci): create isolated home before tests (#6071)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
2026-06-30 12:42:44 +00:00
易良
7f34cdabe1
fix(ci): stabilize merge queue checks (#6056) 2026-06-30 10:27:15 +00:00
jinye
565e4bc437
fix(cli): Guard serve fast-path bundle closure (#5995)
* fix(cli): guard serve fast-path bundle closure

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

* test(cli): tighten serve fast-path bundle guard

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

* codex: address PR review feedback (#5995)

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

* codex: address PR review feedback (#5995)

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

* codex: address PR review feedback (#5995)

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

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-06-29 14:38:32 +00:00
Salman Chishti
34678cfbd9
Upgrade GitHub Actions to latest versions (#3683)
Some checks are pending
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* Upgrade GitHub Actions to latest versions

Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>

* ci: restore ratchet annotations on upgraded actions

The action version bumps had replaced '# ratchet:owner/repo@<ver>'
annotations with bare '# vX.Y.Z' comments, which silently breaks
ratchet's ability to track and update these SHA pins. Restore the
annotations on every changed line (updated to the new major), matching
each line's pre-existing convention on main.

---------

Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
Co-authored-by: yiliang114 <effortyiliang@gmail.com>
2026-06-27 17:03:32 +00:00
易良
d851f49135
ci: take CodeQL and E2E off the per-merge push path (#5859)
After #5842, CodeQL and the E2E suite were the only things running on every push to `main` — the per-commit, post-merge backstop. With merges landing back-to-back, those runs (CodeQL ~30min, three E2E jobs ~25/36/36min, the latter never cancel-superseded) stacked on the scarce hosted Linux pool and were a main driver of the recent runner-saturation incident.

- CodeQL moves to its own scheduled codeql.yml (nightly + workflow_dispatch). It was never a required check and findings still surface in the Security tab, so per-commit scanning bought little. ci.yml loses its now-empty `push` trigger as a result (every remaining job is gated to pull_request / merge_group).
- E2E gets event-scoped concurrency so back-to-back pushes to `main` cancel superseded runs (only the latest tree matters and it covers every merged change), plus a nightly full regression as the guaranteed signal in case a busy merge window keeps cancelling the push run. Manual workflow_dispatch added.

The merge_group gate (ubuntu + integration + mac + win) still validates every PR before it lands; this only changes the non-gating post-merge work.

Follow-up (separate PR): alert on E2E/CodeQL failure (a deduped ci-failure issue) now that they run unattended.
2026-06-25 10:50:12 +00:00
易良
29ad82d6a3
ci: route the merge queue's Linux jobs onto ECS (#5854)
* ci: route the merge queue's Linux jobs onto ECS

The merge queue runs in the base-repo context but classify_pr was PR-only, so its ubuntu_runner output was empty in the queue and the Ubuntu Test + Integration jobs fell back to the shared hosted pool — piling onto the scarce hosted Linux runners exactly when the queue is busiest. Run classify_pr on merge_group too and route both the Ubuntu gate and Integration onto the same in-repo ECS pool as PRs; the MAINTAINER_ECS_RUNNER_DISABLED kill-switch and the hosted fallback are intact, and fork PRs are unaffected.

Also extend the checkout-verification guard to the merge queue: now that the queue's Ubuntu checkout runs on ECS behind the squid egress proxy, a stale-ref checkout could silently test the wrong tree, and a wrong-tree pass in the queue would merge bad code. One sub-second merge-base check.

Routing approach carried forward from #5853 by @wenshao (closed); this adds the merge-queue checkout guard on top.

* ci: fix verify-step wiring test and guard integration_cli on ECS

The merge-queue ECS routing renamed the test job's checkout guard to "Verify
checkout includes expected head commit", but no-ak-integration-ci.test.js still
asserted the old "Verify PR checkout includes head commit" name, failing the
wiring test. Update the assertion.

integration_cli now also routes to ECS (via classify_pr on merge_group) yet
lacked the protections the Ubuntu gate has. Mirror them: fetch-depth 1 (nothing
walks history; a full clone is the heaviest transfer on the ECS runner) and the
same stale-checkout guard, keyed on merge_group.head_sha.

* ci: mirror the Node 22 version probe into integration_cli

The self-hosted Node step claimed to mirror the Ubuntu gate but omitted the
major-version probe, so a non-22 Node on the ECS runner would run integration
tests with no log signal. Add the same warning-only check.
2026-06-25 09:25:09 +00:00
易良
4bd113518f
ci: give each CI job one home in the merge-queue flow (#5842)
Now that the merge queue is live, each job should run in exactly one place instead of doubling up.

- CodeQL and E2E leave the merge queue (CodeQL gains a merge_group guard, E2E loses its merge_group trigger). Neither is a required check, so neither gated a merge — CodeQL just ran ~30min and got cancelled at merge every time, and the three E2E jobs burned ~25/36/36min of hosted time, for nothing. They keep running post-merge on push to main.
- macOS/Windows move to merge_group only (they were also running on push to main), and the ubuntu Test job stops running on push too. The queue already tests the merged tree, so re-running these gate jobs on the post-merge push is redundant.

Net: PR runs ubuntu; the merge queue runs ubuntu + integration + mac + win (the gate); push to main runs CodeQL + E2E (the backstop). No job runs in two of those.
2026-06-25 14:09:08 +08:00
易良
bc586362dc
ci: split platform test matrix into named jobs so PRs can enter the merge queue (#5833)
Some checks are pending
Qwen Code CI / Classify PR (push) Waiting to run
Qwen Code CI / Test (ubuntu-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (macos-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (windows-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Blocked by required conditions
Qwen Code CI / Integration Tests (CLI, No Sandbox) (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* ci: stop running push CI on release/** branches

release.yml pushes version + changelog commits to the release branch.
With 'release/**' under the push trigger, that fired a full push-event CI
run (mac/win/CodeQL all run since event != pull_request) on the release
PR's head, blocking it from main's merge queue and double-running the
matrix. Nothing gates on it: release branches have no protection and
publish happens inside release.yml. Keep 'release/**' under pull_request
for backport PRs.

* ci: split platform test matrix into named jobs to unblock merge queue

The macOS/Windows tests are required status checks that only run in the
merge queue (if: event_name != 'pull_request'). As a single matrix job, a
skipped run collapses to one check named 'Test (${{ matrix.os }}, Node
${{ matrix.node-version }})' — so the required contexts 'Test
(macos-latest, Node 22.x)' and 'Test (windows-latest, Node 22.x)' are never
reported on the PR head and sit 'Expected' forever, leaving every PR BLOCKED
and unable to enter the queue (observed on #5830/#5832).

Split into two named jobs. A skipped named job reports under its exact name
(conclusion: skipped), which satisfies the required check on the PR head —
exactly how the merge-queue-only Integration Tests job already behaves — so
PRs can enter the queue, where these jobs run for real and gate the merge.
No PR-stage runner cost (skipped jobs spin no runner); no ruleset change.

* test(ci): update no-AK wiring test for split platform jobs

The test looked up the 'test_platforms' matrix job, which this branch
split into named 'test_macos' / 'test_windows' jobs. Assert the same
properties (no no-AK script, immutable PR-head checkout) on both new jobs.
2026-06-24 15:58:15 +00:00
易良
f6c8ee1e85
ci: move macOS/Windows tests and CodeQL off the per-PR path (#5813)
These three jobs reran on every PR push but rarely caught push-to-push
regressions: macOS/Windows are the slowest, costliest runners and platform
breakage is rare per iteration, and CodeQL findings seldom change between
pushes. Gate all three off the pull_request event so they no longer sit on
every PR's critical path. They still run on push to main (and in the merge
queue once enabled), so platform and security regressions are still caught
before release. The only required status check, Test (ubuntu-latest, Node
22.x), is unaffected and keeps running on PRs.
2026-06-24 10:59:47 +00:00
易良
6d6ffc67b6
ci: harden Linux CI reliability (shallow ECS checkout + CodeQL timeout) (#5810)
Two independent reliability fixes on the Linux CI path:

- test (ubuntu, ECS-routed): fetch-depth 0 -> 1. Nothing in the job walks
  git history (the verify guard checks head.sha == HEAD; schema/tests only
  touch the working tree), so the full-history clone is dead weight. On the
  self-hosted ECS runner it is the heaviest transfer and chokes the squid
  egress proxy, flaking checkout with "Operation too slow" / connect
  timeouts. depth 1 is enough; coverage diffing runs in a separate hosted
  job that checks out on its own.

- codeql: add timeout-minutes: 30. Analysis normally finishes in ~7-9 min
  (22 min worst case observed). Without a cap, a hosted runner that drops
  its heartbeat mid-analysis leaves the job in_progress for the default 6h,
  holding a scarce hosted Linux slot the whole time and starving the queue.
2026-06-24 17:01:58 +08:00
易良
0b5df52908
ci: collapse PR checks into Ubuntu gate (#5767)
* ci: collapse pr checks into ubuntu gate

* ci: keep platform PR tests in matrix

* ci: update no-ak gate wiring test

* ci: bypass stale self-hosted git cache

* ci: refresh self-hosted checkout cache

* ci: refresh pr refs after cached checkout

* ci: fetch fresh pr refs via github url

* ci: retry stale pr merge checkout

* ci: fetch stale pr merge ref directly

* test: isolate qwen serve streaming home

* test: keep qwen serve fake server off proxy

* ci: check out PR head ref to avoid merge-ref lag

The Ubuntu gate kept failing on the self-hosted runner: the PR checkout
used github.ref (refs/pull/N/merge), which GitHub rebuilds asynchronously
and can serve stale for minutes after a push, so the verify guard saw a
tree without the PR head. The retry/refresh machinery added to work
around this could not help — its direct GitHub fetch fallback times out
on the self-hosted squid proxy.

Check out refs/pull/N/head instead (immutable, published the instant the
branch is pushed) for pull_request events in both the test and
test_platforms jobs, and drop the 6-step retry/verify/refresh block. A
single sanity guard stays to fail loud if the head is missing. Non-PR
events keep github.ref; the merge queue validates the merged result.
2026-06-23 22:08:43 +08:00
易良
ac1e473777
ci: retry merge-ref checkout to fix transient "not our ref" failures (#5732)
* ci: check out PR head SHA to avoid missing merge-ref checkout failures

* ci: skip coverage comment on cancelled runs to free concurrency slot

post_coverage_comment used if: always(), so on a cancelled run it still ran
on the hosted pool. During rapid pushes the cancelled run's coverage job sat
queued for a hosted runner, keeping the run non-terminal and holding the
branch concurrency slot — so the next push's required Test (ubuntu-latest)
check waited behind it (observed ~9 min, with thrash). Switch to !cancelled():
coverage still posts on test failure, but a cancelled run releases the slot
immediately. Its coverage would be stale anyway.

* ci(triage): route /triage comment runs to the ECS pool

`/triage` comments trigger the authorize+triage jobs on hosted runners,
which queue behind CI during peak hours (~2 min vs 4 s off-peak observed).
Route the comment-triggered triage job to the ECS self-hosted pool, which
is not bound by the GitHub-hosted concurrency limit.

Safe scope: only `issue_comment` events; the job is read-only and checks
out the base ref (never PR-head code). Gated on the same
MAINTAINER_ECS_RUNNER_DISABLED kill-switch as `authorize`, so a disabled
ECS pool falls back to hosted. PR/issues/dispatch triggers stay hosted.

* ci: fetch PR head by ref name to fix 'not our ref' checkout failure

* ci: align Test checkout ref with Lint (add branch_ref fallback)

On workflow_dispatch the Test job runs (its if: !cancelled() overrides the
implicit success() gate when classify_pr is skipped), so its checkout must
honor the branch_ref input like Lint does. Without it, dispatch runs validated
github.ref in Test while Lint validated the user-supplied branch_ref.

* ci: retry merge-ref checkout instead of pinning PR head; drop /triage ECS routing

Per review feedback: checking out refs/pull/N/head dropped merge-result
validation, and merge queue isn't enabled on main to backstop it. Keep merge-ref
semantics (github.ref) for the required Lint/Test checkouts and retry once to
absorb the transient merge-ref lag the PR-head change was working around.

Also revert /triage routing to ECS: that job runs an agent (sandbox:false,
shell/write tools, repo tokens) over untrusted PR/issue text, so it stays on
ephemeral hosted runners, not the persistent self-hosted pool.

* ci: back off before the merge-ref checkout retry

The merge ref (refs/pull/N/merge) is built asynchronously, so a back-to-back
retry can hit the still-unbuilt ref again. Sleep 10s before retrying so the
retry absorbs the multi-second build lag, not just instantaneous blips.
2026-06-23 16:40:36 +08:00
易良
494db9cec7
ci: harden self-hosted runner routing (follow-up to #5620 review) (#5644)
* ci: harden self-hosted runner routing per #5620 review

Follow-up to #5620 addressing the review findings:

- authorize (pr-review + triage): add the same-repo guard so fork-triggered runs keep CI_BOT_PAT on ephemeral hosted runners; only in-repo PR events use the persistent ECS runner.
- delay-automatic-review: route back to hosted — its 30-minute environment wait timer would otherwise hold a self-hosted ECS slot idle for the whole wait (GitHub allocates the runner before the timer).
- Lint (self-hosted): warn when Node major != 22 (parity with Test) and use 'npm ci --prefer-offline --no-audit --progress=false' for proxy resilience (parity with Test).

Not included: keeping classify_pr on hosted (the SPOF concern) — deliberately left on ECS; the MAINTAINER_ECS_RUNNER_DISABLED kill switch reverts it within ~1 min if ECS is down.

* ci: guard github.event.pull_request before deref in authorize runner selection

Addresses Copilot's review note on #5644. GitHub Actions expression property access is already null-safe (a missing github.event.pull_request yields null, not an evaluation error), so non-PR events (issue_comment/workflow_dispatch) already fell back to hosted. This makes the fallback explicit and silences the recurring reviewer concern; no behavior change.
2026-06-22 21:42:59 +08:00
易良
7696d9a7d9
ci: route in-repo PRs' Linux test to self-hosted runner (#5620)
* ci: route in-repo PRs' Linux test to self-hosted runner

Send the required Linux Test job to the self-hosted ECS runner for PRs whose head branch lives in this repo (which implies the author had write access), while forks and push/merge_group runs stay on GitHub-hosted runners. This lets maintainer changes skip the shared hosted Linux queue without ever running untrusted fork code on self-hosted infrastructure. The MAINTAINER_ECS_RUNNER_DISABLED repo variable forces everything back to hosted if the ECS runner is unavailable.

* ci: reuse pre-installed Node on self-hosted runners, route Lint to ECS

The self-hosted ECS runners cannot reliably download the Node tarball from nodejs.org through the egress proxy (actions/setup-node aborts mid-download), which failed the Test job routed there. On self-hosted runners, reuse the machine's pre-installed Node instead of re-downloading it every run; hosted runners keep using actions/setup-node. Also route the Lint job to ECS for in-repo PRs — scripts/lint.js already skips installing actionlint/shellcheck/yamllint when they are on PATH, so no lint.js change is needed.

* ci: trim verbose runner-routing comments

* ci: run classify_pr gate on ECS for in-repo PRs

* ci: quote classify_pr/lint runs-on expressions

* ci: keep Lint on hosted runners (ECS proxy truncates linter downloads)

* ci: route Lint and review/triage gate jobs to self-hosted runner

Lint goes back to ECS (linters are now pre-installed on the runners, so scripts/lint.js skips downloading them). The pr-review gate jobs (authorize, review-config, delay-automatic-review, ack-review-request) and the triage authorize gate also move to ECS so the ECS heavy jobs (review-pr, tmux-testing) are no longer bottlenecked by the shared hosted queue. All respect the MAINTAINER_ECS_RUNNER_DISABLED kill-switch.
2026-06-22 20:28:27 +08:00
易良
580a72410f
test(integration): run no-AK smoke tests on PRs (#5607)
* test(integration): run no-AK smoke tests on PRs

* test(integration): isolate qwen serve routes auth
2026-06-22 19:41:32 +08:00
qqqys
b9c5e3566b
feat(voice): voice dictation with native capture, streaming, and biasing (#5502)
* feat(voice): voice dictation with native capture, streaming, and biasing

Add voice dictation for the prompt input:
- /voice [hold|tap|off|status] command + general.voice.{enabled,mode,language,protocol} settings; push-to-talk via Space, /model --voice to pick the model
- Native microphone capture (@qwen-code/audio-capture, miniaudio N-API) with arecord/SoX fallback, silence auto-stop, cold-start warm-up, and macOS permission query
- Batch transcription via DashScope Qwen-ASR (OpenAI-compatible chat/completions + input_audio) with language + keyterm biasing and an echo guard
- Live streaming over the DashScope realtime WebSocket (fun-asr-realtime / paraformer-realtime-v2) with interim text and an input-level waveform, behind voice.protocol=dashscope-realtime
- Rich VoiceIndicator UI (state, level meter, live partial transcript)
- Cross-platform prebuilds via prebuildify + node-gyp-build and a CI matrix

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

* feat(cli): route voice ASR by model

* feat(cli): polish voice realtime parity

* ci: fix voice workflow checks

* fix(cli): address voice review blockers

* fix(cli): harden voice transcription failures

* fix(cli): address voice PR review blockers

* fix(cli): harden voice review follow-ups

* fix(voice): handle realtime review blockers

* fix(cli): add voice command i18n keys

* fix(cli): address voice review blockers

* fix(cli): address voice review follow-ups

* fix(voice): harden review edge cases

* fix(voice): address release and realtime review blockers

* fix(voice): address realtime suggestion followups

* fix(voice): handle realtime review followups

* fix(voice): address realtime review blockers

* fix(voice): address review feedback

* fix(voice): address recorder review feedback

* docs(voice): document ssrf guard boundary

* fix(voice): address review feedback

* fix(voice): preserve warm recorder session safety

* fix(voice): address stream review suggestions

* fix(voice): address multi-round review findings

Realtime/streaming:
- Salvage an already-committed transcript when the WebSocket closes right
  after finish() instead of rejecting the whole dictation
  (qwenAsrRealtimeSession, voiceStreamSession) + regression tests.

useVoiceInput state machine:
- Single-shot finalize guard so a tap-stop racing the silence auto-stop can't
  double-stop the recorder and surface a spurious failure.
- Reset mountedRef on (re)mount so StrictMode (DEBUG) can't freeze the voice UI.
- Widen the hold-mode first-press release window above common key-repeat delays.

Model selection:
- Reject ids with no ASR transport at /model --voice and in the model dialog via
  a new isSelectableVoiceModel; move resolveVoiceTransport into voiceModel so the
  record-time config resolver stays transport-agnostic (+ tests).

macOS mic permission:
- Surface the not-determined state in voice warmup so the first dictation isn't
  silently lost behind the TCC dialog.

Native packaging:
- Make the audio-capture native install non-fatal (falls back to SoX/arecord) so
  a voice-only build failure can't break npm ci.
- Download audio-capture prebuilds before building standalone release archives.

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

* fix(voice): address review blockers

* fix(voice): update batch recording audio level

* fix(voice): tap-mode transcript loss, stream leaks, and dead keyterm cleanup

- Tap-mode dictation submitted a stale empty buffer.text, wiping the just-
  inserted transcript and sending nothing: thread the resulting prompt text
  through onSubmit(text) instead of reading buffer.text back synchronously
  after the async insert (useVoiceInput, InputPrompt).
- Streaming finalize leaked the WebSocket session when recorder.drain() threw:
  abort the session before propagating the error.
- voiceStreamSession: reject the connect promise when 'task-finished' arrives
  before 'task-started' instead of hanging forever in 'transcribing'.
- Remove dead keyterm enrichment (project/branch/recent-file paths were
  unreachable after the privacy fix) and the now-inert CJK echo guard, plus the
  tests that asserted that removed behavior; fix the misleading "OpenAI prompt
  field" comment.
- Add the missing 'Voice Model' and macOS mic-permission i18n keys to
  en/zh/zh-TW (they were falling back to English; check-i18n doesn't flag keys
  absent from en).

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

* fix(voice): reject partial stream transcripts

* fix(cli): let dialogs consume voice keys first

* fix(voice): reject incomplete qwen realtime transcripts

* fix(voice): handle stream review blockers

* fix(voice): salvage qwen realtime transcript on close

* fix(voice): sanitize streamed transcript text

* test(audio): run audio capture tests in CI

* fix(voice): address review blockers

* fix(voice): report stream close while recording

* fix(voice): reduce keyterm echo false positives

* fix(voice): handle realtime close diagnostics

* fix(voice): address realtime review blockers

* fix(lint): allow legacy voice filenames

* chore(cli): rename voice files to kebab-case

---------

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-06-22 14:33:36 +08:00
易良
cf0d9be585
ci(release): report required Test checks on release PRs and auto-approve (#5250)
* ci(release): report required Test checks on release PRs and auto-approve

Release-sync PRs skipped the matrix Test job at job level, so the required "Test (os, Node 22.x)" contexts were never reported and the PR could not merge. Move the skip to step level so the job still expands its matrix and concludes as a work-free pass. Also add a CI_DEV_BOT_PAT approval on the release PR to cover one of the two required reviews.

* ci: single-quote the test job if expression for yamllint

After dropping the inner 'true' comparison, double quotes are no longer required, so yamllint's quoted-strings rule wants single quotes.
2026-06-17 22:30:04 +08:00
易良
004b8bd156
ci: run CLI integration tests in the merge queue (#5224)
Some checks are pending
Qwen Code CI / Classify PR (push) Waiting to run
Qwen Code CI / Lint (push) Blocked by required conditions
Qwen Code CI / Test (macos-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (ubuntu-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (windows-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Blocked by required conditions
Qwen Code CI / Integration Tests (CLI, No Sandbox) (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
Integration tests (integration-tests/) previously ran only in the nightly
Release pipeline, so a PR that broke them merged green and the failure stayed
hidden until release time. Add a merge_group-gated job that runs the existing
test:integration:cli:sandbox:none suite, catching regressions before the PR
lands on main.

Gated on github.event_name == 'merge_group' so it does not touch the per-PR
critical path, and is a no-op until merge queue is enabled on main. Reuses the
OPENAI_* secrets already wired for the release integration jobs.

Refs #5219
2026-06-17 15:47:56 +08:00
Dragon
62e45c567f
feat(desktop): Add desktop app package with Qwen ACP SDK integration (#3778) 2026-06-11 21:57:20 +08:00
易良
2b541f5e9e
Align automated PR review with bundled skill (#4843)
* ci(review): align automated review with bundled skill

* ci(review): trigger when bot review is requested

* ci(review): disable deployment records for review delay

* ci: sync actionlint version env

* ci(review): authorize requested review trigger

* ci(review): centralize review bot login

* ci(review): narrow review config trigger

* ci(review): isolate comment review concurrency

* ci(review): surface reviewer permission check failures

* fix(ci): use exit 0 on permission check API failure

When the GitHub API call to check requester permission fails, the job
should still complete successfully since should_review=false is already
set. Using exit 1 marks the job as failed, which blocks the downstream
review-pr job even with always() — a transient API outage would silently
prevent all reviews.

* fix(ci): only cancel-in-progress on synchronize events

Restrict cancel-in-progress to push (synchronize) events so that
review_requested events (adding a human reviewer) don't accidentally
cancel an in-progress bot review run sharing the same concurrency group.
2026-06-08 20:52:53 +08:00
Salman Chishti
70eecdbdf4
Upgrade GitHub Actions for Node 24 compatibility (#1876)
Signed-off-by: Salman Muin Kayser Chishti <13schishti@gmail.com>
2026-05-12 15:02:33 +08:00
易良
576bd8e0a7
ci: skip unnecessary release and SDK checks (#3984)
* ci: skip unnecessary release and SDK checks

* ci: guard release skip classification for non-pr events

* ci: harden release sync skip gate

* ci: refine release sync skip fallback
2026-05-11 13:20:20 +08:00
易良
983322b1df
ci: reduce PR test matrix runtime (#3962) 2026-05-08 22:15:20 +08:00
jinye
4e0a37549d
fix(i18n): sync mismatched keys between en.js and zh.js (#3534)
Some checks are pending
Qwen Code CI / Lint (push) Waiting to run
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Test-1 (push) Blocked by required conditions
Qwen Code CI / Test-2 (push) Blocked by required conditions
Qwen Code CI / Test-3 (push) Blocked by required conditions
Qwen Code CI / Test-4 (push) Blocked by required conditions
Qwen Code CI / Test-5 (push) Blocked by required conditions
Qwen Code CI / Test-6 (push) Blocked by required conditions
Qwen Code CI / Test-7 (push) Blocked by required conditions
Qwen Code CI / Test-8 (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
* fix(i18n): sync mismatched keys between en.js and zh.js (#3503)

Add 4 keys missing from en.js that are actively used in source code,
add 5 missing Chinese translations to zh.js, integrate check-i18n
into CI to prevent future drift, and skip JSON file write in CI to
avoid dirtying the working tree.

---
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-04-24 00:38:32 +08:00
DragonnZhang
585081e7de feat: add CLI package build and settings schema validation to CI workflow 2026-02-26 16:10:14 +08:00
tanzhenxin
eb95c131be
Sync upstream Gemini-CLI v0.8.2 (#838) 2025-10-23 09:27:04 +08:00
Yiheng Xu
010ad5ddc4
Terminal Bench Integration Test (#521)
Some checks failed
Qwen Code CI / Lint (GitHub Actions) (push) Has been cancelled
Qwen Code CI / Lint (Javascript) (push) Has been cancelled
Qwen Code CI / Lint (Shell) (push) Has been cancelled
Qwen Code CI / Lint (YAML) (push) Has been cancelled
Qwen Code CI / CodeQL (push) Has been cancelled
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Has been cancelled
E2E Tests / E2E Test (Linux) - sandbox:none (push) Has been cancelled
E2E Tests / E2E Test - macOS (push) Has been cancelled
Qwen Code CI / Lint (push) Has been cancelled
Qwen Code CI / Test (push) Has been cancelled
Qwen Code CI / Post Coverage Comment (push) Has been cancelled
* integrate terminal bench

* fix ci

* add ci

* fix ci

* fix ci

* parallel ci

* handle timeout

* fix lint

* trigger
2025-09-05 17:02:03 +08:00
tanzhenxin
2572faf726
# 🚀 Sync Gemini CLI v0.2.1 - Major Feature Update (#483)
Some checks are pending
Qwen Code CI / Lint (GitHub Actions) (push) Waiting to run
Qwen Code CI / Lint (Javascript) (push) Waiting to run
Qwen Code CI / Lint (Shell) (push) Waiting to run
Qwen Code CI / Lint (YAML) (push) Waiting to run
Qwen Code CI / Lint (push) Blocked by required conditions
Qwen Code CI / Test (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run
2025-09-01 14:48:55 +08:00
tanzhenxin
1baf5d795f
Fix GitHub Workflows Configuration Issues (#451) 2025-08-26 16:54:52 +08:00
tanzhenxin
0f3db5275f chore: fix lint errors for shell scripts and yaml files 2025-08-22 11:35:35 +08:00