mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-08-07 07:45:54 +00:00
* perf(review): issue independent setup calls in one response Measured on a real small-PR run: the stretch from parse-args to the first agent launch took 7 minutes of wall clock, one round-trip at a time, on calls that never needed an order — pr-context, comment-status and the Step 2 rules load are mutually independent reads. Step 1 now tells the orchestrator to issue all three in a single response (the same rule Step 3 already enforces for the agent fan-out) and to page their outputs in shared responses too. comment-status loses its wait-for-the-context-file guard in worktree mode: learning whether inline comments exist cost a serial round-trip, while running it on a commentless PR just writes an empty index. Step 6's two deterministic gates (script-lint, test-plan) get the same one-response note. The orderings that matter are kept explicit: fetch-pr before everything (it creates the worktree and the plan), the roster after the rules load (it bakes the rules into every brief). * refactor(core): move review skill incident narratives to DESIGN.md SKILL.md is injected wholesale into the review orchestrator's context on every /review run and re-billed on each of its turns, and ~16KB of it was incident narrative — accounts of past dogfood failures and measurements that justify rules but are not themselves instructions. Move 50 such narrative blocks into a new 'Measured incidents (moved from SKILL.md)' section of DESIGN.md (47 anchors, not loaded at runtime), leaving every rule in place with a short '(measured; DESIGN.md — <anchor>)' pointer. Force-bearing figures stay inline where the number is the argument (e.g. the ~161s cold npm ci, the 41% test-code median, the PR #6457 one-of-five checklist measurement). No instruction, gate, format, flag, threshold, or ordering changed; the YAML frontmatter and all 35 fenced code blocks are byte-identical, and the MUST / Do not / never imperative counts are unchanged outside the moved narrative text (verified by script). SKILL.md: 237,847 -> 228,266 bytes; DESIGN.md: 106,708 -> 125,184 bytes. * fix(review): keep DESIGN.md out of the runtime bundle and pin pointers The slim refactor left DESIGN.md shipped beside SKILL.md in dist/bundled/, so one curious read_file of the 125 KB maintainer document would cost more context than the refactor saves. The bundle copy now skips DESIGN.md, and SKILL.md gains a one-line guard telling the orchestrator the pointers are for humans auditing a rule. Also addresses review feedback: a test pins both directions of the SKILL.md incident-pointer mapping, the transcribed-argument narrative keeps its referent after the move, the incidents section title loses its changelog suffix, and Step 2 no longer asks for a base fetch that fetch-pr already performed. * fix(review): gate setup batching by effort and consolidate incident blocks Address round-1 review feedback on the skill-slim PR: - Gate the ONE-response setup batch and the comment-status call to high and medium effort, matching Step 2's low-effort skip. - Scope the Step 6 lint/test-plan batching to same-repo PR reviews. - Merge same-run incident blocks (self-composed Approve into the paraphrased roster prompt; archive verdict into the narrated-away cap), cross-reference the roster-size and relocated-Critical tellings, and state the #8368 path in its block plus the pointer it was missing. - Pointer-ize the last inline QQChannel narrative and fix the scripts-nobody-ran summary to match its block. - Extend the DESIGN.md exclusion to copy_files.js so the transpiled dist/src build and the published core tarball stop shipping it. - Pin the no-read_file guard and the batch ordering constraints in SKILL.test.ts, and fail loudly on pointers the regex cannot parse. --------- Co-authored-by: verify <verify@local> Co-authored-by: qwen-code-ci-bot <qwen-code-ci-bot@users.noreply.github.com>
112 lines
3.3 KiB
JavaScript
112 lines
3.3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
// Copyright 2025 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const extensionsToCopy = ['.md', '.json', '.sb'];
|
|
|
|
function isBundledSkillDesignDoc(normalizedPath) {
|
|
// DESIGN.md files are maintainer design narratives, not runtime inputs
|
|
// (see copy_bundle_assets.js); the transpiled build loads bundled skills
|
|
// from dist/src/, so they must stay out of it too.
|
|
return (
|
|
normalizedPath.startsWith('skills/bundled/') &&
|
|
path.basename(normalizedPath) === 'DESIGN.md'
|
|
);
|
|
}
|
|
|
|
function copyFilesRecursive(source, target, rootSourceDir) {
|
|
if (!fs.existsSync(target)) {
|
|
fs.mkdirSync(target, { recursive: true });
|
|
}
|
|
|
|
const items = fs.readdirSync(source, { withFileTypes: true });
|
|
|
|
for (const item of items) {
|
|
const sourcePath = path.join(source, item.name);
|
|
const targetPath = path.join(target, item.name);
|
|
|
|
if (item.isDirectory()) {
|
|
copyFilesRecursive(sourcePath, targetPath, rootSourceDir);
|
|
} else {
|
|
const ext = path.extname(item.name);
|
|
// Copy standard extensions, or .js files in i18n/locales directory
|
|
// Use path.relative for precise matching to avoid false positives
|
|
const relativePath = path.relative(rootSourceDir, sourcePath);
|
|
const normalizedPath = relativePath.replace(/\\/g, '/');
|
|
const isLocaleJs =
|
|
ext === '.js' && normalizedPath.startsWith('i18n/locales/');
|
|
if (
|
|
(extensionsToCopy.includes(ext) || isLocaleJs) &&
|
|
!isBundledSkillDesignDoc(normalizedPath)
|
|
) {
|
|
fs.copyFileSync(sourcePath, targetPath);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export function copyFiles({ root = process.cwd() } = {}) {
|
|
const sourceDir = path.join(root, 'src');
|
|
const targetDir = path.join(root, 'dist', 'src');
|
|
|
|
if (!fs.existsSync(sourceDir)) {
|
|
console.error(`Source directory ${sourceDir} not found.`);
|
|
process.exit(1);
|
|
}
|
|
|
|
copyFilesRecursive(sourceDir, targetDir, sourceDir);
|
|
|
|
// Copy example extensions into the bundle.
|
|
const packageName = path.basename(root);
|
|
if (packageName === 'cli') {
|
|
const examplesSource = path.join(
|
|
sourceDir,
|
|
'commands',
|
|
'extensions',
|
|
'examples',
|
|
);
|
|
const examplesTarget = path.join(
|
|
targetDir,
|
|
'commands',
|
|
'extensions',
|
|
'examples',
|
|
);
|
|
if (fs.existsSync(examplesSource)) {
|
|
fs.cpSync(examplesSource, examplesTarget, { recursive: true });
|
|
}
|
|
}
|
|
|
|
console.log('Successfully copied files.');
|
|
}
|
|
|
|
if (isDirectRun()) {
|
|
copyFiles();
|
|
}
|
|
|
|
function isDirectRun() {
|
|
return process.argv[1]
|
|
? fileURLToPath(import.meta.url) === path.resolve(process.argv[1])
|
|
: false;
|
|
}
|