@qaping/cli 0.1.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,122 @@
1
+ # qaping — CLI commands
2
+
3
+ Everything the `qaping` binary does. Your agent runs most of these for you;
4
+ `setup`, `builds` and `rounds` are the ones you will type yourself.
5
+
6
+ ```
7
+ qaping setup [claude-code|cursor|codex] [--force]
8
+ qaping remove [--client <c>]
9
+ qaping publish-build <game.zip> --platform windows|macos
10
+ qaping builds
11
+ qaping builds rm <slug>
12
+ qaping publish <built-dir>
13
+ qaping wait <ping_id> [--timeout <seconds>]
14
+ qaping results <ping_id> [--json]
15
+ qaping rounds [--json] [--offline] [--file <path>]
16
+ qaping rounds add <ping_id> [--platform windows|macos|ios] [--build <url>]
17
+ [--minutes N] [--deadline-seconds N]
18
+ [--game <slug>] [--checks a,b,c]
19
+ [--note "<patch>"] [--json]
20
+ qaping rounds rm <ping_id> [--json]
21
+ qaping issues <game> [--json] [--status open|fixed|verified|closed]
22
+ qaping whoami
23
+ qaping version
24
+ ```
25
+
26
+ ## Getting in and out
27
+
28
+ ### `qaping setup [claude-code|cursor|codex] [--force]`
29
+
30
+ Registers the qaping MCP server with your coding agent, installs the `qaping`
31
+ skill and its rule, and signs you in (a browser window opens once). With no
32
+ client name it detects what is installed. `--force` rewrites an existing
33
+ entry.
34
+
35
+ ### `qaping remove [--client <c>]`
36
+
37
+ Removes qaping's MCP entry, skill and rule from the client. It touches only
38
+ qaping's own state — nothing else you have installed, and not your login.
39
+
40
+ ### `qaping whoami`
41
+
42
+ Which account this machine is signed in as. Results are scoped to the account
43
+ that filed the round, so check this before deciding a round is gone.
44
+
45
+ ### `qaping version`
46
+
47
+ Prints the installed version.
48
+
49
+ ## Hosting a build
50
+
51
+ ### `qaping publish-build <game.zip> --platform windows|macos`
52
+
53
+ Uploads a zipped native build and prints the `/b/<slug>` URL a round is filed
54
+ against. You hold a small number of hosted builds at a time; the oldest is
55
+ listed first by `qaping builds`.
56
+
57
+ ### `qaping builds` / `qaping builds rm <slug>`
58
+
59
+ Lists the hosted builds you hold, or deletes one now to free its slot.
60
+
61
+ ### `qaping publish <built-dir>`
62
+
63
+ Hosts a browser-playable game's built output and prints the public URL. Web
64
+ rounds are filed with that URL and no platform.
65
+
66
+ ## Rounds
67
+
68
+ ### `qaping wait <ping_id> [--timeout <seconds>]`
69
+
70
+ Waits on a filed round, renewing the lease that keeps it visible to new
71
+ playtesters, and prints the results when they land. The agent normally runs
72
+ this in a background task.
73
+
74
+ ### `qaping results <ping_id> [--json]`
75
+
76
+ One passive fetch, no waiting. Exit code `0` means results are in, `2` means
77
+ still pending, `1` anything else (expired, not yours, unreachable).
78
+
79
+ ### `qaping rounds`
80
+
81
+ The parked rounds this repo is owed, read from `qa-open-rounds.json` at the
82
+ repo root, each with its live status. `--offline` skips the status lookup;
83
+ `--file` points at another ledger.
84
+
85
+ ### `qaping rounds add <ping_id> …`
86
+
87
+ Records a round the agent chose to park — an overnight run, a slow native
88
+ claim — so a later session collects it instead of filing a duplicate. Add
89
+ `--build`, `--minutes`, `--deadline-seconds`, `--game`, `--checks` and
90
+ `--note` so the record explains itself; `--game` is the QA plan's
91
+ `game_slug`, so the session that collects the round knows which issue board
92
+ it moved.
93
+
94
+ ### `qaping rounds rm <ping_id>`
95
+
96
+ Forgets a parked round once it is collected or expired.
97
+
98
+ ## The issue board
99
+
100
+ ### `qaping issues <game> [--json]`
101
+
102
+ Prints the game's issue board: every bug that outlived a round, with its
103
+ status — open, fixed (you claim it is fixed), verified (a playtester
104
+ confirmed it is gone), closed. `--status` prints one status only; `--json`
105
+ prints the machine-readable rows.
106
+
107
+ Read-only, on purpose. Your agent files, claims, closes and reopens issues
108
+ through the `qaping_issues` MCP tool while it runs the loop; this is the
109
+ window you read it through. Nothing on the board costs credits — only rounds
110
+ do — and nothing turns *verified* except a playtester answering "Gone" on a
111
+ round filed after the fix was claimed.
112
+
113
+ ## Files qaping leaves in your repo
114
+
115
+ | file | what it is | commit it? |
116
+ |---|---|---|
117
+ | `QA-PLAN.md` | the checks this game must pass; the agent authors, you own | yes — see [the format](QA-PLAN-FORMAT.md) |
118
+ | `qa-rounds.jsonl` | append-only history, one line per finished round | yes |
119
+ | `qa-open-rounds.json` | rounds filed and not yet collected | no — gitignore it |
120
+
121
+ The issue board is not a file: it lives on the service, one board per game,
122
+ and `qaping issues <game>` reads it. The plan's `game_slug` is what names it.
@@ -11,12 +11,19 @@ YAML at the very top of the file:
11
11
  ```yaml
12
12
  ---
13
13
  game: Solar Drift
14
+ game_slug: solar-drift # the issue board's id — minted ONCE, never renamed
14
15
  build_command: ./scripts/package.sh --release # the ONE command that produces a shippable build
15
16
  platforms: [windows] # windows | macos | ios | web
16
17
  input: XInput gamepad # optional; default keyboard+mouse
17
18
  ---
18
19
  ```
