Standardize QA coverage IDs on dotted names (#94702) · openclaw/openclaw@e12cf72
RomneyDa
·
2026-06-19
·
via Recent Commits to openclaw:main
File tree
.agents/skills/claw-score
| Original file line number | Diff line number | Diff line change |
|---|
@@ -30,6 +30,9 @@ out of this repo. If a score needs private evidence, use the redacted
|
30 | 30 | completeness-instruction paths. |
31 | 31 | - Feature `coverageIds` are ANDed proof targets, not aliases. A feature may |
32 | 32 | list multiple IDs when each ID proves part of one capability. |
| 33 | +- Coverage IDs use dotted `namespace.behavior` form, with lowercase |
| 34 | + alphanumeric/dash segments. Profile, surface, and category IDs may remain |
| 35 | + dashed or dotted. |
33 | 36 | - Keep categories and feature names unique, product-shaped, and broader than raw |
34 | 37 | coverage IDs. Do not promote generic IDs into standalone feature names. |
35 | 38 | - Avoid duplicate coverage-ID bundles under different feature names in one |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -59,6 +59,9 @@ selected-category counts and missing coverage IDs; the individual evidence
|
59 | 59 | entries remain the source of truth for the tests, coverage roles, and results. |
60 | 60 | Taxonomy feature coverage IDs are exact proof targets, not aliases. Primary |
61 | 61 | scenario coverage fulfills matching IDs; secondary coverage stays advisory. |
| 62 | +Coverage IDs use dotted `namespace.behavior` form with lowercase |
| 63 | +alphanumeric/dash segments; profile, surface, and category IDs may still use |
| 64 | +the existing dashed or dotted taxonomy IDs. |
62 | 65 | Slim evidence omits per-entry `execution` and sets `evidenceMode: "slim"`; |
63 | 66 | `smoke-ci` defaults to slim, and `--evidence-mode full` restores full entries: |
64 | 67 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -14,6 +14,7 @@ const TEST_EXECUTABLE_COVERAGE_ID = "channels.dm";
|
14 | 14 | const TEST_BROWSER_CATEGORY_ID = "browser-control-ui-and-webchat.browser-ui"; |
15 | 15 | const TEST_BROWSER_COVERAGE_ID = "ui.control"; |
16 | 16 | const TEST_WEBCHAT_COVERAGE_ID = "ui.webchat"; |
| 17 | +const DOTTED_COVERAGE_ID_PATTERN = /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)+$/; |
17 | 18 | |
18 | 19 | function testMaturityTaxonomy(params?: { |
19 | 20 | categoryId?: string; |
@@ -138,6 +139,11 @@ describe("qa coverage report", () => {
|
138 | 139 | expect(inventory.scorecardTaxonomy.evidenceRefCount).toBeGreaterThan(0); |
139 | 140 | expect(inventory.scorecardTaxonomy.scenarioCoverageIdCount).toBeGreaterThan(0); |
140 | 141 | expect(inventory.scorecardTaxonomy.unknownCoverageIdCount).toBe(0); |
| 142 | +expect( |
| 143 | +inventory.scorecardTaxonomy.categories |
| 144 | +.flatMap((category) => category.coverageIds) |
| 145 | +.every((coverageId) => DOTTED_COVERAGE_ID_PATTERN.test(coverageId)), |
| 146 | +).toBe(true); |
141 | 147 | expect(inventory.scorecardTaxonomy.validationIssues.length).toBeGreaterThan(0); |
142 | 148 | expect( |
143 | 149 | inventory.scorecardTaxonomy.validationIssues.some((issue) => |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -198,7 +198,7 @@ describe("evidence gallery", () => {
|
198 | 198 | surface: "web-ui", |
199 | 199 | }, |
200 | 200 | { |
201 | | -coverageIds: ["cli-entrypoint"], |
| 201 | +coverageIds: ["cli.entrypoint"], |
202 | 202 | runner: { |
203 | 203 | availability: "local", |
204 | 204 | command: "pnpm openclaw qa suite --scenario ux-matrix-evidence-dashboard", |
@@ -274,7 +274,7 @@ describe("evidence gallery", () => {
|
274 | 274 | title: "UX Matrix: cli / error-state", |
275 | 275 | source: { path: "scripts/ux-matrix/dashboard.ts" }, |
276 | 276 | }, |
277 | | -coverage: [{ id: "status-snapshots", role: "primary" }], |
| 277 | +coverage: [{ id: "cli.status-snapshots", role: "primary" }], |
278 | 278 | execution: { |
279 | 279 | runner: "ux-matrix-dashboard", |
280 | 280 | environment: { |
@@ -359,7 +359,7 @@ describe("evidence gallery", () => {
|
359 | 359 | { |
360 | 360 | artifactKinds: [], |
361 | 361 | artifactPaths: [], |
362 | | -coverageIds: ["cli-entrypoint"], |
| 362 | +coverageIds: ["cli.entrypoint"], |
363 | 363 | runner: { |
364 | 364 | availability: "local", |
365 | 365 | command: "pnpm openclaw qa suite --scenario ux-matrix-evidence-dashboard", |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -346,7 +346,7 @@ describe("evidence summary", () => {
|
346 | 346 | id: "control-ui.browser-run", |
347 | 347 | title: "Control UI browser workflow", |
348 | 348 | sourcePath: "ui/control-ui.e2e.test.ts", |
349 | | -primaryCoverageIds: ["control-ui.browser"], |
| 349 | +primaryCoverageIds: ["ui.control"], |
350 | 350 | docsRefs: ["docs/concepts/qa-e2e-automation.md"], |
351 | 351 | codeRefs: ["ui/"], |
352 | 352 | }, |
@@ -374,7 +374,7 @@ describe("evidence summary", () => {
|
374 | 374 | }, |
375 | 375 | coverage: [ |
376 | 376 | { |
377 | | -id: "control-ui.browser", |
| 377 | +id: "ui.control", |
378 | 378 | role: "primary", |
379 | 379 | }, |
380 | 380 | ], |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -25,6 +25,8 @@ function listScenarioMarkdownPaths(dir = "qa/scenarios"): string[] {
|
25 | 25 | } |
26 | 26 | |
27 | 27 | describe("qa scenario catalog", () => { |
| 28 | +const dottedCoverageIdPattern = /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)+$/; |
| 29 | + |
28 | 30 | it("keeps repo-backed scenarios YAML-only", () => { |
29 | 31 | expect(listScenarioMarkdownPaths()).toStrictEqual([]); |
30 | 32 | }); |
@@ -74,6 +76,17 @@ describe("qa scenario catalog", () => {
|
74 | 76 | .filter((scenario) => !(scenario.coverage?.primary.length ?? 0)) |
75 | 77 | .map((scenario) => scenario.id), |
76 | 78 | ).toStrictEqual([]); |
| 79 | +expect( |
| 80 | +pack.scenarios.every( |
| 81 | +(scenario) => |
| 82 | +(scenario.coverage?.primary ?? []).every((coverageId) => |
| 83 | +dottedCoverageIdPattern.test(coverageId), |
| 84 | +) && |
| 85 | +(scenario.coverage?.secondary ?? []).every((coverageId) => |
| 86 | +dottedCoverageIdPattern.test(coverageId), |
| 87 | +), |
| 88 | +), |
| 89 | +).toBe(true); |
77 | 90 | expect(readQaScenarioById("memory-recall").coverage?.primary).toContain("memory.recall"); |
78 | 91 | }); |
79 | 92 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -87,8 +87,8 @@ const qaScenarioExecutionSchema = z.union([
|
87 | 87 | const qaCoverageIdSchema = z |
88 | 88 | .string() |
89 | 89 | .trim() |
90 | | -.regex(/^[a-z0-9]+(?:[.-][a-z0-9]+)*$/, { |
91 | | -message: "coverage ids must use lowercase dotted or dashed tokens", |
| 90 | +.regex(/^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)+$/, { |
| 91 | +message: "coverage ids must use lowercase dotted tokens", |
92 | 92 | }); |
93 | 93 | |
94 | 94 | const qaCoverageIdListSchema = z.array(qaCoverageIdSchema).min(1); |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -11,7 +11,14 @@ const qaScorecardIdSchema = z
|
11 | 11 | .string() |
12 | 12 | .trim() |
13 | 13 | .regex(/^[a-z0-9]+(?:[.-][a-z0-9]+)*$/, { |
14 | | -message: "scorecard and coverage ids must use lowercase dotted or dashed tokens", |
| 14 | +message: "scorecard ids must use lowercase dotted or dashed tokens", |
| 15 | +}); |
| 16 | + |
| 17 | +const qaCoverageIdSchema = z |
| 18 | +.string() |
| 19 | +.trim() |
| 20 | +.regex(/^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)+$/, { |
| 21 | +message: "coverage ids must use lowercase dotted tokens", |
15 | 22 | }); |
16 | 23 | |
17 | 24 | function isRepoRootRelativeRef(value: string) { |
@@ -31,7 +38,7 @@ const qaScorecardProfileSchema = z.object({
|
31 | 38 | |
32 | 39 | const qaMaturityFeatureSchema = z.object({ |
33 | 40 | name: z.string().trim().min(1), |
34 | | -coverageIds: z.array(qaScorecardIdSchema).default([]), |
| 41 | +coverageIds: z.array(qaCoverageIdSchema).default([]), |
35 | 42 | description: z.string().trim().min(1).optional(), |
36 | 43 | }); |
37 | 44 | |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -726,9 +726,9 @@ describe("qa test file scenario runner", () => {
|
726 | 726 | "tools.evidence", |
727 | 727 | "workspace.artifacts", |
728 | 728 | "ui.control", |
729 | | -"control-ui", |
730 | | -"cli-entrypoint", |
731 | | -"status-snapshots", |
| 729 | +"gateway.control-ui-hosting", |
| 730 | +"cli.entrypoint", |
| 731 | +"cli.status-snapshots", |
732 | 732 | ]), |
733 | 733 | ); |
734 | 734 | const artifactKinds = evidence.entries.flatMap( |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -213,7 +213,7 @@ describe("QA Lab UI evidence render", () => {
|
213 | 213 | { |
214 | 214 | artifactKinds: [], |
215 | 215 | artifactPaths: [], |
216 | | -coverageIds: ["cli-entrypoint"], |
| 216 | +coverageIds: ["cli.entrypoint"], |
217 | 217 | runner: { |
218 | 218 | availability: "local", |
219 | 219 | command: "pnpm openclaw qa suite --scenario ux-matrix-evidence-dashboard", |
@@ -247,7 +247,7 @@ describe("QA Lab UI evidence render", () => {
|
247 | 247 | expect(html).toContain('data-evidence-entry-id="ux-matrix.web-ui.first-run"'); |
248 | 248 | expect(html).toContain("evidence-matrix-cell-proof-gap"); |
249 | 249 | expect(html).toContain("not executed in this run"); |
250 | | -expect(html).toContain("Coverage: cli-entrypoint"); |
| 250 | +expect(html).toContain("Coverage: cli.entrypoint"); |
251 | 251 | expect(html).toContain("Runner: cli-status"); |
252 | 252 | expect(html).toContain("Open media artifact"); |
253 | 253 | expect(html).toContain("Open video artifact"); |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。