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
This commit is contained in:
yiliang114 2026-09-05 23:54:54 +09:00
parent bdbdc459dd
commit b1b94a8762
35 changed files with 347 additions and 263 deletions

View file

@ -1,5 +1,5 @@
name: 'Configure Windows self-hosted runner'
description: 'Tunes a self-hosted Windows runner for the test gates: exports the Linux gates'' C.UTF-8 locale env (inert on Windows, where Node collates through ICU), redirects TEMP/TMP to RUNNER_TEMP, and puts Git Bash on PATH for bash-shell steps. Runs after actions/checkout because repository-local actions resolve from the workspace; callers turn off autocrlf before the checkout itself. Shared by the Windows merge-queue gate and the runner smoke workflow so both always run an identical configuration.'
description: "Tunes a self-hosted Windows runner for the test gates: exports the Linux gates' C.UTF-8 locale env (inert on Windows, where Node collates through ICU), redirects TEMP/TMP to RUNNER_TEMP, and puts Git Bash on PATH for bash-shell steps. Runs after actions/checkout because repository-local actions resolve from the workspace; callers turn off autocrlf before the checkout itself. Shared by the Windows merge-queue gate and the runner smoke workflow so both always run an identical configuration."
runs:
using: 'composite'

View file

@ -30,7 +30,10 @@ test('MDX is executable content, never docs_only', () => {
assert.equal(classifyChangedFiles(['docs/guide.mdx']), 'full');
assert.equal(classifyChangedFiles(['docs/guide.MDX']), 'full');
assert.equal(classifyChangedFiles(['README.mdx']), 'full');
assert.equal(classifyChangedFiles(['docs/usage.md', 'docs/guide.mdx']), 'full');
assert.equal(
classifyChangedFiles(['docs/usage.md', 'docs/guide.mdx']),
'full',
);
});
test('falls back to full for root docs names used as directories', () => {

View file

@ -191,9 +191,8 @@ test('the body stays bounded on a total-suite failure', () => {
`body is ${body.length} chars, must stay under GitHub's 65,536 limit`,
);
assert.ok(body.includes(`- …and ${400 - MAX_BODY_TESTS} more`));
const markerCount = (
body.match(new RegExp(TEST_MARKER_PREFIX, 'g')) ?? []
).length;
const markerCount = (body.match(new RegExp(TEST_MARKER_PREFIX, 'g')) ?? [])
.length;
assert.ok(
markerCount <= MAX_SEARCH_MARKERS,
`body carries ${markerCount} markers, at most ${MAX_SEARCH_MARKERS}`,

View file

@ -240,7 +240,7 @@ describe('release note classification', () => {
// labels — its projectCards lookup fails on affected gh builds).
"if (args[0] === 'api' && args[1] === '-X' && (args[2] === 'POST' || args[2] === 'DELETE') && /\\/issues\\/\\d+\\/labels/.test(args[3])) {",
" const action = args[2] === 'DELETE' ? 'remove' : 'add';",
" const number = args[3].match(/\\/issues\\/(\\d+)\\/labels/)[1];",
' const number = args[3].match(/\\/issues\\/(\\d+)\\/labels/)[1];',
` process.getBuiltinModule('node:fs').appendFileSync(${JSON.stringify(updates)}, number + ' ' + action + '\\n');`,
' process.exit(0);',
'}',

View file

@ -7,12 +7,7 @@ import path from 'node:path';
const options = parseArguments(process.argv.slice(2));
const assets = fs.readdirSync(options.assets).sort();
const patterns = {
macos: [
/-arm64\.zip$/i,
/-x64\.zip$/i,
/-arm64\.dmg$/i,
/-x64\.dmg$/i,
],
macos: [/-arm64\.zip$/i, /-x64\.zip$/i, /-arm64\.dmg$/i, /-x64\.dmg$/i],
windows: [/-setup\.exe$/i],
linux: [/\.AppImage$/i],
};
@ -20,7 +15,9 @@ const selectedPatterns = patterns[options.platform];
if (!selectedPatterns) {
throw new Error(`Invalid --platform: ${options.platform}`);
}
const names = selectedPatterns.map((pattern) => selectArtifact(assets, pattern));
const names = selectedPatterns.map((pattern) =>
selectArtifact(assets, pattern),
);
const artifacts = names.map((name) => readArtifact(assets, name));
const primary = artifacts[0];

View file

@ -1,13 +1,22 @@
import assert from 'node:assert/strict';
import { spawnSync } from 'node:child_process';
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import {
mkdtempSync,
mkdirSync,
readFileSync,
rmSync,
writeFileSync,
} from 'node:fs';
import { tmpdir } from 'node:os';
import { dirname, join } from 'node:path';
import { after, before, describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';
const root = mkdtempSync(join(tmpdir(), 'dsw-tb-manifest-'));
const script = join(dirname(fileURLToPath(import.meta.url)), 'make-terminal-bench-manifest.py');
const script = join(
dirname(fileURLToPath(import.meta.url)),
'make-terminal-bench-manifest.py',
);
let archive;
before(() => {
@ -23,18 +32,30 @@ before(() => {
writeFileSync(join(task, 'instruction.md'), 'test\n');
}
archive = join(root, 'tasks.tar.gz');
const result = spawnSync('tar', ['-czf', archive, '-C', root, 'tasks'], { encoding: 'utf8' });
const result = spawnSync('tar', ['-czf', archive, '-C', root, 'tasks'], {
encoding: 'utf8',
});
assert.equal(result.status, 0, result.stderr);
});
after(() => rmSync(root, { recursive: true, force: true }));
const run = (...args) => spawnSync('python3', [script, '--archive', archive, ...args], { encoding: 'utf8' });
const run = (...args) =>
spawnSync('python3', [script, '--archive', archive, ...args], {
encoding: 'utf8',
});
describe('make-terminal-bench-manifest', () => {
it('selects one exact task for an end-to-end smoke', () => {
const output = join(root, 'one.json');
const result = run('--limit', '1', '--instance-id', 'task-42', '--output', output);
const result = run(
'--limit',
'1',
'--instance-id',
'task-42',
'--output',
output,
);
assert.equal(result.status, 0, result.stderr);
const manifest = JSON.parse(readFileSync(output, 'utf8'));
assert.equal(manifest.expected_instances, 1);
@ -51,7 +72,14 @@ describe('make-terminal-bench-manifest', () => {
});
it('rejects an unknown exact task', () => {
const result = run('--limit', '1', '--instance-id', 'missing', '--output', join(root, 'bad.json'));
const result = run(
'--limit',
'1',
'--instance-id',
'missing',
'--output',
join(root, 'bad.json'),
);
assert.equal(result.status, 1);
assert.match(result.stderr, /Unknown Terminal-Bench/);
});

View file

@ -50,7 +50,7 @@ jobs:
runner: 'windows-2022'
arch: 'x64'
steps:
- uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
- uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
- uses: 'actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e' # v6.4.0
with:
node-version: '22'

View file

@ -46,7 +46,7 @@ jobs:
run: 'echo "push_image=${PUSH_IMAGE}" >> "$GITHUB_OUTPUT"'
- name: 'Checkout repository'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
with:
ref: '${{ github.ref }}'
@ -189,7 +189,7 @@ jobs:
issues: 'write'
steps:
- name: 'Checkout repository'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
with:
persist-credentials: false

View file

@ -30,7 +30,7 @@ jobs:
timeout-minutes: 30
steps:
- name: 'Checkout'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
- name: 'Initialize CodeQL'
uses: 'github/codeql-action/init@df559355d593797519d70b90fc8edd5db049e7a2' # ratchet:github/codeql-action/init@v3

View file

@ -24,7 +24,7 @@ jobs:
runs-on: 'ubuntu-latest'
steps:
- name: 'Checkout'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
- name: 'Setup Pages'
uses: 'actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d' # ratchet:actions/configure-pages@v6

View file

@ -74,7 +74,7 @@ jobs:
id: 'gate'
env:
EVENT_NAME: '${{ github.event_name }}'
RELEASE_TAG: '${{ github.event.release.tag_name || '''' }}'
RELEASE_TAG: "${{ github.event.release.tag_name || '' }}"
RELEASE_PRERELEASE: '${{ github.event.release.prerelease || false }}'
INPUT_EXECUTION_BACKEND: '${{ inputs.execution_backend }}'
INPUT_INSTANCE_LIMIT: '${{ inputs.instance_limit }}'
@ -136,12 +136,12 @@ jobs:
benchmark:
name: 'Dispatch SWE-bench and Terminal-Bench to DSW'
needs: 'release_gate'
if: '${{ needs.release_gate.outputs.should_run == ''true'' }}'
if: "${{ needs.release_gate.outputs.should_run == 'true' }}"
runs-on: ['self-hosted', 'Linux', 'X64', 'qwen-benchmark-dsw-hk-eas']
timeout-minutes: 15
env:
RELEASE_TAG: '${{ github.event_name == ''release'' && github.event.release.tag_name || inputs.release_tag }}'
QWEN_REF: '${{ github.event_name == ''release'' && github.event.release.tag_name || inputs.qwen_release_tag || inputs.release_tag }}'
RELEASE_TAG: "${{ github.event_name == 'release' && github.event.release.tag_name || inputs.release_tag }}"
QWEN_REF: "${{ github.event_name == 'release' && github.event.release.tag_name || inputs.qwen_release_tag || inputs.release_tag }}"
INSTANCE_LIMIT: '${{ needs.release_gate.outputs.instance_limit }}'
BENCHMARK_INSTANCE_ID: '${{ needs.release_gate.outputs.instance_id }}'
TERMINAL_BENCH_LIMIT: '${{ needs.release_gate.outputs.terminal_bench_limit }}'

View file

@ -3058,7 +3058,6 @@ jobs:
gh pr comment "$PR_NUMBER" --repo "$REPO" --body-file "${WORKDIR}/report.md" ||
echo "::warning::Resolve was skipped, but posting the skip-reason comment failed."
# Publishes what the agent job produced — verification, push and the result
# comment — on a runner that never executed the agent. It starts from a
# fresh checkout, fetches the base and head refs from GitHub itself, and

View file

@ -25,7 +25,7 @@ jobs:
decision: '${{ steps.assess.outputs.decision }}'
steps:
- name: 'Checkout trusted precheck script'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
with:
ref: '${{ github.event.repository.default_branch }}'
sparse-checkout: '.github/scripts/pr-safety-precheck.mjs'

View file

@ -34,7 +34,7 @@ on:
default: false
concurrency:
group: '${{ github.workflow }}-${{ github.event.inputs.create_nightly_release == ''true'' && ''nightly'' || github.event.inputs.create_preview_release == ''true'' && ''preview'' || ''stable'' }}'
group: "${{ github.workflow }}-${{ github.event.inputs.create_nightly_release == 'true' && 'nightly' || github.event.inputs.create_preview_release == 'true' && 'preview' || 'stable' }}"
cancel-in-progress: false
jobs:
@ -100,7 +100,7 @@ jobs:
fi
- name: 'Checkout'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
with:
ref: '${{ github.event.inputs.ref || github.sha }}'
fetch-depth: 0
@ -136,7 +136,7 @@ jobs:
echo "sha=$(git rev-parse HEAD)" >> "${GITHUB_OUTPUT}"
- name: 'Setup Node.js'
uses: 'actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e' # v6.4.0
uses: 'actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e' # v6.4.0
with:
node-version-file: '.nvmrc'
cache: 'npm'
@ -203,7 +203,7 @@ jobs:
MANUAL_VERSION: '${{ inputs.version }}'
- name: 'Setup Python'
uses: 'actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405' # v6.2.0
uses: 'actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405' # v6.2.0
with:
# Keep in sync with packages/sdk-python/pyproject.toml [project] requires-python.
python-version: '3.11'

View file

@ -64,7 +64,7 @@ jobs:
steps:
- name: 'Checkout'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
with:
ref: '${{ github.event.release.tag_name || github.event.inputs.ref || github.sha }}'
fetch-depth: 0
@ -208,7 +208,7 @@ jobs:
steps:
- name: 'Checkout'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
with:
ref: '${{ github.event.release.tag_name || github.event.inputs.ref || github.sha }}'
fetch-depth: 0
@ -295,7 +295,7 @@ jobs:
steps:
- name: 'Checkout'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
with:
ref: '${{ github.event.release.tag_name || github.event.inputs.ref || github.sha }}'

View file

@ -77,10 +77,10 @@ jobs:
python-version: ['3.10', '3.11', '3.12']
steps:
- name: 'Checkout'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
- name: 'Set up Python'
uses: 'actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405' # v6.2.0
uses: 'actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405' # v6.2.0
with:
python-version: '${{ matrix.python-version }}'

View file

@ -24,7 +24,7 @@ jobs:
group: '${{ github.workflow }}-stale'
cancel-in-progress: true
steps:
- uses: 'actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899' # v10.3.0
- uses: 'actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899' # v10.3.0
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
# Issues are intentionally disabled here; a separate policy will

View file

@ -75,7 +75,14 @@ jobs:
if: "${{ github.repository == 'QwenLM/qwen-code' }}"
strategy:
matrix:
runner: ['ecs-update-hk-1', 'ecs-update-hk-2', 'ecs-update-hk-3', 'ecs-update-hk-4', 'ecs-update-hk-5']
runner:
[
'ecs-update-hk-1',
'ecs-update-hk-2',
'ecs-update-hk-3',
'ecs-update-hk-4',
'ecs-update-hk-5',
]
fail-fast: false
runs-on: ['self-hosted', 'linux', 'x64', '${{ matrix.runner }}']
concurrency:
@ -150,7 +157,7 @@ jobs:
issues: 'write'
steps:
- name: 'Checkout'
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
uses: 'actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10' # v6.0.3
with:
persist-credentials: false

View file

@ -78,26 +78,26 @@ path this repo ships or loads. A path named by more than one row takes the
most restrictive outcome: Never-a-target beats Report-only, which beats
Landable.
| Territory | Outcome |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `packages/cli/src` — the whole package (`generated/` stays under the Never-a-target row below; `**/*.sb` stays under the Report-only row below; `i18n/locales/**` and `commands/extensions/examples/**` stay under the Report-only row below; `**/*.test.ts(x)`, `**/*.spec.ts(x)`, `**/__snapshots__/**` are never targets, always searched as consumers) | Landable |
| `scripts/`, `esbuild.config.js`, `eslint.legacy-filenames.mjs`, root manifests | Landable |
| Territory | Outcome |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `packages/cli/src` — the whole package (`generated/` stays under the Never-a-target row below; `**/*.sb` stays under the Report-only row below; `i18n/locales/**` and `commands/extensions/examples/**` stay under the Report-only row below; `**/*.test.ts(x)`, `**/*.spec.ts(x)`, `**/__snapshots__/**` are never targets, always searched as consumers) | Landable |
| `scripts/`, `esbuild.config.js`, `eslint.legacy-filenames.mjs`, root manifests | Landable |
| Whole files or directories nothing consumes by any mechanism named above — no import and no runtime read, loader, manifest, or tool config — anywhere outside `packages/core/src`, `packages/audio-capture`, `packages/channels`, `packages/sdk-*`, `packages/acp-bridge`, `packages/vscode-ide-companion`, `packages/chrome-extension`, `packages/zed-extension`, `packages/web-shell`, `packages/core/vendor`, `.github`, and the Never-a-target row below | Landable |
| `docs/users/**`, `docs/developers/**`, `docs/index.md`, `docs/_meta.ts`, `packages/cli/src/i18n/locales/**`, `packages/cli/src/commands/extensions/examples/**` — as whole files or directories | **Report-only** — copied into the published tarball (`scripts/prepare-package.js` copies the locales and extension examples; `scripts/copy_bundle_assets.js` copies `docs/users/` for qc-helper) and consumed by the published docs site (`docs-site/scripts/link-public-docs.mjs` symlinks `docs/users/` and `docs/developers/` into the Nextra build per `PUBLIC_DOC_ROOTS` and copies `docs/index.md` and `docs/_meta.ts`; the site discovers pages by walking that tree); consumers are runtime reads — qc-helper's doc paths, the i18n loader's segment-assembled `import()`, `/extensions new` scaffolds — never imports. Individual orphan locale keys stay class-4 candidates: their proof greps the literal key, naming its mechanism |
| `docs-site/` | **Report-only** — standalone published-site app, not a workspace member; route files are consumed by Next.js filesystem routing and an out-of-repo deploy, never imports, and no in-repo CI builds it |
| Tracked `.qwen/skills/**`, `.qwen/agents/**`, `.qwen/e2e-tests/**`, `docs/design/**`, `docs/plans/**` | **Report-only** — consumed by the skill loader, agent definitions, and process readers (including `AGENTS.md` itself), never imports |
| `AGENTS.md`, `CLAUDE.md`, `SECURITY.md`, `CONTRIBUTING.md`, `.prettierrc.json`, `.prettierignore`, `.editorconfig`, `.nvmrc`, `.npmrc`, `.yamllint.yml` | **Report-only** — consumed by external tooling through filename convention (agent harnesses, GitHub's security-policy UI, prettier and yamllint config auto-discovery, nvm, editors); never imports, and an in-repo grep for them measures only prose |
| Anything under `packages/core/src` | **Report-only** — published |
| `packages/audio-capture`, `packages/channels` | **Report-only** — npm-published (`--access public`) |
| `packages/core/vendor/**`, `packages/web-shell` | **Report-only** — shipped inside the published `@qwen-code/qwen-code` tarball / served to browsers by `qwen serve`; consumers are bundled or browser-side, never imports |
| `packages/cli/src/utils/**/*.sb` | **Report-only** — copied into the published bundle by extension glob (`scripts/copy_bundle_assets.js` copies `packages/**/*.sb`, `scripts/prepare-package.js` lists `'*.sb'`) and read at runtime through a segment-assembled path (`resolveSeatbeltProfileFile()` builds `sandbox-macos-${profile}.sb`); consumers are never imports, and a basename grep measures zero |
| Any key in `packages/cli/src/config/settingsSchema.ts` | **Report-only** — see below |
| `packages/sdk-*`, `packages/acp-bridge`, protocol/wire shapes | **Report-only** — out-of-repo consumers |
| `packages/vscode-ide-companion`, `packages/chrome-extension`, `packages/zed-extension` | **Report-only** — shipped as store manifests; the store is the consumer |
| `.github/` — workflows, actions, CODEOWNERS | **Report-only** — consumed GitHub-side: triggers, required checks, cross-repo `uses:` |
| `package.json` dependencies | **Report-only** — bundlers and postinstall hide consumers |
| Comments, JSDoc, commented-out code | **Out of scope**`AGENTS.md` says do not delete existing comments as cleanup |
| `packages/desktop-shell`, `packages/cua-driver`, `packages/mobile-mcp`, `**/generated/**`, `**/*.test.ts(x)`, `**/*.spec.ts(x)`, `**/__snapshots__/**` | Never a target; always searched as consumers — vitest discovers tests by filename glob, nothing imports them, so an import-based orphan detector matches every live test vacuously |
| `docs/users/**`, `docs/developers/**`, `docs/index.md`, `docs/_meta.ts`, `packages/cli/src/i18n/locales/**`, `packages/cli/src/commands/extensions/examples/**` — as whole files or directories | **Report-only** — copied into the published tarball (`scripts/prepare-package.js` copies the locales and extension examples; `scripts/copy_bundle_assets.js` copies `docs/users/` for qc-helper) and consumed by the published docs site (`docs-site/scripts/link-public-docs.mjs` symlinks `docs/users/` and `docs/developers/` into the Nextra build per `PUBLIC_DOC_ROOTS` and copies `docs/index.md` and `docs/_meta.ts`; the site discovers pages by walking that tree); consumers are runtime reads — qc-helper's doc paths, the i18n loader's segment-assembled `import()`, `/extensions new` scaffolds — never imports. Individual orphan locale keys stay class-4 candidates: their proof greps the literal key, naming its mechanism |
| `docs-site/` | **Report-only** — standalone published-site app, not a workspace member; route files are consumed by Next.js filesystem routing and an out-of-repo deploy, never imports, and no in-repo CI builds it |
| Tracked `.qwen/skills/**`, `.qwen/agents/**`, `.qwen/e2e-tests/**`, `docs/design/**`, `docs/plans/**` | **Report-only** — consumed by the skill loader, agent definitions, and process readers (including `AGENTS.md` itself), never imports |
| `AGENTS.md`, `CLAUDE.md`, `SECURITY.md`, `CONTRIBUTING.md`, `.prettierrc.json`, `.prettierignore`, `.editorconfig`, `.nvmrc`, `.npmrc`, `.yamllint.yml` | **Report-only** — consumed by external tooling through filename convention (agent harnesses, GitHub's security-policy UI, prettier and yamllint config auto-discovery, nvm, editors); never imports, and an in-repo grep for them measures only prose |
| Anything under `packages/core/src` | **Report-only** — published |
| `packages/audio-capture`, `packages/channels` | **Report-only** — npm-published (`--access public`) |
| `packages/core/vendor/**`, `packages/web-shell` | **Report-only** — shipped inside the published `@qwen-code/qwen-code` tarball / served to browsers by `qwen serve`; consumers are bundled or browser-side, never imports |
| `packages/cli/src/utils/**/*.sb` | **Report-only** — copied into the published bundle by extension glob (`scripts/copy_bundle_assets.js` copies `packages/**/*.sb`, `scripts/prepare-package.js` lists `'*.sb'`) and read at runtime through a segment-assembled path (`resolveSeatbeltProfileFile()` builds `sandbox-macos-${profile}.sb`); consumers are never imports, and a basename grep measures zero |
| Any key in `packages/cli/src/config/settingsSchema.ts` | **Report-only** — see below |
| `packages/sdk-*`, `packages/acp-bridge`, protocol/wire shapes | **Report-only** — out-of-repo consumers |
| `packages/vscode-ide-companion`, `packages/chrome-extension`, `packages/zed-extension` | **Report-only** — shipped as store manifests; the store is the consumer |
| `.github/` — workflows, actions, CODEOWNERS | **Report-only** — consumed GitHub-side: triggers, required checks, cross-repo `uses:` |
| `package.json` dependencies | **Report-only** — bundlers and postinstall hide consumers |
| Comments, JSDoc, commented-out code | **Out of scope**`AGENTS.md` says do not delete existing comments as cleanup |
| `packages/desktop-shell`, `packages/cua-driver`, `packages/mobile-mcp`, `**/generated/**`, `**/*.test.ts(x)`, `**/*.spec.ts(x)`, `**/__snapshots__/**` | Never a target; always searched as consumers — vitest discovers tests by filename glob, nothing imports them, so an import-based orphan detector matches every live test vacuously |
A settings key with zero read sites is still not cleanup. The key is likely
documented under `docs/users/` and completed from the generated schema;

View file

@ -8,11 +8,7 @@ import type { CommandModule } from 'yargs';
import { getErrorMessage } from '../../utils/errors.js';
import { writeStdoutLine, writeStderrLine } from '../../utils/stdioHelpers.js';
import { extensionToOutputString, getExtensionManager } from './utils.js';
import {
t,
initializeI18n,
resolveLanguageSetting,
} from '../../i18n/index.js';
import { t, initializeI18n, resolveLanguageSetting } from '../../i18n/index.js';
import { loadSettings } from '../../config/settings.js';
export async function handleList() {

View file

@ -311,7 +311,7 @@ export async function initializeI18n(
export function resolveLanguageSetting(
settingsLanguage?: string,
): SupportedLanguage | 'auto' {
return (
process.env['QWEN_CODE_LANG'] || settingsLanguage || 'auto'
) as SupportedLanguage | 'auto';
return (process.env['QWEN_CODE_LANG'] || settingsLanguage || 'auto') as
| SupportedLanguage
| 'auto';
}

View file

@ -56,10 +56,16 @@ export function ScopeSelectStep({
const title =
mode === 'disable'
? t('Disable "{{name}}" - Select Scope', {
name: getExtensionDisplayName(selectedExtension, getCurrentLanguage()),
name: getExtensionDisplayName(
selectedExtension,
getCurrentLanguage(),
),
})
: t('Enable "{{name}}" - Select Scope', {
name: getExtensionDisplayName(selectedExtension, getCurrentLanguage()),
name: getExtensionDisplayName(
selectedExtension,
getCurrentLanguage(),
),
});
return (

View file

@ -60,7 +60,10 @@ export function UninstallConfirmStep({
<Box flexDirection="column" gap={1}>
<Text color={theme.status.error}>
{t('Are you sure you want to uninstall extension "{{name}}"?', {
name: getExtensionDisplayName(selectedExtension, getCurrentLanguage()),
name: getExtensionDisplayName(
selectedExtension,
getCurrentLanguage(),
),
})}
</Text>
<Text color={theme.status.error}>

View file

@ -53,9 +53,10 @@ class InMemoryServerTransport {
}
/** Build a canned client-hosted MCP server exposing one echo tool. */
function buildCannedServer(
sink: (message: JSONRPCMessage) => void,
): { transport: InMemoryServerTransport; ready: Promise<void> } {
function buildCannedServer(sink: (message: JSONRPCMessage) => void): {
transport: InMemoryServerTransport;
ready: Promise<void>;
} {
const server = new McpServer({
name: 'chrome-tools',
version: '0.0.1',

View file

@ -1,161 +1,165 @@
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
import stylistic from "@stylistic/eslint-plugin";
import importRules from "eslint-plugin-import";
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import stylistic from '@stylistic/eslint-plugin';
import importRules from 'eslint-plugin-import';
const plugins = {
"@stylistic": stylistic,
"@typescript-eslint": typescriptEslint,
import: importRules,
'@stylistic': stylistic,
'@typescript-eslint': typescriptEslint,
import: importRules,
};
export const baseRules = {
"@typescript-eslint/no-unused-vars": [
2,
{args: "none", caughtErrors: "none"},
],
'@typescript-eslint/no-unused-vars': [
2,
{ args: 'none', caughtErrors: 'none' },
],
/**
* Enforced rules
*/
// syntax preferences
"object-curly-spacing": ["error", "always"],
quotes: [
2,
"double",
{
avoidEscape: true,
allowTemplateLiterals: true,
},
],
"jsx-quotes": [2, "prefer-single"],
"no-extra-semi": 2,
"@stylistic/semi": [2],
"comma-style": [2, "last"],
"wrap-iife": [2, "inside"],
"spaced-comment": [
2,
"always",
{
markers: ["*"],
},
],
eqeqeq: [2],
"accessor-pairs": [
2,
{
getWithoutSet: false,
setWithoutGet: false,
},
],
"brace-style": [2, "1tbs", {allowSingleLine: true}],
curly: [2, "all"],
"new-parens": 2,
"arrow-parens": [2, "as-needed"],
"prefer-const": 2,
"quote-props": [2, "consistent"],
"nonblock-statement-body-position": [2, "below"],
/**
* Enforced rules
*/
// syntax preferences
'object-curly-spacing': ['error', 'always'],
quotes: [
2,
'double',
{
avoidEscape: true,
allowTemplateLiterals: true,
},
],
'jsx-quotes': [2, 'prefer-single'],
'no-extra-semi': 2,
'@stylistic/semi': [2],
'comma-style': [2, 'last'],
'wrap-iife': [2, 'inside'],
'spaced-comment': [
2,
'always',
{
markers: ['*'],
},
],
eqeqeq: [2],
'accessor-pairs': [
2,
{
getWithoutSet: false,
setWithoutGet: false,
},
],
'brace-style': [2, '1tbs', { allowSingleLine: true }],
curly: [2, 'all'],
'new-parens': 2,
'arrow-parens': [2, 'as-needed'],
'prefer-const': 2,
'quote-props': [2, 'consistent'],
'nonblock-statement-body-position': [2, 'below'],
// anti-patterns
"no-var": 2,
"no-with": 2,
"no-multi-str": 2,
"no-caller": 2,
"no-implied-eval": 2,
"no-labels": 2,
"no-new-object": 2,
"no-octal-escape": 2,
"no-self-compare": 2,
"no-shadow-restricted-names": 2,
"no-cond-assign": 2,
"no-debugger": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty-character-class": 2,
"no-unreachable": 2,
"no-unsafe-negation": 2,
radix: 2,
"valid-typeof": 2,
"no-implicit-globals": [2],
"no-unused-expressions": [
2,
{allowShortCircuit: true, allowTernary: true, allowTaggedTemplates: true},
],
"no-proto": 2,
// anti-patterns
'no-var': 2,
'no-with': 2,
'no-multi-str': 2,
'no-caller': 2,
'no-implied-eval': 2,
'no-labels': 2,
'no-new-object': 2,
'no-octal-escape': 2,
'no-self-compare': 2,
'no-shadow-restricted-names': 2,
'no-cond-assign': 2,
'no-debugger': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-unreachable': 2,
'no-unsafe-negation': 2,
radix: 2,
'valid-typeof': 2,
'no-implicit-globals': [2],
'no-unused-expressions': [
2,
{ allowShortCircuit: true, allowTernary: true, allowTaggedTemplates: true },
],
'no-proto': 2,
// es2015 features
"require-yield": 2,
"template-curly-spacing": [2, "never"],
// es2015 features
'require-yield': 2,
'template-curly-spacing': [2, 'never'],
// spacing details
"space-infix-ops": 2,
"space-in-parens": [2, "never"],
"array-bracket-spacing": [2, "never"],
"comma-spacing": [2, {before: false, after: true}],
"keyword-spacing": [2, "always"],
"space-before-function-paren": [
2,
{
anonymous: "never",
named: "never",
asyncArrow: "always",
},
],
"no-whitespace-before-property": 2,
"keyword-spacing": [
2,
{
overrides: {
if: {after: true},
else: {after: true},
for: {after: true},
while: {after: true},
do: {after: true},
switch: {after: true},
return: {after: true},
},
},
],
"arrow-spacing": [
2,
{
after: true,
before: true,
},
],
"@stylistic/func-call-spacing": 2,
"@stylistic/type-annotation-spacing": 2,
// spacing details
'space-infix-ops': 2,
'space-in-parens': [2, 'never'],
'array-bracket-spacing': [2, 'never'],
'comma-spacing': [2, { before: false, after: true }],
'keyword-spacing': [2, 'always'],
'space-before-function-paren': [
2,
{
anonymous: 'never',
named: 'never',
asyncArrow: 'always',
},
],
'no-whitespace-before-property': 2,
'keyword-spacing': [
2,
{
overrides: {
if: { after: true },
else: { after: true },
for: { after: true },
while: { after: true },
do: { after: true },
switch: { after: true },
return: { after: true },
},
},
],
'arrow-spacing': [
2,
{
after: true,
before: true,
},
],
'@stylistic/func-call-spacing': 2,
'@stylistic/type-annotation-spacing': 2,
// file whitespace
"no-multiple-empty-lines": [2, {max: 2, maxEOF: 0}],
"no-mixed-spaces-and-tabs": 2,
"no-trailing-spaces": 2,
"linebreak-style": [process.platform === "win32" ? 0 : 2, "unix"],
indent: [
2,
"tab",
{SwitchCase: 1, CallExpression: {arguments: "first"}, MemberExpression: 1},
],
"key-spacing": [
2,
{
beforeColon: false,
},
],
"eol-last": 2,
// file whitespace
'no-multiple-empty-lines': [2, { max: 2, maxEOF: 0 }],
'no-mixed-spaces-and-tabs': 2,
'no-trailing-spaces': 2,
'linebreak-style': [process.platform === 'win32' ? 0 : 2, 'unix'],
indent: [
2,
'tab',
{
SwitchCase: 1,
CallExpression: { arguments: 'first' },
MemberExpression: 1,
},
],
'key-spacing': [
2,
{
beforeColon: false,
},
],
'eol-last': 2,
};
const languageOptions = {
parser: tsParser,
ecmaVersion: 9,
sourceType: "module",
parser: tsParser,
ecmaVersion: 9,
sourceType: 'module',
};
export default [
{
files: ["**/*.ts"],
plugins,
languageOptions,
rules: baseRules,
},
{
files: ['**/*.ts'],
plugins,
languageOptions,
rules: baseRules,
},
];

View file

@ -32,7 +32,9 @@ const kernelChildren = () => {
let failures = 0;
const check = (label, cond, detail) => {
console.log(`${cond ? 'PASS' : 'FAIL'} ${label}${detail ? `${detail}` : ''}`);
console.log(
`${cond ? 'PASS' : 'FAIL'} ${label}${detail ? `${detail}` : ''}`,
);
if (!cond) failures++;
};
@ -86,8 +88,14 @@ const stillAlive = before.filter((pid) => {
return false;
}
});
check('kernel child reaped', stillAlive.length === 0, `alive=${stillAlive.join(',') || 'none'}`);
check(
'kernel child reaped',
stillAlive.length === 0,
`alive=${stillAlive.join(',') || 'none'}`,
);
if (!exited) server.kill('SIGKILL');
console.log(failures === 0 ? '\nLIFECYCLE SMOKE PASSED' : `\n${failures} FAILED`);
console.log(
failures === 0 ? '\nLIFECYCLE SMOKE PASSED' : `\n${failures} FAILED`,
);
process.exit(failures === 0 ? 0 : 1);

View file

@ -29,7 +29,9 @@ const run = async (code) => {
let failures = 0;
const check = (label, cond, detail) => {
console.log(`${cond ? 'PASS' : 'FAIL'} ${label}${detail ? `${detail}` : ''}`);
console.log(
`${cond ? 'PASS' : 'FAIL'} ${label}${detail ? `${detail}` : ''}`,
);
if (!cond) failures++;
};
@ -46,7 +48,11 @@ try {
);
const r3 = await run('nodeRepl.write(typeof host);');
const text3 = r3.mcp.content.find((b) => b.type === 'text')?.text ?? '';
check('dynamic import binding persists', text3.includes('string'), text3.trim());
check(
'dynamic import binding persists',
text3.includes('string'),
text3.trim(),
);
// 3. Image output (1x1 PNG).
const png =
@ -75,5 +81,9 @@ try {
manager.dispose();
}
console.log(failures === 0 ? '\nALL SMOKE CHECKS PASSED' : `\n${failures} CHECK(S) FAILED`);
console.log(
failures === 0
? '\nALL SMOKE CHECKS PASSED'
: `\n${failures} CHECK(S) FAILED`,
);
process.exit(failures === 0 ? 0 : 1);

View file

@ -839,10 +839,7 @@ function readSuccessfulBindings(module, bindingExports) {
async function handleExec(message) {
if (!config || !loader) throw new Error('kernel is not initialized');
if (activeExec) throw new Error('kernel received overlapping executions');
if (
pendingCancelExecId !== null &&
pendingCancelExecId !== message.execId
) {
if (pendingCancelExecId !== null && pendingCancelExecId !== message.execId) {
pendingCancelExecId = null;
}
const expected = sortedBindingDescriptors();

View file

@ -49,7 +49,11 @@ new AgentSideConnection(
authMethods: [{ id: 'openai', name: 'Use OpenAI API key' }],
agentCapabilities: {
loadSession: false,
promptCapabilities: { image: true, audio: false, embeddedContext: false },
promptCapabilities: {
image: true,
audio: false,
embeddedContext: false,
},
},
};
},
@ -85,7 +89,11 @@ new AgentSideConnection(
title: text.slice(0, 80),
},
options: [
{ optionId: 'proceed_once', name: 'Allow once', kind: 'allow_once' },
{
optionId: 'proceed_once',
name: 'Allow once',
kind: 'allow_once',
},
{ optionId: 'cancel', name: 'Cancel', kind: 'reject_once' },
],
});

View file

@ -250,18 +250,14 @@
overflow: hidden;
}
:global(
[data-web-shell-toolbar-popover][data-web-shell-compact-overlay]
) {
:global([data-web-shell-toolbar-popover][data-web-shell-compact-overlay]) {
width: min(360px, calc(100vw - 16px));
max-width: calc(100vw - 16px);
box-sizing: border-box;
padding: 6px;
}
:global(
[data-web-shell-toolbar-popover][data-web-shell-compact-overlay]
)
:global([data-web-shell-toolbar-popover][data-web-shell-compact-overlay])
.dropdownItemDesc {
display: -webkit-box;
overflow-wrap: anywhere;
@ -1329,10 +1325,7 @@
border-radius: 6px;
}
.editorShell[data-web-shell-compact-composer]
.toolbarRight
button
svg {
.editorShell[data-web-shell-compact-composer] .toolbarRight button svg {
width: 16px;
height: 16px;
}

View file

@ -15,8 +15,7 @@
padding: 3px 9px;
border-radius: 20px;
cursor: pointer;
border: 1px solid
color-mix(in srgb, var(--git-mode-current) 20%, transparent);
border: 1px solid color-mix(in srgb, var(--git-mode-current) 20%, transparent);
background: color-mix(in srgb, var(--git-mode-current) 10%, transparent);
color: var(--git-mode-current);
transition:

View file

@ -262,11 +262,6 @@
gap: 8px;
}
/* ── branch select (searchable) ─────────────── */
.branchSelectTrigger {
display: inline-flex;

View file

@ -27,7 +27,27 @@
THEME_STORAGE_KEY in main.tsx.
-->
<script>
!function(){try{var k='qwen-code-web-shell-theme',p=new URLSearchParams(location.search),t=p.get('theme');if(t!=='dark'&&t!=='light'){try{t=localStorage.getItem(k)}catch(_){t=null}}if(t!=='dark'&&t!=='light')t='dark';document.documentElement.classList.add('theme-'+t);var m=document.querySelector('meta[name=theme-color]');if(m)m.setAttribute('content',t==='light'?'#ffffff':'#0d0d0d')}catch(e){console.warn('theme-init:',e)}}();
!(function () {
try {
var k = 'qwen-code-web-shell-theme',
p = new URLSearchParams(location.search),
t = p.get('theme');
if (t !== 'dark' && t !== 'light') {
try {
t = localStorage.getItem(k);
} catch (_) {
t = null;
}
}
if (t !== 'dark' && t !== 'light') t = 'dark';
document.documentElement.classList.add('theme-' + t);
var m = document.querySelector('meta[name=theme-color]');
if (m)
m.setAttribute('content', t === 'light' ? '#ffffff' : '#0d0d0d');
} catch (e) {
console.warn('theme-init:', e);
}
})();
</script>
<!--
Favicon is inlined as a data: URI rather than a /favicon.svg file because

View file

@ -26,16 +26,25 @@ const require = createRequire(import.meta.url);
const { Agent } = require('../packages/core/node_modules/undici/index.js');
const ITERATIONS = parseInt(process.env['ITERATIONS'] ?? '3', 10);
const REQUEST_TIMEOUT_MS = parseInt(process.env['REQUEST_TIMEOUT_MS'] ?? '5000', 10);
const REQUEST_TIMEOUT_MS = parseInt(
process.env['REQUEST_TIMEOUT_MS'] ?? '5000',
10,
);
const DEFAULT_ENDPOINTS = [
{ url: 'https://api.openai.com', label: 'OpenAI' },
{ url: 'https://api.anthropic.com', label: 'Anthropic' },
{ url: 'https://dashscope.aliyuncs.com/compatible-mode/v1', label: 'DashScope (openai-compatible)' },
{ url: 'https://api.openai.com', label: 'OpenAI' },
{ url: 'https://api.anthropic.com', label: 'Anthropic' },
{
url: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
label: 'DashScope (openai-compatible)',
},
];
const extraUrls = process.env['BENCHMARK_URLS']
? process.env['BENCHMARK_URLS'].split(' ').filter(Boolean).map((url) => ({ url, label: url }))
? process.env['BENCHMARK_URLS']
.split(' ')
.filter(Boolean)
.map((url) => ({ url, label: url }))
: [];
const ENDPOINTS = [...DEFAULT_ENDPOINTS, ...extraUrls];
@ -146,10 +155,10 @@ for (const endpoint of ENDPOINTS) {
console.log('\n\n=== Results ===\n');
console.log(
'Endpoint'.padEnd(36) +
'Cold (avg)'.padStart(12) +
'Warm (avg)'.padStart(12) +
'Saved'.padStart(10) +
'Improvement'.padStart(13),
'Cold (avg)'.padStart(12) +
'Warm (avg)'.padStart(12) +
'Saved'.padStart(10) +
'Improvement'.padStart(13),
);
console.log('─'.repeat(83));
@ -157,10 +166,10 @@ for (const r of results) {
const status = r.pct >= 30 ? '✓' : r.pct >= 10 ? '~' : '✗';
console.log(
r.label.slice(0, 35).padEnd(36) +
fmt(r.avgCold).padStart(12) +
fmt(r.avgWarm).padStart(12) +
fmt(r.saved).padStart(10) +
`${r.pct.toFixed(1)}% ${status}`.padStart(13),
fmt(r.avgCold).padStart(12) +
fmt(r.avgWarm).padStart(12) +
fmt(r.saved).padStart(10) +
`${r.pct.toFixed(1)}% ${status}`.padStart(13),
);
}

View file

@ -110,7 +110,9 @@ function renderDelta(current, baseline) {
const b = baseline.counts[p.name];
const d = c - b;
const arrow = d < 0 ? '↓' : d > 0 ? '↑' : '·';
stdout.write(` ${p.name.padEnd(18)} ${d > 0 ? '+' : ''}${d} ${arrow}\n`);
stdout.write(
` ${p.name.padEnd(18)} ${d > 0 ? '+' : ''}${d} ${arrow}\n`,
);
}
stdout.write(
'\ntip: lower clearTerminalPair (and lower clearScreen) on "current" wins.\n',