mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-25 02:01:16 +00:00
refactor(qa): keep synthetic UX evidence out of scenario catalog (#109315)
* refactor(qa): keep UX evidence producer out of catalog * test(qa): preserve UX producer runner integration
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Produces a QA Lab UX Matrix evidence bundle through the script scenario contract.
|
||||
// Produces standalone QA Lab UX Matrix fixture artifacts for gallery and evidence tests.
|
||||
import { execFile } from "node:child_process";
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
@@ -16,16 +16,13 @@ import {
|
||||
type QaEvidenceSummaryEntry,
|
||||
type QaEvidenceSummaryJson,
|
||||
} from "../../extensions/qa-lab/src/evidence-summary.js";
|
||||
import { readQaScenarioById } from "../../extensions/qa-lab/src/scenario-catalog.js";
|
||||
import {
|
||||
ensurePlaywrightChromium,
|
||||
resolveSystemChromiumExecutablePath,
|
||||
} from "../ensure-playwright-chromium.mjs";
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const SCENARIO_ID = "ux-matrix-evidence-dashboard";
|
||||
const SOURCE_PATH = "scripts/qa/ux-matrix-evidence-producer.ts";
|
||||
const SUITE_COMMAND = `pnpm openclaw qa suite --scenario ${SCENARIO_ID}`;
|
||||
|
||||
type MatrixCell = {
|
||||
artifacts: Array<{ kind: string; path: string }>;
|
||||
@@ -227,21 +224,7 @@ function buildExecution(params: {
|
||||
};
|
||||
}
|
||||
|
||||
function readCanonicalScenarioCoverage(): QaEvidenceSummaryEntry["coverage"] {
|
||||
// Matrix cells are artifacts of one catalog scenario, not independent scenarios.
|
||||
// Evidence therefore uses that scenario's mapping instead of cell-local coverage IDs.
|
||||
const coverage = readQaScenarioById(SCENARIO_ID).coverage;
|
||||
return [
|
||||
...(coverage?.primary ?? []).map((id) => ({ id, role: "primary" as const })),
|
||||
...(coverage?.secondary ?? []).map((id) => ({ id, role: "secondary" as const })),
|
||||
];
|
||||
}
|
||||
|
||||
function buildEvidenceEntry(
|
||||
cell: MatrixCell,
|
||||
repoRoot: string,
|
||||
coverage: QaEvidenceSummaryEntry["coverage"],
|
||||
): QaEvidenceSummaryEntry {
|
||||
function buildEvidenceEntry(cell: MatrixCell, repoRoot: string): QaEvidenceSummaryEntry {
|
||||
const source = `ux-matrix:${cell.surface}:${cell.stage}`;
|
||||
return {
|
||||
test: {
|
||||
@@ -250,7 +233,8 @@ function buildEvidenceEntry(
|
||||
title: cell.title,
|
||||
source: { path: SOURCE_PATH },
|
||||
},
|
||||
coverage,
|
||||
// These entries prove the evidence/gallery infrastructure, not product taxonomy behavior.
|
||||
coverage: [],
|
||||
refs: [
|
||||
{ kind: "code", path: SOURCE_PATH },
|
||||
{ kind: "docs", path: "docs/concepts/qa-e2e-automation.md" },
|
||||
@@ -282,13 +266,12 @@ function buildEvidenceSummary(params: {
|
||||
generatedAt: string;
|
||||
repoRoot: string;
|
||||
}): QaEvidenceSummaryJson {
|
||||
const coverage = readCanonicalScenarioCoverage();
|
||||
return validateQaEvidenceSummaryJson({
|
||||
kind: QA_EVIDENCE_SUMMARY_KIND,
|
||||
schemaVersion: QA_EVIDENCE_SUMMARY_SCHEMA_VERSION,
|
||||
generatedAt: params.generatedAt,
|
||||
evidenceMode: "full",
|
||||
entries: params.cells.map((cell) => buildEvidenceEntry(cell, params.repoRoot, coverage)),
|
||||
entries: params.cells.map((cell) => buildEvidenceEntry(cell, params.repoRoot)),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -500,9 +483,9 @@ async function writeProducerArtifactFixtureHtml(params: {
|
||||
</style>
|
||||
<main>
|
||||
<h1>UX Matrix Producer Artifact Fixture</h1>
|
||||
<p class="meta">Script-produced ${escapeHtml(QA_EVIDENCE_FILENAME)} for ${escapeHtml(
|
||||
SCENARIO_ID,
|
||||
)}; this fixture is not the QA Lab Evidence Archive UI.</p>
|
||||
<p class="meta">Standalone script-produced ${escapeHtml(
|
||||
QA_EVIDENCE_FILENAME,
|
||||
)}; this fixture is not the QA Lab Evidence Archive UI or product-behavior proof.</p>
|
||||
<section class="panel">
|
||||
<h2>UX Matrix entries</h2>
|
||||
<ul>${entryRows}</ul>
|
||||
@@ -612,7 +595,6 @@ async function writeProducerMetadata(params: {
|
||||
cells: readonly MatrixCell[];
|
||||
repoRoot: string;
|
||||
}) {
|
||||
const coverageIds = readCanonicalScenarioCoverage().map((coverage) => coverage.id);
|
||||
const counts = params.cells.reduce<Record<string, number>>((acc, cell) => {
|
||||
acc[cell.status] = (acc[cell.status] ?? 0) + 1;
|
||||
return acc;
|
||||
@@ -620,13 +602,12 @@ async function writeProducerMetadata(params: {
|
||||
await writeJson(path.join(params.artifactBase, "manifest.json"), {
|
||||
kind: "openclaw.qa.ux-matrix",
|
||||
run: {
|
||||
scenarioId: SCENARIO_ID,
|
||||
status: counts.fail ? "fail" : counts.blocked ? "blocked" : "pass",
|
||||
},
|
||||
});
|
||||
await writeJson(path.join(params.artifactBase, "matrix.json"), {
|
||||
cells: params.cells.map((cell) => ({
|
||||
coverageIds,
|
||||
coverageIds: [],
|
||||
stage: cell.stage,
|
||||
status: cell.status,
|
||||
surface: cell.surface,
|
||||
@@ -635,7 +616,7 @@ async function writeProducerMetadata(params: {
|
||||
});
|
||||
await writeJson(path.join(params.artifactBase, "release-ledger.json"), {
|
||||
entries: params.cells.map((cell) => ({
|
||||
coverageIds,
|
||||
coverageIds: [],
|
||||
stage: cell.stage,
|
||||
status: cell.status,
|
||||
surface: cell.surface,
|
||||
@@ -644,13 +625,10 @@ async function writeProducerMetadata(params: {
|
||||
});
|
||||
await writeText(
|
||||
path.join(params.artifactBase, "commands.txt"),
|
||||
[
|
||||
`${SUITE_COMMAND} --output-dir ${toRepoRelativePath(params.repoRoot, params.artifactBase)}`,
|
||||
`node --import tsx ${SOURCE_PATH} --artifact-base ${toRepoRelativePath(
|
||||
params.repoRoot,
|
||||
params.artifactBase,
|
||||
)}`,
|
||||
].join("\n") + "\n",
|
||||
`node --import tsx ${SOURCE_PATH} --artifact-base ${toRepoRelativePath(
|
||||
params.repoRoot,
|
||||
params.artifactBase,
|
||||
)}\n`,
|
||||
);
|
||||
await writeText(
|
||||
path.join(params.artifactBase, "scorecard.md"),
|
||||
|
||||
Reference in New Issue
Block a user