完成五人团队正式内用最小收口(07-18-small-team-internal-readiness)

这个提交包含在:
2026-07-18 15:46:14 +08:00
父节点 58c8decef9
当前提交 5d0a5f9a38
共修改 134 个文件,包含 10790 行新增和 1413 行删除
@@ -0,0 +1,310 @@
import assert from "node:assert/strict";
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import test from "node:test";
import { buildReport, hasBlockingGaps } from "../check-flow-coverage.mjs";
const WITNESS_SPEC = `
import { test } from "@playwright/test";
export const LOCAL_CANDIDATE_MANIFEST_DRIVEN_WITNESSES = true;
for (const flow of localCandidateFlows) {
test(flow.witnessTag, async ({ page }) => {
installBrowserErrorMonitor(page);
installSyntheticApis(page, flow.roleFixture);
await loginToWitness(page, flow.witnessRoute);
await expectUniqueH1(page, flow.expectedH1);
await expectPrimaryActionContract(page, flow);
});
}
`;
function candidateFlow(bundle = "core-flow", witnessRoute = "/core", overrides = {}) {
return {
bundle,
witnessRoute,
witnessTag: `@local-candidate:${bundle}`,
expectedH1: "核心页面",
roleFixture: "employee",
primaryAction: { allowed: "开始", forbidden: "越权操作" },
witnessSpec: "client/tests/e2e/local-candidate-witnesses.spec.ts",
...overrides,
};
}
function writeFixture({
routes = ["/core"],
coreBundles = ["core-flow"],
manifestRoutes = [
{
path: "/core",
classification: "core",
bundle: "core-flow",
behaviorSpecs: ["client/tests/e2e/core.spec.ts"],
},
],
localCandidateFlows = [candidateFlow()],
acceptanceSpecs = ["client/tests/e2e/acceptance.spec.ts"],
specs = {},
} = {}) {
const root = mkdtempSync(path.join(tmpdir(), "hyb-flow-coverage-"));
const routerPath = path.join(root, "client/src/router/index.tsx");
const manifestPath = path.join(root, "scripts/qa/route-manifest.json");
mkdirSync(path.dirname(routerPath), { recursive: true });
mkdirSync(path.dirname(manifestPath), { recursive: true });
writeFileSync(
routerPath,
`export function RouterFixture() { return <Routes>${routes.map((route) => `<Route path="${route}" element={<div />} />`).join("")}</Routes>; }\n`,
"utf8",
);
writeFileSync(
manifestPath,
`${JSON.stringify({
schemaVersion: 1,
coreBundles,
acceptanceSpecs,
localCandidateFlows,
routes: manifestRoutes,
}, null, 2)}\n`,
"utf8",
);
const defaultSpecs = {
"client/tests/e2e/core.spec.ts": 'import { test } from "@playwright/test";\ntest("core", async ({ page }) => { await page.goto("/core"); });\n',
"client/tests/e2e/acceptance.spec.ts": 'import { test } from "@playwright/test";\ntest("acceptance", async ({ page }) => { await page.goto("/core"); });\n',
"client/tests/e2e/local-candidate-witnesses.spec.ts": WITNESS_SPEC,
...specs,
};
for (const [relativePath, source] of Object.entries(defaultSpecs)) {
if (source == null) continue;
const file = path.join(root, relativePath);
mkdirSync(path.dirname(file), { recursive: true });
writeFileSync(file, source, "utf8");
}
return root;
}
function runFixture(root) {
const report = buildReport(root);
return { status: hasBlockingGaps(report) ? 1 : 0, report };
}
function withFixture(options, callback) {
const root = writeFixture(options);
try {
callback(root);
} finally {
rmSync(root, { recursive: true, force: true });
}
}
test("完整 manifest、acceptance spec 与可信 witness 通过", () => {
withFixture({}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 0);
assert.equal(result.report.summary.blockingGapCount, 0);
assert.equal(result.report.summary.coveredCoreBundleCount, 1);
assert.equal(result.report.summary.coveredWitnessCount, 1);
assert.equal(result.report.summary.validAcceptanceSpecCount, 1);
});
});
test("未分类注册路由必须阻断", () => {
withFixture({ routes: ["/core", "/unmapped"] }, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.unclassified, 1);
});
});
test("403 与 wildcard 注册路由不能从分类扫描中豁免", () => {
withFixture({ routes: ["/core", "/403", "*"] }, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.routeCount, 3);
assert.equal(result.report.summary.gapCounts.unclassified, 2);
});
});
test("manual 或 live spec 不能充当核心行为证据", () => {
withFixture({
manifestRoutes: [
{
path: "/core",
classification: "core",
bundle: "core-flow",
behaviorSpecs: ["client/tests/e2e/manual/core.spec.ts"],
},
],
specs: {
"client/tests/e2e/manual/core.spec.ts": 'import { test } from "@playwright/test";\ntest("manual", async ({ page }) => { await page.goto("/core"); });\n',
},
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.manual_only, 1);
});
});
test("核心路由缺失行为测试必须阻断", () => {
withFixture({
manifestRoutes: [{ path: "/core", classification: "core", bundle: "core-flow" }],
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.missing_behavior, 1);
});
});
test("visualRequired 缺失可执行视觉 spec 必须阻断", () => {
withFixture({
manifestRoutes: [
{
path: "/core",
classification: "core",
bundle: "core-flow",
behaviorSpecs: ["client/tests/e2e/core.spec.ts"],
visualRequired: true,
},
],
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.missing_visual, 1);
});
});
test("核心 bundle 缺失 witness 必须阻断", () => {
withFixture({ localCandidateFlows: [] }, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.missing_local_candidate_witness, 1);
});
});
test("重复 bundle 与重复 witness tag 必须阻断", () => {
withFixture({ localCandidateFlows: [candidateFlow(), candidateFlow()] }, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.duplicate_local_candidate_bundle, 1);
assert.equal(result.report.summary.gapCounts.duplicate_witness_tag, 1);
});
});
test("未知 local-candidate bundle 必须阻断", () => {
withFixture({
localCandidateFlows: [candidateFlow(), candidateFlow("unknown-flow", "/core")],
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.unknown_local_candidate_bundle, 1);
});
});
test("重复 core bundle 必须阻断", () => {
withFixture({ coreBundles: ["core-flow", "core-flow"] }, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.duplicate_core_bundle, 1);
});
});
test("orphan manifest 路由必须阻断", () => {
withFixture({
manifestRoutes: [
{
path: "/core",
classification: "core",
bundle: "core-flow",
behaviorSpecs: ["client/tests/e2e/core.spec.ts"],
},
{ path: "/orphan", classification: "supported-noncore" },
],
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.orphan_manifest_route, 1);
});
});
test("witnessRoute 指向未注册路由必须阻断", () => {
withFixture({ localCandidateFlows: [candidateFlow("core-flow", "/missing")] }, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.orphan_witness_route, 1);
});
});
test("witnessRoute 绑定到其他 bundle 必须阻断", () => {
const otherSpec = 'import { test } from "@playwright/test";\ntest("other", async ({ page }) => { await page.goto("/other"); });\n';
withFixture({
routes: ["/core", "/other"],
coreBundles: ["core-flow", "other-flow"],
manifestRoutes: [
{
path: "/core",
classification: "core",
bundle: "core-flow",
behaviorSpecs: ["client/tests/e2e/core.spec.ts"],
},
{
path: "/other",
classification: "core",
bundle: "other-flow",
behaviorSpecs: ["client/tests/e2e/other.spec.ts"],
},
],
localCandidateFlows: [candidateFlow("core-flow", "/other"), candidateFlow("other-flow", "/other")],
specs: { "client/tests/e2e/other.spec.ts": otherSpec },
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.wrong_witness_association, 1);
});
});
test("witness 字段不完整或 tag 不稳定必须阻断", () => {
withFixture({
localCandidateFlows: [candidateFlow("core-flow", "/core", {
witnessTag: "@local-candidate:wrong",
expectedH1: "",
roleFixture: "unknown",
primaryAction: { allowed: "相同", forbidden: "相同" },
})],
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.invalid_witness_tag, 1);
assert.equal(result.report.summary.gapCounts.missing_expected_h1, 1);
assert.equal(result.report.summary.gapCounts.invalid_role_fixture, 1);
assert.equal(result.report.summary.gapCounts.invalid_primary_action, 1);
});
});
test("manual/live acceptance spec 必须阻断", () => {
withFixture({
acceptanceSpecs: ["client/tests/e2e/manual/acceptance.spec.ts"],
specs: {
"client/tests/e2e/manual/acceptance.spec.ts": 'import { test } from "@playwright/test";\ntest("manual", async () => {});\n',
},
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.equal(result.report.summary.gapCounts.manual_or_live_acceptance_spec, 1);
});
});
test("候选 spec 不同路径使用同一 basename 必须阻断", () => {
withFixture({
acceptanceSpecs: ["client/tests/e2e/nested/local-candidate-witnesses.spec.ts"],
specs: {
"client/tests/e2e/nested/local-candidate-witnesses.spec.ts":
'import { test } from "@playwright/test";\ntest("acceptance", async ({ page }) => { await page.goto("/core"); });\n',
},
}, (root) => {
const result = runFixture(root);
assert.equal(result.status, 1);
assert.deepEqual(result.report.duplicateCandidateSpecBasenames, ["local-candidate-witnesses.spec.ts"]);
assert.equal(result.report.summary.gapCounts.duplicate_candidate_spec_basename, 1);
});
});
@@ -0,0 +1,106 @@
import assert from "node:assert/strict";
import {
chmodSync,
existsSync,
mkdtempSync,
mkdirSync,
readFileSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { spawnSync } from "node:child_process";
import test from "node:test";
const repoRoot = path.resolve(new URL("../../..", import.meta.url).pathname);
const sourceScript = path.join(repoRoot, "scripts/check-minimal.sh");
const localCandidateRunner = path.join(repoRoot, "scripts/qa/run-local-candidate.sh");
function writeExecutable(file, source) {
mkdirSync(path.dirname(file), { recursive: true });
writeFileSync(file, source, "utf8");
chmodSync(file, 0o755);
}
test("local-candidate 基础 profile 在没有 issues 目录时不调用历史 CSV 门禁", () => {
const fixtureRoot = mkdtempSync(path.join(tmpdir(), "hyb-local-candidate-profile-"));
try {
const scriptSource = readFileSync(sourceScript, "utf8");
const fixtureScript = path.join(fixtureRoot, "scripts/check-minimal.sh");
writeExecutable(fixtureScript, scriptSource);
mkdirSync(path.join(fixtureRoot, "server"), { recursive: true });
mkdirSync(path.join(fixtureRoot, "client"), { recursive: true });
for (const match of scriptSource.matchAll(/\bbash -n ([^\s]+)/gu)) {
const relativeFile = match[1];
for (const base of [fixtureRoot, path.join(fixtureRoot, "server")]) {
const file = path.join(base, relativeFile);
mkdirSync(path.dirname(file), { recursive: true });
writeFileSync(file, "#!/usr/bin/env bash\n", "utf8");
}
}
const binDir = path.join(fixtureRoot, "bin");
const commandLog = path.join(fixtureRoot, "commands.log");
writeExecutable(path.join(binDir, "node"), `#!/usr/bin/env bash
printf 'node %s\\n' "$*" >> "$CHECK_MINIMAL_COMMAND_LOG"
if [[ "$*" == *check-process-contract.mjs* ]]; then exit 91; fi
exit 0
`);
writeExecutable(path.join(binDir, "npm"), `#!/usr/bin/env bash
printf 'npm %s\\n' "$*" >> "$CHECK_MINIMAL_COMMAND_LOG"
exit 0
`);
writeExecutable(path.join(binDir, "python3"), `#!/usr/bin/env bash
printf 'python3 %s\\n' "$*" >> "$CHECK_MINIMAL_COMMAND_LOG"
exit 92
`);
const result = spawnSync("bash", [fixtureScript, "local-candidate"], {
cwd: fixtureRoot,
encoding: "utf8",
env: {
...process.env,
PATH: `${binDir}:${process.env.PATH ?? ""}`,
CHECK_MINIMAL_COMMAND_LOG: commandLog,
},
});
assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
const commands = readFileSync(commandLog, "utf8");
assert.doesNotMatch(commands, /check-process-contract|validate-feature-matrix|python3/u);
assert.equal(existsSync(path.join(fixtureRoot, "issues")), false);
} finally {
rmSync(fixtureRoot, { recursive: true, force: true });
}
});
test("local-candidate 结果标签严格区分 full、focused 与 list", () => {
const source = readFileSync(localCandidateRunner, "utf8");
const blockStart = source.lastIndexOf('if [[ "$MODE" == "full" ]]; then');
const blockEnd = source.indexOf("\nfi", blockStart);
assert.notEqual(blockStart, -1, "缺少 full/focused 结果标签分支");
assert.notEqual(blockEnd, -1, "full/focused 结果标签分支不完整");
const resultLabelBlock = source.slice(blockStart, blockEnd + "\nfi".length);
const runLabelBlock = (mode) => spawnSync("bash", ["-c", resultLabelBlock], {
encoding: "utf8",
env: { ...process.env, MODE: mode },
});
const full = runLabelBlock("full");
const focused = runLabelBlock("focused");
assert.equal(full.status, 0, full.stderr);
assert.match(full.stdout, /LOCAL_CANDIDATE_PASS/u);
assert.doesNotMatch(full.stdout, /FOCUSED_BROWSER_PASS/u);
assert.equal(focused.status, 0, focused.stderr);
assert.match(focused.stdout, /FOCUSED_BROWSER_PASS/u);
assert.doesNotMatch(focused.stdout, /LOCAL_CANDIDATE_PASS/u);
assert.equal(source.match(/LOCAL_CANDIDATE_PASS/gu)?.length, 1);
assert.match(
source,
/if \[\[ "\$MODE" == "list" \]\]; then[\s\S]*?LIST_ONLY[\s\S]*?exit 0[\s\S]*?\nfi/u,
);
});
@@ -0,0 +1,40 @@
import assert from "node:assert/strict";
import test from "node:test";
import { validateLoopbackHttpUrl, validateTcpPort } from "../validate-loopback-url.mjs";
for (const [input, expected] of [
["http://127.0.0.1:5178", "http://127.0.0.1:5178"],
["http://localhost:3000/", "http://localhost:3000"],
["http://[::1]:4173", "http://[::1]:4173"],
]) {
test(`accepts loopback origin ${input}`, () => {
assert.equal(validateLoopbackHttpUrl(input), expected);
});
}
for (const input of ["1", "80", "5178", "65535"]) {
test(`accepts canonical TCP port ${input}`, () => {
assert.equal(validateTcpPort(input), input);
});
}
for (const input of ["", "0", "065", "65536", "5178/path", "[email protected]", "1.5", "-1"]) {
test(`rejects ambiguous or invalid TCP port ${input || "<empty>"}`, () => {
assert.throws(() => validateTcpPort(input));
});
}
for (const input of [
"https://127.0.0.1:5178",
"http://example.invalid:5178",
"http://localhost.example.invalid:5178",
"http://[email protected]:5178",
"http://remote.invalid@localhost:5178",
"http://user:[email protected]:5178",
"http://127.0.0.1:5178/path",
"not-a-url",
]) {
test(`rejects non-loopback or ambiguous target ${input}`, () => {
assert.throws(() => validateLoopbackHttpUrl(input));
});
}
@@ -0,0 +1,189 @@
import assert from "node:assert/strict";
import test from "node:test";
import { verifyLocalCandidateResults } from "../verify-local-candidate-results.mjs";
const bundles = [
"login-logout",
"reimbursement",
"approval",
"invoice",
"procurement",
"project-contract",
"payment-ap",
"people-audit",
"attendance-archive",
"mobile-workspace",
];
function manifest() {
return {
localCandidateFlows: bundles.map((bundle) => ({
bundle,
witnessTag: `@local-candidate:${bundle}`,
witnessSpec: "client/tests/e2e/synthetic-local-candidate.spec.ts",
})),
};
}
function spec(tag, status = "passed", overrides = {}) {
return {
title: tag,
file: "client/tests/e2e/synthetic-local-candidate.spec.ts",
line: 12,
tags: [],
tests: [
{
expectedStatus: "passed",
results: [{ status }],
},
],
...overrides,
};
}
function results(specs, overrides = {}) {
return {
suites: [{ title: "local candidate", specs }],
errors: [],
stats: { expected: specs.length, skipped: 0, unexpected: 0 },
...overrides,
};
}
test("10 个唯一 witness tag 全部 passed 时通过", () => {
const summary = verifyLocalCandidateResults(
manifest(),
results(bundles.map((bundle) => spec(`@local-candidate:${bundle}`))),
);
assert.equal(summary.ok, true);
assert.equal(summary.passedTagCount, 10);
assert.equal(summary.skippedTagCount, 0);
});
test("结果缺失 tag 必须阻断", () => {
const summary = verifyLocalCandidateResults(
manifest(),
results(bundles.slice(1).map((bundle) => spec(`@local-candidate:${bundle}`))),
);
assert.equal(summary.ok, false);
assert.deepEqual(summary.missingTags, ["@local-candidate:login-logout"]);
assert.ok(summary.issues.includes("missing_tag_result"));
});
test("重复 tag 结果必须阻断", () => {
const specs = bundles.map((bundle) => spec(`@local-candidate:${bundle}`));
specs.push(spec("@local-candidate:login-logout"));
const summary = verifyLocalCandidateResults(manifest(), results(specs));
assert.equal(summary.ok, false);
assert.deepEqual(summary.duplicateTags, ["@local-candidate:login-logout"]);
});
test("未知 tag 结果必须阻断", () => {
const specs = bundles.map((bundle) => spec(`@local-candidate:${bundle}`));
specs.push(spec("@local-candidate:unknown"));
const summary = verifyLocalCandidateResults(manifest(), results(specs));
assert.equal(summary.ok, false);
assert.deepEqual(summary.unknownTags, ["@local-candidate:unknown"]);
});
test("全部 witness skipped 必须阻断", () => {
const summary = verifyLocalCandidateResults(
manifest(),
results(bundles.map((bundle) => spec(`@local-candidate:${bundle}`, "skipped"))),
);
assert.equal(summary.ok, false);
assert.equal(summary.skippedTagCount, 10);
assert.equal(summary.passedTagCount, 0);
assert.ok(summary.issues.includes("skipped_tag_result"));
});
test("任一 witness 或整体 Playwright suite 失败必须阻断", () => {
const specs = bundles.map((bundle) =>
spec(`@local-candidate:${bundle}`, bundle === "payment-ap" ? "failed" : "passed"),
);
const summary = verifyLocalCandidateResults(
manifest(),
results(specs, { errors: [{}], stats: { expected: 9, skipped: 0, unexpected: 1 } }),
);
assert.equal(summary.ok, false);
assert.deepEqual(summary.failedTags, ["@local-candidate:payment-ap"]);
assert.ok(summary.issues.includes("playwright_suite_failed"));
assert.deepEqual(summary.failedTests, [{
file: "synthetic-local-candidate.spec.ts",
line: 12,
title: "@local-candidate:payment-ap",
status: "failed",
}]);
});
test("非 witness acceptance 用例 skipped 也必须阻断且诊断不泄露绝对路径", () => {
const specs = bundles.map((bundle) => spec(`@local-candidate:${bundle}`));
specs.push(spec("本地附加验收", "skipped", {
file: "/private/workspace/client/tests/e2e/acceptance.spec.ts",
line: 27,
}));
const summary = verifyLocalCandidateResults(
manifest(),
results(specs, { stats: { expected: 10, skipped: 1, unexpected: 0 } }),
);
assert.equal(summary.ok, false);
assert.ok(summary.issues.includes("playwright_suite_skipped"));
assert.equal(summary.suiteSkippedTestCount, 1);
assert.deepEqual(summary.skippedTests, [{
file: "acceptance.spec.ts",
line: 27,
title: "本地附加验收",
status: "skipped",
}]);
});
test("单一测试合并多个 witness tag 不能冒充十个独立流程", () => {
const mergedTitle = bundles.map((bundle) => `@local-candidate:${bundle}`).join(" ");
const summary = verifyLocalCandidateResults(manifest(), results([spec(mergedTitle)]));
assert.equal(summary.ok, false);
assert.equal(summary.totalTestResultCount, 1);
assert.ok(summary.issues.includes("multi_tag_test_result"));
assert.equal(summary.multiTagTests.length, 1);
});
test("witness tag 必须来自 manifest 指定的测试文件", () => {
const specs = bundles.map((bundle) => spec(`@local-candidate:${bundle}`));
specs[0] = spec("@local-candidate:login-logout", "passed", {
file: "/private/workspace/client/tests/e2e/unrelated.spec.ts",
});
const summary = verifyLocalCandidateResults(manifest(), results(specs));
assert.equal(summary.ok, false);
assert.ok(summary.issues.includes("wrong_witness_spec_result"));
assert.deepEqual(summary.wrongWitnessSpecs, [{
tag: "@local-candidate:login-logout",
expectedFile: "synthetic-local-candidate.spec.ts",
observedFile: "unrelated.spec.ts",
}]);
});
test("Playwright JSON 将 file 放在父 suite 时仍能核对 witness 来源", () => {
const specs = bundles.map((bundle) => {
const item = spec(`@local-candidate:${bundle}`);
delete item.file;
return item;
});
const report = results([], {
suites: [{
title: "local candidate witnesses",
file: "tests/e2e/synthetic-local-candidate.spec.ts",
specs,
}],
});
const summary = verifyLocalCandidateResults(manifest(), report);
assert.equal(summary.ok, true);
assert.deepEqual(summary.wrongWitnessSpecs, []);
});
test("Playwright JSON 只提供 spec basename 时按 manifest 唯一 basename 核对", () => {
const specs = bundles.map((bundle) => spec(`@local-candidate:${bundle}`, "passed", {
file: "synthetic-local-candidate.spec.ts",
}));
const summary = verifyLocalCandidateResults(manifest(), results(specs));
assert.equal(summary.ok, true);
assert.deepEqual(summary.wrongWitnessSpecs, []);
});