Skip to content

Commit d475c70

Browse files
baozhoutaoclaude
andauthored
qa/checklist: result-issue-per-run + checklist-author/checklist-test skills + list-filename selector (#7304)
* qa/checklist: result issue per run — text-only, repro rules not screenshots Encode the maintainer decision for how a checklist run reports results: - Every completed run (pass or fail alike) files exactly ONE GitHub issue as its durable record, labeled qa-run; add bug/regression when any clause failed so a defect triages straight from the run issue. - The issue is pure text. Screenshots are live judgment aids only — taken to reach a verdict, discarded with the run environment, never uploaded, linked, or committed. This keeps results out of the repo tree AND out of the issue. - Every fail carries a reproduction rule (ordered steps / API calls / selector path + expected-vs-actual) instead of a picture, so a human or fresh agent can re-hit it without any captured image. Updates checklist-run SKILL.md §4 + §2, RUNNER.md (rule 2 + Run records), README.md (release-sweep results), and runs/README.md (format contract). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YD9f6FYyMraUWYeJf53V43 * qa/checklist: rename skills to checklist-author / checklist-test pair Give the two checklist skills a shared 'checklist-' namespace so they read as one authoring/execution pair: - coverage-sweep → checklist-author (finds gaps, AUTHORS items) - checklist-run → checklist-test (runs items, produces the report issue) Natural-language triggers ('coverage sweep', '测一下 <功能>') are unchanged; only the skill ids, H1 titles, cross-references and one script comment move. internal: true markers untouched. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YD9f6FYyMraUWYeJf53V43 * qa/checklist: resolver accepts a list-directory filename with no prefix checklist-select now takes a prefix-less selector that looks like a path: - `records-forms.json` (or a full `…/areas/records-forms.json` path) → that area, matched by basename — paste a list-directory filename, run the whole area. - a bare path with a `/` or a code extension → resolves as `file:<path>` (test whatever covers that source file), no prefix to remember. Bare ids and bare area names are unchanged. Adds 5 self-test cases (17 total) and documents the conveniences in the header and the checklist-test §0 table. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YD9f6FYyMraUWYeJf53V43 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent b56a163 commit d475c70

6 files changed

Lines changed: 121 additions & 58 deletions

File tree

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
name: coverage-sweep
2+
name: checklist-author
33
description: >
44
Re-audit the platform test checklist (docs/qa/platform-checklist/) for coverage
55
gaps and author the missing items — the five-angle capability sweep. Use whenever
@@ -16,7 +16,7 @@ metadata:
1616
internal: true
1717
---
1818

19-
# Coverage sweepkeep the platform test checklist honest
19+
# Checklist author — the coverage sweep that keeps the checklist honest
2020

2121
The canonical method lives in **`docs/qa/platform-checklist/SWEEP.md`** — read it
2222
first and follow it; this skill is the trigger and the orchestration contract, not a
Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
---
2-
name: checklist-run
2+
name: checklist-test
33
description: >
44
Execute the platform test checklist (docs/qa/platform-checklist/) against a real
55
running app and produce a run record. Use whenever the maintainer says "测一下
66
<功能>", "跑这个测试项", "run the checklist for <area/item>", "test this feature
77
file", "验证 <功能点>", or points at a framework source file and asks whether it
88
still works. Takes a SELECTOR (item id · area · capability kind · priority · a
99
release · or a source-file path) and drives every matched item through its steps
10-
following RUNNER.md. The companion to `coverage-sweep` (which AUTHORS items); this
10+
following RUNNER.md. The companion to `checklist-author` (which AUTHORS items); this
1111
one RUNS them. NOT a customer-published skill — internal agent tooling (lives in
1212
.claude/, never in the published `skills/` dir).
1313
metadata:
@@ -17,7 +17,7 @@ metadata:
1717
internal: true
1818
---
1919

20-
# Checklist run — execute selected items against a live app
20+
# Checklist test — execute selected items against a live app
2121

2222
You resolve a **selector** to a set of checklist items, boot the app in isolation, drive
2323
each item's steps in the browser / over the API, and emit a **run record**. The method
@@ -44,11 +44,12 @@ Selectors (one per run):
4444
|---|---|
4545
| `platform-core.console-login` (bare id) | that one item |
4646
| `area:records-forms` (or bare `records-forms`) | every item in the area |
47+
| **`records-forms.json`** (or the full `…/areas/records-forms.json` path) | **every item in that area — a list-directory filename works with no prefix** |
4748
| `capability:hook` | items mapped to a metadata kind in `coverage.json` |
4849
| `priority:P0` | the standing smoke |
4950
| `surface:api` | every API-surface item (cheap — no browser build needed) |
5051
| `since:v17` | everything introduced in a release (the release-sweep filter) |
51-
| **`file:packages/plugins/plugin-approvals/src/approval-service.ts`** | **items whose `source[]` cites that file — "test whatever covers this file"** |
52+
| **`file:packages/plugins/plugin-approvals/src/approval-service.ts`** | **items whose `source[]` cites that file — "test whatever covers this file"** (a bare path with a `/` or a code extension auto-resolves as `file:` too) |
5253
| `all` | the whole checklist |
5354

5455
`--json` gives the runnable list (id · priority · surface · revision). **Blocked items are
@@ -83,7 +84,8 @@ Build once, up front, for the whole run.
8384
- Execute each item's `steps` faithfully; judge each `acceptance` clause and each
8485
`negative` against its declared `oracle`, capturing the `evidence` the clause names.
8586
**Server truth outranks pixels; DOM only after a screenshot confirms render; a `fail`
86-
needs reproduction ×2 + the automation self-check + a filed issue** (RUNNER §rules).
87+
needs reproduction ×2 + the automation self-check + a reproduction rule in the run
88+
issue** (RUNNER §rules).
8789

8890
## 3. When the run teaches you something about the ITEM
8991

@@ -94,21 +96,42 @@ a `history` entry, keep `node scripts/check-platform-checklist.mjs` green, and l
9496
task branch. Product defects found while running go to `FOLLOW-UPS.md` (or a filed issue)
9597
as expected-fail probes — never tick a clause green over a real defect.
9698

97-
## 4. The run record — results do NOT go in the repo
98-
99-
Write one JSON per run in the shape RUNNER.md defines (env with framework sha +
100-
`.objectui-sha` + port + db; per-clause verdicts each naming its evidence; derived item
101-
verdict; issues). **`runs/` is git-ignored** — the record and its screenshots stay in the
102-
executing environment / the tracking issue / an external QA store, never committed. The
103-
committed source is the checklist under `areas/`; a run is a dated assertion about one
104-
build and belongs with that build's artifacts. Report the per-clause verdict table + the
105-
evidence paths + the env-setup-vs-test time split back to the maintainer.
99+
## 4. The result issue — one GitHub issue per run, text only
100+
101+
Every completed run — **pass or fail alike** — files exactly one GitHub issue as its
102+
durable record. Nothing about a run enters the repo tree: not the JSON, not screenshots.
103+
The JSON run record (RUNNER.md shape) is scratch in the executing environment; `runs/`
104+
stays git-ignored. The issue is the report.
105+
106+
**The issue is pure text — no images, ever.** Screenshots exist only to let you and your
107+
subagents reach a verdict *live*; they are a judgment aid, discarded with the run
108+
environment. The durable report needs the **reproduction rule, not the picture**.
109+
110+
File it with `issue_write` (github MCP):
111+
112+
- **Title**`QA run · <selector> · <framework-sha[:8]> · <date>`
113+
- **Labels**`qa-run` always; add `bug` (and `regression` for a P0/P1) whenever any
114+
clause failed, so a real defect is triageable straight from the run issue without a
115+
second one.
116+
- **Body**, in this order:
117+
- **Env fingerprint** — framework sha, `.objectui-sha`, port, db, seed, timestamp.
118+
- **Scope** — the selector + the `revision` each item ran against.
119+
- **Per-clause verdict table** — item · clause · verdict · one line of **text** oracle
120+
evidence (the API/network/build/test result — server truth, never a pixel).
121+
- **For every `fail`, a reproduction rule** — the exact ordered steps / the API calls
122+
(method · path · body) / the ref-targeted selector path to re-hit it on a fresh boot,
123+
plus expected-vs-actual from the oracle. Enough for a human or a fresh agent to
124+
reproduce it with no screenshot from you.
125+
- Derived item verdicts + any fixture-gap list.
126+
127+
Report the same per-clause table + the env-setup-vs-test time split back to the maintainer
128+
in chat, and link the filed issue.
106129

107130
## Guardrails
108131

109132
- **Don't fake coverage.** Missing fixture → `blocked(fixture)` with the reason; unbuilt
110133
console → build it or record `blocked(environment)`; a half-proven item is `partial`,
111134
not `pass`. A blocked verdict WITH evidence is a successful run; a faked pass is not.
112135
- **Don't run blocked items as if runnable** — the resolver hides them for this reason.
113-
- **One selector, one run record.** For a release sweep, run `since:vN` and `priority:P0`
114-
as separate records rather than smearing them together.
136+
- **One selector, one run, one issue.** For a release sweep, run `since:vN` and
137+
`priority:P0` as separate runs → separate issues, rather than smearing them together.

docs/qa/platform-checklist/README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ acceptance oracle and captured evidence.
1111
Validated by `pnpm check:platform-checklist` (`scripts/check-platform-checklist.mjs`) —
1212
a zero-dependency structural + coverage check. **By maintainer decision it runs on a
1313
periodic MANUAL cadence, not in CI**: run it before a release, after a large platform
14-
surface lands, or alongside a `coverage-sweep` / `checklist-run`. It is a QA ledger, not
14+
surface lands, or alongside a `checklist-author` / `checklist-test`. It is a QA ledger, not
1515
a per-PR code gate, so an unrelated PR is never blocked by checklist drift. Execution
1616
protocol for agents: [RUNNER.md](./RUNNER.md). Run records: [runs/](./runs/README.md).
1717

1818
**Two internal skills drive this ledger** (`.claude/skills/`, never published):
19-
`coverage-sweep` **authors** items (find gaps → write them, per
20-
[SWEEP.md](./SWEEP.md)); `checklist-run` **executes** them (pick items by selector →
19+
`checklist-author` **authors** items (find gaps → write them, per
20+
[SWEEP.md](./SWEEP.md)); `checklist-test` **executes** them (pick items by selector →
2121
drive them → emit a run record, per [RUNNER.md](./RUNNER.md)). The runner resolves what
2222
to test with `scripts/checklist-select.mjs <selector>` — an item id, an `area:`, a
2323
`capability:`, a `priority:`, a `since:vN` release, or a **`file:<path>`** that maps a
@@ -179,7 +179,7 @@ checklist drift. It runs on a **manual / periodic cadence** instead. Run
179179
- **after a large platform surface lands** — a new metadata kind, a new enum, a new area;
180180
- **whenever you touch the checklist** — the structural + coverage check catches a
181181
dangling id or a forgotten `revision` bump in your own edit;
182-
- **alongside a `coverage-sweep`** (find gaps) **or `checklist-run`** (execute items).
182+
- **alongside a `checklist-author`** (find gaps) **or `checklist-test`** (execute items).
183183

184184
The trade-off of staying out of CI: a new capability kind or enum value that lands on
185185
`main` between runs is caught at the **next** manual run, not the moment it merged. The
@@ -206,11 +206,12 @@ ever matters more than PR independence, re-adding the one-line CI step
206206
A release no longer gets a hand-written checklist. The sweep for `vN` is a **filter
207207
over this ledger**: `since == vN` (the new capabilities) ∪ all `P0` (the standing
208208
smoke) ∪ any item whose `source` cites a PR in the release. The tracking issue for the
209-
sweep links here and hosts discussion; results live as a run record kept OUT of the
210-
repo (in the CI artifact / tracking issue / QA store — `runs/` is git-ignored), plus
211-
findings filed as issues, one per failure. Item text, fixtures learned, and new
212-
traps discovered flow **back into the ledger** as revisions — that is the accumulation
213-
the one-off checklists never had.
209+
sweep links here and hosts discussion; results stay OUT of the repo — every run files
210+
one `qa-run` GitHub issue as its record (text only: the verdict table + a reproduction
211+
rule per failure, never screenshots; `runs/` is git-ignored), and a run that finds a real
212+
regression carries the `bug` label so it triages straight from that issue. Item text,
213+
fixtures learned, and new traps discovered flow **back into the ledger** as revisions —
214+
that is the accumulation the one-off checklists never had.
214215

215216
## Relationship to what already exists
216217

docs/qa/platform-checklist/RUNNER.md

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@ test-run output the clause's `evidence` field names.
5050
- check the `traps` field and rule each listed trap out;
5151
- for console UI failures, confirm against current objectui source or a fresh build
5252
— the vendored `/_console` bundle may be stale (skill §2);
53-
- then file the issue and cite it in the run record. A `fail` without a filed issue
54-
is not a completed verdict.
53+
- then capture the **reproduction rule** — ordered steps / API calls (method · path ·
54+
body) / the ref-targeted selector path + expected-vs-actual — into the run's result
55+
issue, which is labeled `bug`. A `fail` with no reproduction rule in its issue is not
56+
a completed verdict. (The screenshot that convinced you is a live judgment aid, not
57+
report content — describe what it showed in one line; never attach it.)
5558
3. **Classify blockers honestly.** Missing seed/persona/fixture → `blocked(fixture)`,
5659
and *record the gap on the item* (`fixtures.knownGaps` or `blocked`) so the next
5760
sweep doesn't rediscover it. A defect in the fixture itself (seed silently failing,
@@ -88,13 +91,20 @@ test-run output the clause's `evidence` field names.
8891
| `wrong-panel` | feature looks missing on a sibling surface | item's `steps` name the exact surface; check it |
8992
| `wrong-persona` | admin privileges mask a guard | run guard checks as the non-privileged persona |
9093

91-
## Run records
94+
## Run records — the GitHub issue is the report
9295

93-
One JSON per executed sweep, written to `runs/YYYY-MM-DD-<slug>.json`. **Results are
94-
NOT committed** — a run record is output about one build, not source; `runs/` is
95-
git-ignored except its README (the format contract). Keep the record and its evidence
96-
in the executing environment (CI artifact, runner workspace, the sweep's tracking
97-
issue, or an external QA store). Shape:
96+
Every completed run — **pass or fail alike** — files **one GitHub issue** as its durable
97+
record, labeled `qa-run` (plus `bug` when any clause failed). **Nothing lands in the
98+
repo** — not the JSON, not screenshots; `runs/` is git-ignored except its README.
99+
100+
**The issue is text only.** Screenshots and DOM dumps are oracles you consult *live* to
101+
reach a verdict — never report artifacts. What the report carries for a defect is the
102+
**reproduction rule**: ordered steps / API calls (method · path · body) / the
103+
ref-targeted selector path + expected-vs-actual from the oracle, enough to re-hit it on a
104+
fresh boot with no picture. A clause whose oracle was a screenshot is recorded as a
105+
one-line text description of what it showed, not a link.
106+
107+
The in-environment JSON scratch (RUNNER shape, never committed):
98108

99109
```jsonc
100110
{
@@ -114,7 +124,7 @@ issue, or an external QA store). Shape:
114124
"revision": 1, // ← the revision this verdict is valid for
115125
"verdict": "pass",
116126
"clauses": [
117-
{ "clause": 0, "verdict": "pass", "evidence": "…what was captured, where" }
127+
{ "clause": 0, "verdict": "pass", "evidence": "text: what the oracle returned — no image links" }
118128
],
119129
"issues": [], // filed failures / fixture gaps
120130
"notes": ""
@@ -123,7 +133,8 @@ issue, or an external QA store). Shape:
123133
}
124134
```
125135

126-
A run summary for humans may additionally go to the sweep's tracking issue or an
127-
external QA store — but none of it lands in the repo. The durable, version-controlled
128-
truth is the checklist under `areas/`; a run is a dated assertion about a build that
129-
belongs wherever that build's other artifacts live.
136+
The issue body is: env fingerprint · scope (selector + per-item `revision`) · the
137+
per-clause verdict table (text oracle evidence) · a reproduction rule per `fail` ·
138+
derived item verdicts + fixture gaps. The durable, version-controlled truth is still the
139+
checklist under `areas/`; a run is a dated assertion about one build, and it lives in its
140+
issue, not the tree.

docs/qa/platform-checklist/runs/README.md

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,25 @@ land in the repo (`.gitignore` here tracks only this README). The durable source
88
the checklist itself under `../areas/`; a run is a snapshot that goes stale the moment
99
the build moves.
1010

11-
**Where results go instead — the canonical home is one tracking issue per release
12-
sweep** (a `[sweep] vN release test sweep` issue, successor to the #3358 model):
11+
**Where results go instead — every completed run files one `qa-run` GitHub issue** as its
12+
durable, **text-only** report (pass or fail alike):
1313

14-
- the issue **body** hosts the human-readable summary — the per-item verdict table
15-
(pass / partial / fail / blocked) and the filter that selected them (`since:vN` ∪ all
16-
`P0` ∪ items whose `source` cites a release PR);
17-
- the machine **run-record JSON(s)** (shape below) attach to that issue — pasted in a
18-
comment or linked as a CI artifact from the sweep job;
19-
- every `fail` becomes its **own linked issue** (RUNNER.md makes a filed issue part of a
20-
completed `fail` verdict), cross-referenced from the sweep issue.
14+
- the issue **body** hosts the per-clause verdict table (pass / partial / fail / blocked)
15+
and the scope — the selector that chose the items + the `revision` each ran against;
16+
- **every `fail` carries a reproduction rule** in that same issue — ordered steps / API
17+
calls (method · path · body) / the ref-targeted selector path + expected-vs-actual —
18+
and the issue gains the `bug` label (a real regression may additionally get its own
19+
linked issue) so it triages straight from the run;
20+
- **screenshots are never part of the report** — they are live judgment aids that die
21+
with the run environment, described in one line of text, never attached or linked.
2122

22-
A raw CI artifact or an external QA store is a fine substitute where one exists, but the
23-
per-release tracking issue is the default so a sweep is never lost. What NEVER lands in
24-
the repo is the record itself — only the durable ledger under `../areas/` accumulates
25-
here, through each item's `revision`/`history`. A verdict is interpretable only next to
26-
the `revision` it names, so the run record stays with its build's artifacts, not in git.
23+
For a release sweep, the per-run issues roll up under the sweep's `[sweep] vN release test
24+
sweep` tracking issue (successor to the #3358 model) so a sweep is never lost. The machine
25+
run-record JSON (shape below) is optional scratch in the executing environment (the
26+
runner's workspace or a CI artifact) and is git-ignored — **do not commit it.** What NEVER
27+
lands in the repo is the record itself; only the durable ledger under `../areas/`
28+
accumulates here, through each item's `revision`/`history`, and a verdict is interpretable
29+
only next to the `revision` it names.
2730

2831
## Record shape (write to `YYYY-MM-DD-<slug>.json`, kept out of git)
2932

@@ -44,7 +47,7 @@ are only meaningful next to the item `revision` they ran against.
4447
"id": "approvals.per-group-signoff",
4548
"revision": 1, // ← the revision this verdict is valid for
4649
"verdict": "pass", // derived: pass | partial | fail | blocked | not-run
47-
"clauses": [ { "clause": 0, "verdict": "pass", "evidence": "…what was captured, where" } ],
50+
"clauses": [ { "clause": 0, "verdict": "pass", "evidence": "text: what the oracle returned — no image links" } ],
4851
"issues": [],
4952
"notes": ""
5053
}

0 commit comments

Comments
 (0)