19
20
 
21
+ `game_slug` is minted once from the game name — lowercase, every run of
22
+ non-alphanumerics collapsed to a single `-`, no leading or trailing `-`, ≤64
23
+ characters — and is then permanent, exactly like a check id: it names the
24
+ game's issue board, and renaming it orphans every issue filed under the old
25
+ one. Every playtest round is filed with it as `game`.
26
+
20
27
  `build_command` is recorded once at setup so every future run can build without
21
28
  asking. `platforms: [web]` means a browser-playable game — its "build" is a
22
29
  static directory, not a zip. `input` declares the hardware the
@@ -88,6 +95,26 @@ setup: "?save=campaign-mid"
88
95
  anything missing, corrupted, or visually wrong.
89
96
  ````
90
97
 
98
+ ## Bugs live on the issue board; checks live here
99
+
100
+ A check is what the game must ALWAYS do — it belongs in this file, forever. A
101
+ bug is what the game does wrong right now — it belongs on the game's issue
102
+ board (`qaping issues <game_slug>`, moved by the agent through the
103
+ `qaping_issues` tool), where it is numbered, carried across rounds, and
104
+ retired when it is gone. Do not write bugs into `QA-PLAN.md`: a check written
105
+ to describe one bug ("the shop does not close when you press B twice") ages
106
+ into a puzzle the moment the bug is fixed.
107
+
108
+ The board is what makes a fix provable. The agent may CLAIM a fix (with the
109
+ exact build URL the next round will play); only a playtester answering
110
+ "Gone" on a round filed after that claim turns the issue *verified*, and a
111
+ "Still here" on a claimed fix regresses it. Because every round is filed with
112
+ `game`, the board's open and claimed-fixed issues ride it as the playtester's
113
+ checklist — no step budget spent, no bug forgotten between patches.
114
+
115
+ A check and the bug that came from it stay linked through the issue's
116
+ `check_id`: the same id this file gives the check.
117
+
91
118
  ## The round ledger — qa-rounds.jsonl
92
119
 
93
120
  Beside the plan, at the game repo root, sits `qa-rounds.jsonl`: one JSON line
@@ -96,6 +123,8 @@ appended per round, committed alongside the plan updates —
96
123
  ```json
97
124
  {"round_id": "…", "report_url": "…", "build": "<sha or hosted url>",
98
125
  "evidence_grade": "…", "checks": [{"id": "…", "outcome": "…"}],
126
+ "issues": {"game": "solar-drift", "verified": [3], "regressed": [5],
127
+ "new": [7], "still_open": [2]},
99
128
  "verdict": "…", "credits": 20, "follow_ups": ["…"]}
100
129
  ```
101
130
 
@@ -106,8 +135,30 @@ page (what the results tool returns), never a PR or issue link. There is no
106
135
  evidence-link field, deliberately: signed recording URLs expire in days.
107
136
  The ledger is the machine truth of what was asked and answered, per check,
108
137
  per round; the plan's `last_verified` and `state` are derived from it and
