mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-11 17:43:43 -10:00
feat/btw-qodercli-alignment
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5b470befa0 |
ci: make the Prettier lane a real gate (#11117)
* chore: format the 35 files CI had been silently rewriting `scripts/lint.js --prettier` and the release workflow's `Format Project` step both run `prettier --write`, which reformats in place and exits 0. Neither is followed by a dirty-tree check, so the rewrites are discarded when the job ends and these files have stayed unformatted on `main`. This is the output of `prettier --write` over exactly those files, so the next commit can turn the check into a real gate without failing on a backlog. No behaviour change: every hunk is whitespace, quoting or wrapping. Verified with prettier 3.6.1, the version pinned in package-lock.json. `prettier --check .` over the whole repo reports these 35 and nothing else. Refs #11109 * fix(ci): make the Prettier lane a real gate `runPrettier()` ran `prettier --write .`. Prettier exits 0 after reformatting, and no caller checks the tree afterwards, so the lane passed on unformatted code and CI threw the rewrites away — the 35 files in the previous commit are what it had been silently fixing and discarding. ESLint does not cover the gap: eslint.config.js loads eslint-config-prettier, which disables formatting rules rather than enforcing them. With this change the only enforcement point outside the husky pre-commit hook actually enforces something. `npm run lint:all` now reports unformatted files instead of fixing them; `npm run format` is the fix. Prettier's own failure message says so. Refs #11109 * fix(release): drop Format Project, it writes and discards The step ran `npm run format` (`prettier --write .`) and nothing in release.yml inspected the tree afterwards — no `git diff --exit-code`, no `git status --porcelain` anywhere in the file. The rewrites died with the job, so the only failure it could produce was Prettier crashing on an unparsable file, which the Run Lint step reports anyway. It cost 13m58s on a quiet host and 20m45s on a contended one, against a 30-minute cap that `quality_static` hit twice today (runs 33957952281 and 33963757913, both cancelled mid-lint with nothing failing). The remaining steps are `npm ci` (1m44s) and `lint:ci` (~8m20s), so the job now has real headroom instead of finishing 24 seconds over the wall. Formatting is now gated where it belongs: the previous commit makes the PR-CI Prettier lane `--check`. Refs #11109 * fix(ci): keep prettier --check out of .qwen/ and the pre-paint theme script Two things the `--write` → `--check` flip broke that `--write` had hidden. `.qwen/` is gitignored as `.qwen/*` and holds machine-written state — pending-skills/, auto-skill-*/, learned-skill-*/, computer-use/installed.json. Prettier does not read .gitignore, so it was walking in and silently reformatting whatever a contributor had there; under `--check` that turns into a failed `npm run lint:all` on files git does not even track. CI never saw it (fresh checkout, tracked files only), which is exactly why it went unnoticed. Adding `.qwen/` to .prettierignore also drops the one tracked file under it — skills/find-simplifications/SKILL.md, force-added past .gitignore — from the previous formatting commit, since a directory the gate should not police should not be reformatted for it either. The inline theme script in web-shell's index.html is restored to its original single line behind `<!-- prettier-ignore -->`. It is a render-blocking script in <head> that applies the stored theme before first paint; the expanded form ships ~600 more bytes on the critical path and buys no readability the comment above it does not already give. A change about CI hygiene should not be reshaping that. Refs #11109 * fix(ci): keep prettier --check out of vendored packages/mobile-mcp eslint.config.js has ignored `packages/mobile-mcp/**` since it landed — "vendored mobile-next/mobile-mcp; has own eslint config" — and .prettierignore already carries its sibling `packages/cua-driver/`, listed one line above with the same rationale. mobile-mcp was simply missed. `--write` hid that: it reformatted the vendored package's own eslint config to our house style every run and threw the result away. The formatting commit in this PR would have made that permanent, widening the diff against upstream on the next sync for a package this repo has already decided not to lint. That file is reverted here and the directory is ignored. Same class as the .qwen/ fix in the previous commit: the gate reaching somewhere the repo had already decided it should not. Refs #11109 * fix(ci): mirror eslint's remaining global ignores in .prettierignore `--check` makes .prettierignore load-bearing in a way `--write` never was: under `--write` a file prettier should not touch was reformatted and the result discarded, so nobody noticed; under `--check` it fails the lane. These three are the rest of eslint.config.js's global ignores, added for the reasons it already states. `scripts/codemod/fixtures/` is the one that matters: those files are "intentionally non-idiomatic ink input/output", so the obvious response to a `--check` failure there — reformat to house style — would corrupt the fixtures the codemod tests assert against. The trap is not live today (all three currently satisfy prettier), which is precisely why it is worth closing before someone meets it. Refs #11109 * chore: format converter.test.ts, which drifted onto main since this branch This branch merged main 32 commits after its base and `prettier --check .` found one new offender. It is the same gate failing the same way: nothing enforces formatting, so `--write` reformatted this file on every CI run since it landed and threw the result away. Worth noting as evidence rather than noise — the backlog this PR fixes was not a one-off from before someone got careless; it accrues continuously, and it accrued again while the PR was open. Refs #11109 * Revert "fix(release): drop Format Project, it writes and discards" This reverts the release.yml half of this PR. #11195 removes that step on its own, in one file and four lines, and two PRs racing on the same deletion helps nobody. The reasoning and the evidence are unchanged and now live on #11195: the dry-run release dispatched from this branch with the step removed (34022919438) went 18/18 green in 65m43s, quality_static finished in 7m00s against main's 8m57s, and Run Lint was 4m52s vs 4m43s — nothing downstream ever read what the step produced. Dropping release.yml from this PR also widens who can review it. It was the only file here owned by @pomelo-nwu and @wenshao alone; what remains under CODEOWNERS is /packages/core/, whose owner list is six people. The Prettier gate no longer waits on the two maintainers who must sign off on release workflow changes. Refs #11109, #11195 * fix(ci): make the gate resolve the file set npm run format resolves Two review findings, one root cause: the gate was checking a different set of files than the tree it is supposed to police. **The `.qwen/` ignore rested on a false premise (R1-1, @chiga0).** Prettier 3.6's `--ignore-path` already defaults to `[.gitignore, .prettierignore]`, so every machine-written path that entry's comment named — `pending-skills/`, `auto-skill-*/`, `learned-skill-*/` — was outside the gate before it via `.gitignore:32`. What the entry actually excluded is the corpus `.gitignore` deliberately re-includes: `.qwen/commands/**`, `skills/**`, `agents/**`, `team-memory/**`, `review-context.json` — 57 tracked, hand-authored files. The gate then passed because the surface had been narrowed, not because the tree was formatted, and contributors editing those docs could ship them unformatted with both enforcement points silent. The entry is dropped and the first commit's formatting of `skills/find-simplifications/SKILL.md`, reverted alongside it, is re-landed. **The gate and the remedy used different CLIs (R1-2).** `runPrettier()` ran the classic `prettier --check .` while `npm run format` runs `prettier --experimental-cli --write .`. The classic CLI reads only the repo-root `.gitignore`; the experimental one also honours nested ones, and this repo has 23 of those. Verified on a scratch tree: given `pkg/.gitignore` containing `lib/`, classic reports `pkg/lib/nested.js` and experimental skips it. So the lane could go red on a locally built package's output that `npm run format` provably cannot clear. The gate now uses the same CLI as the remedy it names. Refs #11109 * fix(ci): let the pre-commit hook cover what the gate now checks, and pin it **The hook was narrower than the gate (R1-5).** `lint-staged` formatted only `*.{js,jsx,ts,tsx}` and `*.{json,md}`, but the gate checks every extension Prettier has a parser for. Of the 35 files the first commit formatted, 29 (83%) are in classes the hook never touched — 13 `.yml`, 12 `.mjs`, 3 `.css`, 1 `.html`. Left alone, the backlog this PR just cleared would re-accumulate, and now as a red CI step on someone else's PR rather than as silent drift. `.mjs`, `.cjs`, `.yml`, `.yaml`, `.css` and `.html` join the Prettier-only group; ESLint's globs are unchanged, since the gap is about formatting coverage, not lint coverage. **Nothing pinned the flag (R1-4).** `scripts/tests/lint.test.js` exercised only the linter-directory helpers, and `ci-platform-lanes.test.js` asserts that the `Run Prettier` step exists and is profile-gated, not what it runs. A refactor, or a well-meant "make lint auto-fix again", could restore the silent pass with every suite green. Two assertions now pin it: that `runPrettier()` checks rather than writes, and that it uses the same Prettier CLI as `npm run format`, so the two cannot drift apart again the way R1-2 found them. Refs #11109 * docs: correct the instructions and comments the --check flip falsified **Three tracked instructions to automation agents now say the opposite of what the code does (R1-9), and one is fed to a CI lane today** — `.github/workflows/qwen-triage.yml` re-pins `verify-pr` from the base commit and hands it to the verifying agent. - `verify-pr/SKILL.md` told agents never to run `scripts/lint.js` with no arguments because it would rewrite the working tree under their A/B harness. That is no longer why. The prohibition is kept — it is still right — but re-grounded in what the no-arg form actually does now (`setupLinters()` wipes the linter temp dir and re-downloads three pinned binaries), and `--prettier` joins the enumerated non-mutating checks it was the only flag missing from. - `find-simplifications/SKILL.md` and its `references/land.md` told the simplification agent that a formatting diff "carries zero signal" because CI runs `--write`. An agent believing that would skip `npm run format` after a deletion changed line shape — on the very extensions the hook does not cover — and go red on formatting it was told could not matter. - `update-ecs-runner-qwen-workflow.test.js`'s comment justified parsing two matrix layouts by "CI runs `prettier --write .` before this suite". CI no longer rewrites anything; the two layouts are still worth parsing, so the comment is re-grounded in the checked-in form versus older branches. **The index.html rationale overstated its own number (R1-8, @chiga0).** It claimed the expanded script ships "~600 more bytes"; measured against this repo's Prettier 3.6.1 and its `tabWidth: 2`, it is +258 source and +8 gzipped here, +287/+20 by the reviewer's method — either way roughly half what was claimed, and "~600" is what the same expansion costs at `--tab-width 4`. Since the prose ships verbatim inside the built `index.html`, the fix is to drop the contested figure and keep the comment short. The `<!-- prettier-ignore -->` guard itself stays: it is load-bearing. Refs #11109 * chore: format classify-profile.test.mjs, drifted again after commit 1 Third instance in this PR's lifetime, and the sharpest: commit `b1b94a8762` formatted this exact file as one of the 35, and `main` reintroduced unformatted content in it within a day. The other two were `converter.test.ts` at the first merge and this file at the second. The gate is the fix; until it lands, every merge from `main` re-opens the same hole. Refs #11109 |
||
|
|
27285a5243 |
refactor: centralize approval mode contracts (#9796)
* refactor: centralize approval mode contracts * fix: align Python SDK import grouping * test: restore approval mode exports in CLI mocks * fix: close approval mode drift gaps * test(cli): preserve core exports in serve mocks * fix: close approval mode review gaps * test(cli): complete permission request fixture * test(sdk): match approval mode route * test(approval): close review coverage gaps * test(sdk): cover approval mode global scope path |
||
|
|
fb6637f0d3 |
chore(ci): Add security hygiene: CODEOWNERS for release workflows, least-privilege permissions, security checks and Scorecard (#9008)
* chore(ci): add security hygiene: CODEOWNERS for release workflows, least-privilege permissions, security checks and scorecard workflows * chore(ci): pin TruffleHog scanner version and drop invalid path input * fix(ci): close security workflow review gaps * fix(ci): fail package audit on install errors * test(ci): pin security workflow guardrails * fix(ci): pin security workflow test assertions for SHA refs, status edges, and push trigger * test(ci): pin security workflow edge guards * test(ci): pin security workflow contracts * test(ci): pin secret-scan push guard * fix(ci): quote secret-scan condition * fix(ci): audit workspace package locks directly * fix(ci): scope security checks concurrency * docs(ci): explain mobile audit skip * test(ci): link trufflehog version pin |
||
|
|
df6be035e1 |
Upgrade GitHub Actions for Node 24 compatibility (#5157)
* Upgrade GitHub Actions for Node 24 compatibility Signed-off-by: Salman Muin Kayser Chishti <[email protected]> * ci: update remaining checkout pins --------- Signed-off-by: Salman Muin Kayser Chishti <[email protected]> Co-authored-by: qwen-code-dev-bot <[email protected]> Co-authored-by: 易良 <[email protected]> Co-authored-by: yiliang114 <[email protected]> |
||
|
|
70eecdbdf4 |
Upgrade GitHub Actions for Node 24 compatibility (#1876)
Signed-off-by: Salman Muin Kayser Chishti <[email protected]> |
||
|
|
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 |
||
|
|
03f66bada5 |
feat(sdk-python): add PyPI release workflow (#3685)
* feat(sdk-python): add pypi release workflow Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): build cli before smoke test Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): tighten release conflict handling Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): harden python release workflow Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): tighten stable release guards Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): harden prerelease publish flow Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): reuse release branches on rerun Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): resume incomplete releases Co-authored-by: Qwen-Coder <[email protected]> * fix(release): tighten missing-release checks Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): resume stable release reruns Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): tighten release recovery guards Co-authored-by: Qwen-Coder <[email protected]> * test(sdk-python): cover release version edge cases Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): address release workflow review feedback Co-authored-by: Qwen-Coder <[email protected]> * refactor(sdk-python): address review feedback on release version script - Remove unreachable `if (type === 'stable')` branch in bumpVersion(); the stable path was dead code since getVersion() throws for all stable conflicts before calling bumpVersion(). Move nightly conflict throw to the call site for symmetry. - Rename getNextPatchBaseVersion → getNextBaseVersion to reflect that the function can return a prerelease base without incrementing patch. - Add test for preview+nightly coexistence where nightly base is higher. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): address remaining review feedback on release workflow - Fix failure-issue gate to read github.event.inputs.dry_run directly instead of steps.vars.outputs.is_dry_run (which is empty when early steps fail). Add --repo flag for gh issue create when checkout failed. - Add diagnostic state table to failure-issue body (RELEASE_TAG, PACKAGE_VERSION, PUBLISH_CHANNEL, RESUME_EXISTING_RELEASE, etc.) - Fix release-notes error swallow: only silence release not found / Not Found / HTTP 404, emit ::warning:: for other gh release view errors. - Improve validateVersion error messages to use human-readable format keys (X.Y.Z, X.Y.Z-preview.N) matching TS sibling convention. - Filter fully-yanked versions in getAllVersionsFromPyPI. - Add console.error log when stable is derived from nightly. - Add bash regex guard for inputs.version to prevent shell injection. - Use per-release-type concurrency groups (nightly/preview/stable). - Add jq null-guard checks for all 6 field extractions. - Remove misleading --follow-tags from git push (lightweight tags). 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): rename misleading test description The test asserts that preview/nightly releases return empty previousReleaseTag, but the name said "same-channel previous release tags" which implied non-empty values. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): address unresolved review comments on release workflow - Remove -z check in extract_field() that blocked preview/nightly releases (previousReleaseTag is legitimately empty for non-stable releases) - Use static environment.url since step outputs aren't available at job startup - Use skip-existing for resumed PyPI publish to fill in missing artifacts - Add AbortSignal.timeout(30s) to PyPI fetch to prevent indefinite hangs - Add downgrade guard for stable_version_override - Use GHA ::warning:: annotation instead of console.error for visibility - Separate yanked/non-yanked version lists so conflict detection includes yanked versions (PyPI still reserves those slots) - Filter current release from previousReleaseTag to avoid self-reference on resume - Add tests for yanked conflict detection, downgrade guard, and resume previousReleaseTag Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): address final review round on release version script - Fix getNextBaseVersion() first-release skip: use pyproject.toml version directly when PyPI has no stable versions instead of unconditionally incrementing - Fix getNextBaseVersion() off-by-one: change > to >= so equal prerelease base continues the existing line instead of incrementing patch - Add ::warning:: annotation when preview auto-bumps due to orphan git tags (tag exists without PyPI version or GitHub release) - Add set -euo pipefail to 5 workflow steps missing it: release_branch, persist_source, Create GitHub release, Delete prerelease branch, Create issue on failure - Fix 2 existing tests affected by first-release change, add 4 new tests 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) * fix(sdk-python): use stderr for GHA warning annotations to avoid corrupting JSON stdout console.log writes to stdout, which gets captured by VERSION_JSON=$(node ...) in the workflow and corrupts the JSON output for jq. Switch to console.error so ::warning:: annotations go to stderr (GHA recognizes workflow commands on both streams). Also add set -euo pipefail to the "Get the version" step for consistency with other workflow steps. 🤖 Generated with [Qwen Code](https://github.com/QwenLM/qwen-code) --------- Co-authored-by: jinye.djy <[email protected]> Co-authored-by: Qwen-Coder <[email protected]> |
||
|
|
e384338145 |
feat(SDK) Add Python SDK implementation for #3010 (#3494)
* Codex worktree snapshot: startup-cleanup Co-authored-by: Codex * Add Python SDK real smoke test Adds a repository-only real E2E smoke script for the Python SDK, plus npm and developer documentation entry points. Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): address review findings — bugs, type safety, and test coverage - Fix prepare_spawn_info: JS files now use "node" instead of sys.executable - Fix protocol.py: correct total=False misuse on 7 TypedDicts (required fields were optional) - Fix query.py: add _closed guard in _ensure_started, suppress exceptions in close() - Fix sync_query.py: prevent close() deadlock, add context manager, add timeouts - Fix transport.py: handle malformed JSON lines, add _closed guard in start() - Fix validation.py: use uuid.RFC_4122 instead of magic UUID - Fix __init__.py: export TextBlock, widen query_sync signature - Remove dead code: ensure_not_aborted, write_json_line, _thread_error - Add 12 new tests (29 → 41): context managers, JSON skip, closed guards, spawn info, timeouts Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): address wenshao review — session_id, bool validation, debug stderr - Fix continue_session=True generating a wrong random session_id - Add _as_optional_bool helper for strict type validation on bool fields - Default debug stderr to sys.stderr when no custom callback is provided Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): address remaining wenshao review feedback Co-authored-by: Qwen-Coder <[email protected]> * test(cli): harden settings dialog restart prompt test Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): review fixes — UUID compat, stderr fallback, sync cleanup - Remove UUID version restriction to support v6/v7/v8 (RFC 9562) - Always write to sys.stderr when stderr callback raises (was silent when debug=False) - Prevent duplicate _STOP sentinel in SyncQuery.close() via _stop_sent flag - Add ruff format --check to CI workflow - Fix smoke_real.py version guard: fail early before imports instead of NameError - Apply ruff format to existing files Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): remaining review fixes — exit_code attr, guard strictness, sync timeout - Add exit_code attribute to ProcessExitError for programmatic access - Strengthen is_control_response/is_control_cancel guards to require payload fields, preventing misrouting of malformed messages - Expose control_request_timeout property on Query so SyncQuery uses the configured timeout instead of a hardcoded 30s default - Use dataclasses.replace() instead of direct mutation on frozen-style QueryOptions in query() factory - Add ResourceWarning in SyncQuery.__del__ when not properly closed Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): add exit_code default and guard __del__ against partial GC - Give ProcessExitError.exit_code a default value (-1) so user code can construct the exception with just a message string - Wrap SyncQuery.__del__ in try/except AttributeError to prevent crashes when the object is partially garbage-collected Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): review fixes — resource leak, type safety, CI matrix, docs - Fix SyncQuery.__del__ to call close() on GC instead of only warning - Replace hasattr duck-type check with isinstance(prompt, AsyncIterable) - Type-validate permission_mode/auth_type in QueryOptions.from_mapping - Use TypeGuard return types on all is_sdk_*/is_control_* predicates - Add 5s margin to sync wrapper timeouts to prevent error type masking - Expand CI matrix to test Python 3.10, 3.11, 3.12 - Change ProcessExitError.exit_code default from -1 to None - Add stderr to docs QueryOptions listing - Update README sync example to use context manager pattern Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): preserve iterator exhaustion state and suppress detached task warning - Add _exhausted flag to Query.__anext__ and SyncQuery.__next__ so repeated iteration after end-of-stream raises Stop(Async)Iteration instead of blocking forever. - Remove re-raise in _initialize() to prevent asyncio "Task exception was never retrieved" warning on detached tasks; the error is already surfaced via _finish_with_error(). Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): reject mcp_servers at validation time and add iterator/init tests - Reject mcp_servers in validate_query_options() with a clear error instead of advertising MCP support to the CLI and then failing at runtime when mcp_message arrives. - Remove dead mcp_servers branch from _initialize(). - Add tests for async/sync iterator exhaustion, detached init task warning suppression, and mcp_servers validation. Co-authored-by: Qwen-Coder <[email protected]> * fix(sdk-python): fix ruff lint errors in new tests - Use ControlRequestTimeoutError instead of bare Exception (B017) - Fix import sorting for stdlib vs third-party (I001) - Break long line to stay within 88-char limit (E501) Co-authored-by: Qwen-Coder <[email protected]> * style(sdk-python): apply ruff format to new tests Co-authored-by: Qwen-Coder <[email protected]> --------- Co-authored-by: jinye.djy <[email protected]> Co-authored-by: Qwen-Coder <[email protected]> |