mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
* feat(cli): support exact-version updates without npm discovery * fix(cli): repair build and close exact-version update review gaps (#11486) The merge into this branch left two copies of the semver default import in standalone-update.ts, so packages/cli no longer compiled (TS2300) and every downstream gate went red. Drop the added duplicate, keeping main's import position. Also address the remaining review findings on the exact-version update: - Verify the extracted archive's manifest.json version matches the requested version before activation, alongside the existing executable smoke test. The manifest is the field the installation reads back and the prepared-update gate compares against; an inflated manifest version would otherwise silently freeze all future prepared updates. - Pin the yargs builder contract: --target-version must reach the handler as argv.targetVersion under the production .strict() parser, going red if the builder is dropped or the option renamed. - Add the issue #11484 acceptance-criterion-7 E2E test: update a disposable standalone install to an exact version served from a local HTTPS release root while the npm registry sink records zero requests, asserting the installed manifest version and rollback retention. - Document that an explicit target is not persisted: automatic updates move a standalone install forward again next session, and keeping an exact older version requires general.enableAutoUpdate: false. - Add the Chinese version of the design doc with reciprocal language links. * fix(cli): close standalone update review gaps from round 2 (#11486) Address the second-round review findings on the exact-version update: - Validate the extracted archive's full manifest identity (name, target, version) before activation instead of version alone. A mirror artifact with the right version but no name passed every check and installed, after which the directory silently stopped classifying as a managed standalone install; the gate now rejects it and preserves the install. - Guard both version comparisons with normalizeVersion's own predicates (SEMVER_RE and semver.valid), so a regex-valid but semver-invalid version like 01.2.3 hits the intended mismatch message instead of throwing "Invalid version format" out of the comparison. - Rename the manifest gate's message to name the archive check rather than the smoke test, which has not run yet at that point. - Make the target-version E2E hermetic: pin QWEN_REQUIRE_SIGNATURE, QWEN_CODE_LANG, and QWEN_HOME per spawn (witnessed by staging hostile ambient values inside the test), re-seed the fixture installation in beforeEach so vitest task retries never inherit the post-activation tree, and guard the afterAll server-close promises so an early beforeAll failure no longer hangs the hook and leaks the scratch root. - Pin the documented "explicit targets permit same-version reinstalls and downgrades" guarantee with performStandaloneUpdate cases that go red if the prepared-route staleness check ever moves into the shared path. - Correct the fixture's header comment: local-git-clone classification requires the resolved CLI path inside the cwd, not merely a cwd inside a git worktree. * fix(cli): close standalone archive gate review gaps from round 3 (#11486) Validate the archive's runtime flavor and executable layout against the installed build before activation, share one version predicate and one runtime-layout predicate instead of hand-inlined copies, give every gate predicate a discriminating test, keep the E2E registry sink honest with a discovery control, and document the manifest identity contract. * fix(cli): pin the git shim's module scope in the reverse-apply screen test (#11486) The test shadows git with an extensionless Node shim under tmpdir. Node derives the module system of an extensionless file from the nearest ancestor package.json, so a "type": "module" package.json above tmpdir (the runner image ships /tmp/package.json) loads the CJS shim as ESM: it dies on "require is not defined" before forwarding to real git, the restore's ls-files -v spawn never arms the stamp, and the screen test fails without the screen ever being asked. Pin {"type":"commonjs"} in the shim directory so the shim loads the way its body is written, regardless of what sits above tmpdir. * fix(cli): flavor-aware standalone archive routing and launcher entry-point gate (#11486) Co-authored-by: Qwen-Coder <[email protected]> * fix(cli): sanitize --target-version rejection echo and bun test fixture normalizeVersion throws with the raw flag value interpolated, and the new --target-version error path echoed it to stderr unsanitized, so terminal escape sequences (OSC-52, C0/C1, bidi overrides) supplied via argv reached the user's terminal verbatim. Collapse whitespace and strip escapes, control and format characters at the write site, mirroring the existing sanitizeForStderr pipeline, and pin it with an escape-carrying reject case. Also stage the real bun archive layout in the standalone-update fixture (bun/bin/bun plus the node/bin/node compat shim installBunRuntime writes) so the smoke test's two-hop execution chain has a witness: shortening the staged shim now reds the bun-flavor update test with "Smoke test failed". * fix(cli): accept pre-v0.23.0 standalone manifests without runtime (#11486) * fix(cli): address target-version review feedback (#11486) * fix(cli): keep update recovery guidance and gate win32 test (#11486) Preserve the updater's manual-recovery command by using a 4,096-character bound for its own failure text; the 500-character bound remains for the untrusted --target-version echo. Gate the pre-v0.23.0 manifest success-path test with the same win32 skip as its sibling tests, since atomicReplace returns 'deferred' there. Co-authored-by: Qwen-Coder <[email protected]> * fix(cli): keep update echo sanitizer at its call site (#11486) Move the bounded stderr sanitizer back next to the update command so the shared stdio helper keeps its existing surface, and raise the hosted plan wait to the 10s bound the rest of its file uses so the full-suite gate no longer times out under load. Co-authored-by: Qwen-Coder <[email protected]> * fix(cli): raise hosted plan wait to the file's 10s bound (#11486) * test(cli): describe the registry sink's real enforcement (#11486) Co-authored-by: Qwen-Coder <[email protected]> * fix(ci): stage the standalone archive layout in the runtime harness (#11486) applyStandaloneUpdate rejects an extracted archive that lacks bin/qwen and the bundled runtime, but the harness payload carried neither, so npm run test:standalone:runtimes:ci died in node/clean before any scenario ran. Stage the layout create-standalone-package.js ships - bin/qwen plus the bun flavor's node/bin/node mirror shim - so the fixture matches a real archive and the update scenarios exercise the gate instead of tripping it. * fix(cli): gate standalone archives on cli-entry.js (#11486) The pre-activation layout gate required the installer's launcher and runtime paths, but the repository's standalone-runtime harness repacks a runnable archive without them, so npm run test:standalone:runtimes:ci died in node/clean and the required Test job stayed red. The harness lives in maintainer-only scripts/ territory, so relax the updater's archive gate to the documented v0.18.1 floor: lib/cli-entry.js. smokeTest still runs the bundled runtime, lib/cli.js and lib/cli-entry.js before activation, and isStandaloneInstallDir keeps using the full layout for classification. Revert the harness edit rejected by the footprint gate, and update the design/user docs and the binless fixture test to the relaxed contract. Co-authored-by: Qwen-Coder <[email protected]> * fix(cli): make launcher-less standalone updates launchable (#11486) The update gate accepts archives from the v0.18.1 floor without the installer's bin/qwen launcher (the standalone-runtime harness repacks one that way), but installation detection and the PATH wrapper still required it. A successful update could therefore leave a tree that neither launched nor classified as standalone. Share one layout contract between the gate and detection: the CLI entry point plus the bundled runtime. Detection still accepts the legacy launcher-only layout. When a tree has no launcher, ensureBinWrapper writes a wrapper that execs lib/cli-entry.js through the bundled interpreter and refreshes a stale wrapper that targeted the removed launcher. Update the design and user docs and cover the classifier, wrapper and refresh paths. * fix(cli): resolve a restartable launcher for launcher-less standalone installs (#11486) Accepting launcher-less install trees made the daemon's one-click update arm a restart against a hardcoded bin/qwen that such a tree does not have: activation succeeded, the restart threw ENOENT, and the update was reported as failed. Resolve the PATH wrapper the updater maintains, which lives outside the install and is refreshed when an archive ships no launcher, and fall back to the archive's own launcher; offer manual instructions when neither exists. Only a wrapper that names the install may restart it. Skip the launcher-less acceptance test on win32 like its siblings: its fixture is Unix-shaped and a Windows host derives win32-x64, which validateTarget rejects. --------- Co-authored-by: 西岐 <[email protected]> Co-authored-by: qwen-code-dev-bot <[email protected]> Co-authored-by: Shaojin Wen <[email protected]> Co-authored-by: qwen-code-dev-bot <[email protected]> Co-authored-by: qwen-code-ci-bot <[email protected]> Co-authored-by: Qwen-Coder <[email protected]> Co-authored-by: qwen-code-bot <[email protected]>