109
- stay the dev-readable contract. Open `follow_ups` are what the next filing
110
- must carry forward.
138
+ stay the dev-readable contract. `issues` is what this round did to the issue
139
+ board, by number (omitted when the round carried no `game`). `follow_ups` is
140
+ NON-BUG follow-ups only — a check to add, a build affordance to write, a
141
+ question to settle; bugs go on the board, where they are numbered and
142
+ re-checked. Open `follow_ups` are what the next filing must carry forward.
143
+
144
+ ## Rounds still open — qa-open-rounds.json
145
+
146
+ A playtest may run for many hours, so a round the agent cannot sit through is
147
+ PARKED: filed with an explicit long deadline, then recorded in
148
+ `qa-open-rounds.json` (same directory) so a LATER session collects it —
149
+
150
+ ```json
151
+ {"rounds": [{"ping_id": "<uuid>", "filed_at": "<ISO>", "platform": "windows",
152
+ "build": "<the hosted or store URL>", "est_minutes": 10,
153
+ "deadline_seconds": 86400, "game": "solar-drift",
154
+ "checks": ["<check ids>"], "note": "<the patch this round covers>"}]}
155
+ ```
156
+
157
+ `qaping rounds` lists it with each round's live status, `qaping rounds add`
158
+ (with `--game` for the board this round carries) records one,
159
+ `qaping rounds rm` drops it once collected. This file is the
160
+ opposite of the ledger and never merges with it: mutable OPEN state, one entry
161
+ per round still owed, emptied as rounds land. It is not history — gitignore it.
111
162
 
112
163
  ## Maintenance rules
113
164
 
package/docs/icon.svg ADDED
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64"><rect x="4" y="4" width="56" height="56" rx="14" fill="#FF7A45"/><path d="M20 33.5l8 8 16-17" fill="none" stroke="#fff" stroke-width="6.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qaping/cli",
3
- "version": "0.1.5",
3
+ "version": "0.3.0",
4
4
  "homepage": "https://qaping.dev",
5
5
  "description": "qaping: automatic QA for your game. Your coding agent authors and maintains the QA plan, ships each patch's build to real human playtesters, and reports what broke.",
6
6
  "keywords": [
@@ -25,7 +25,7 @@
25
25
  "node": "^20.17.0 || ^22.13.0 || >=23.5.0"
26
26
  },
27
27
  "dependencies": {
28
- "pingfusi": "^0.16.0"
28
+ "pingfusi": "^0.17.1"
29
29
  },
30
30
  "publishConfig": {
31
31
  "access": "public"
@@ -0,0 +1,19 @@
1
+ {
2
+ "note": "sha256 of every SKILL.md version this package has shipped (LF-normalized). setup refreshes an installed skill whose hash is listed here — it is ours — and preserves anything else as a local edit. APPEND-ONLY; regenerate with: node scripts/gen-skill-hashes.js [<skill-root>...]",
3
+ "skills": {
4
+ "qaping": [
5
+ "184aa97ba0d529eea36be3c6eb4a5f4c1db8e2a65a0230e03814276a18a92354",
6
+ "217ffcc582e068424eefbb69376825ac71433fa92f34e3546bd02d8521ef008c",
7
+ "2fe5cafeef48146d8c9cc263ae1aaef764720027d17c0af3ab879e6853cf4a26",
8
+ "38cdc3289db6a544bc0cc828f4981a3f4ed6b39036ce81eebbaf4cbe9c47a5d0",
9
+ "490ff02895fdc6a2eb3a0b671628a8d4eee3efd906782eb45d99eac40bf59846",
10
+ "5462b858f58d183a020a5b2fa214dd1da6856e71a238316641f13d70eb0f0df4",
11
+ "5d0751c023af0a1cf69f152ba587b10c34087c7d5299f2d4b0e782f1ad0d66b0",
12
+ "6d0a5a1b430a8a0fd1c7c06b726de657e7fe82ac37ce69c9446539065d2ce751",
13
+ "71e64cd2b58996236c7fd3375a324ca2ae7b3e4028f7b358a389c562464c8bf3",
14
+ "8d817af568154734cd893122ce2e40ef2cd20cb725abbf318f134318157e5b6c",
15
+ "966bd642f1ee052691c7974a186e9f8f50644bce0ea010b6f0b444931879dbad",
16
+ "b9d08318e69290759bf31e149d64207b9d186faac9ccd01bc1db3ffcff29506c"
17
+ ]
18
+ }
19
+ }