perf(web): add batch-scoped source search entrypoint
This commit is contained in:
@@ -43,6 +43,8 @@ node tools/web/print-task-context.mjs
|
||||
- 每完成一个段落或模块,报告必须明确列出源码动态 inventory 的 unitCount、verifiedUnits、unverifiedUnits、sourceTreeSha256,以及本段绑定的 unit 增量;历史 `6900-entry` 只读保留,未绑定源码单元不得计为覆盖进度。
|
||||
- 失败、环境缺失或 hash 漂移保持 `in_progress`/`blocked`,不得推进指针。
|
||||
|
||||
源码检索强制使用 `node tools/web/search-wbv2-batch-source.mjs --pattern <text>`(可重复 `--runtime`);禁止全量 `rg`/`sed`,完整 inventory 仅显式 `--full-inventory` 审计。
|
||||
|
||||
## 交接
|
||||
|
||||
```text
|
||||
|
||||
64
tools/web/search-wbv2-batch-source.mjs
Normal file
64
tools/web/search-wbv2-batch-source.mjs
Normal file
@@ -0,0 +1,64 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const abs = (file) => path.join(root, file);
|
||||
const read = (file) => fs.readFileSync(abs(file), "utf8");
|
||||
const json = (file) => JSON.parse(read(file));
|
||||
const arg = (name, fallback = null) => {
|
||||
const index = process.argv.indexOf(name);
|
||||
return index >= 0 ? process.argv[index + 1] : fallback;
|
||||
};
|
||||
const task = arg("--task") ?? read("docs/EXECUTION_QUEUE.md").match(/\| 当前任务 \| `([^`]+)` \|/u)?.[1];
|
||||
const pattern = arg("--pattern");
|
||||
if (!task) throw new Error("unable to resolve current WBV2 task");
|
||||
if (!pattern && !process.argv.includes("--list")) throw new Error("usage: node tools/web/search-wbv2-batch-source.mjs [--task <task-id>] --pattern <text> [--runtime <path> ...] or --list");
|
||||
|
||||
const queueTaskManifest = `tests/golden/${task}/manifest.json`;
|
||||
const index = json("tests/golden/WBV2/task-index.json");
|
||||
const plan = json(index.source.path);
|
||||
const taskRecord = plan.tasks.find((candidate) => candidate.id === task);
|
||||
const manifest = fs.existsSync(abs(queueTaskManifest)) ? json(queueTaskManifest) : null;
|
||||
const sourcePaths = new Set();
|
||||
for (const artifact of Object.values(manifest?.artifacts ?? {})) {
|
||||
if (artifact?.path?.startsWith("blender-5.2.0/source/blender/")) sourcePaths.add(artifact.path);
|
||||
}
|
||||
for (const source of taskRecord?.module?.sourcePaths ?? []) {
|
||||
if (source.startsWith("blender-5.2.0/source/blender/")) sourcePaths.add(source);
|
||||
}
|
||||
const runtimeAllowlist = new Set([
|
||||
"tools/web/run-wbv2-module-task.mjs",
|
||||
"tools/web/bind-wbv2-module-coverage.mjs",
|
||||
"tools/web/finalize-wbv2-module-batch.mjs",
|
||||
"tools/web/check-source-dynamic-inventory.mjs",
|
||||
"tools/web/reuse-wbv2-source-dependencies.mjs",
|
||||
"my-tools/wbv2_runtime.py",
|
||||
"web/app/src/engine-client/WebEngineClient.ts",
|
||||
]);
|
||||
const runtimePaths = [];
|
||||
for (let index = 0; index < process.argv.length; index += 1) {
|
||||
if (process.argv[index] === "--runtime") {
|
||||
const file = process.argv[index + 1];
|
||||
if (!runtimeAllowlist.has(file)) throw new Error(`runtime path is not allowlisted: ${file}`);
|
||||
runtimePaths.push(file);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
const allowedPaths = [...sourcePaths, ...runtimePaths].filter((file, index, all) => all.indexOf(file) === index && fs.existsSync(abs(file)));
|
||||
if (!allowedPaths.length) throw new Error(`no batch-scoped source paths found for ${task}`);
|
||||
if (process.argv.includes("--list")) {
|
||||
process.stdout.write(`${JSON.stringify({ schemaVersion: 1, task, scope: "batch", sourcePaths: [...sourcePaths], runtimePaths, allowedPaths }, null, 2)}\n`);
|
||||
process.exit(0);
|
||||
}
|
||||
const result = spawnSync("rg", ["--line-number", "--no-heading", "--color", "never", pattern, ...allowedPaths], {
|
||||
cwd: root,
|
||||
encoding: "utf8",
|
||||
maxBuffer: 8 * 1024 * 1024,
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
if (result.status !== 0 && result.status !== 1) throw new Error(`batch search failed with exit ${result.status}`);
|
||||
const output = result.stdout ?? "";
|
||||
const hits = output ? output.trimEnd().split("\n").filter(Boolean) : [];
|
||||
process.stdout.write(`${JSON.stringify({ schemaVersion: 1, task, scope: "batch", pattern, sourcePathCount: sourcePaths.size, runtimePathCount: runtimePaths.length, hitCount: hits.length, hits }, null, 2)}\n`);
|
||||
Reference in New Issue
Block a user