@witchpot/gmc 0.5.0 → 0.8.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.
- package/CHANGELOG.md +70 -0
- package/README.md +3 -0
- package/package.json +2 -2
- package/skill/gmc-analysis/CHANGELOG.md +190 -0
- package/skill/gmc-analysis/SKILL.md +401 -7
- package/skill/gmc-analysis/references/quota.md +4 -2
- package/skill/gmc-analysis.manifest.json +2 -2
- package/src/args.js +42 -4
- package/src/constants.js +20 -3
- package/src/help.js +208 -1
- package/src/index.js +1 -0
- package/src/requests.js +399 -2
- package/src/requests.test.js +870 -0
- package/src/workflows.js +15 -1
- package/src/workflows.test.js +156 -0
package/src/help.js
CHANGED
|
@@ -29,8 +29,11 @@ Usage:
|
|
|
29
29
|
gmc tags --q <term> --limit <number> --json
|
|
30
30
|
gmc lists --json
|
|
31
31
|
gmc lists create --name <name> --kind manual --json
|
|
32
|
-
gmc lists
|
|
32
|
+
gmc lists create --name <name> --kind filter --filter '<json>' --json
|
|
33
|
+
gmc lists games <id> --limit <number> --cursor <cursor> --json
|
|
33
34
|
gmc lists add <id> --app-ids <appid[,appid...]> --json
|
|
35
|
+
gmc lists resolve <id> --json
|
|
36
|
+
gmc lists materialize <id> --confirm --json
|
|
34
37
|
gmc games search --source steam --query <text> --json
|
|
35
38
|
gmc games count --source steam --release-year <year> --reviews-gt <number> --json
|
|
36
39
|
gmc games aggregate --source steam --metric count,median_reviews --group-by release_year --json
|
|
@@ -44,6 +47,10 @@ Usage:
|
|
|
44
47
|
gmc campaigns signals --source steam <externalId> --json
|
|
45
48
|
gmc games compare --source steam <externalId> <externalId...> --focus market --json
|
|
46
49
|
gmc games topics --source steam <externalId> --json
|
|
50
|
+
gmc games language-topics --source steam <externalId> --json
|
|
51
|
+
gmc games language-topics --source steam <externalId> --min-reviews <number> --include-insufficient --json
|
|
52
|
+
gmc games review-history --source steam <externalId> --json
|
|
53
|
+
gmc games more-like-this --source steam <externalId> --country <country> --json
|
|
47
54
|
gmc reviews patterns --source steam --tags <tag_slug[,tag_slug...]> --reviews-min <number> --json
|
|
48
55
|
gmc reviews patterns --source steam --tags <tag_slug[,tag_slug...]> --sample-size <number> --preset summary --json
|
|
49
56
|
gmc marketing patterns --source steam --tags <tag_slug[,tag_slug...]> --reviews-min <number> --json
|
|
@@ -56,7 +63,12 @@ Usage:
|
|
|
56
63
|
gmc cohort brief --source steam --list <id> --json
|
|
57
64
|
gmc showcases search --query <text> --json
|
|
58
65
|
gmc showcases fit --source steam <externalId> --deadline-before <YYYY-MM-DD> --json
|
|
66
|
+
gmc showcases history --source steam <externalId> --json
|
|
59
67
|
gmc showcases patterns --source steam --tags <tag_slug[,tag_slug...]> --json
|
|
68
|
+
gmc steam trend-stories --locale en --json
|
|
69
|
+
gmc steam tag-trends --view featured --json
|
|
70
|
+
gmc steam tag-trends --view table --sort release_share_delta --order desc --json
|
|
71
|
+
gmc steam tag-trends --view tag --tag <tag_slug> --json
|
|
60
72
|
|
|
61
73
|
Tag taxonomy:
|
|
62
74
|
gmc tags --json List the full tag dictionary (slug, name).
|
|
@@ -71,11 +83,168 @@ Tag taxonomy:
|
|
|
71
83
|
<term> first to resolve a genre or keyword to valid slugs before
|
|
72
84
|
building a --tags filter.
|
|
73
85
|
|
|
86
|
+
Review topics by review language:
|
|
87
|
+
gmc games language-topics --source steam <externalId> --json
|
|
88
|
+
One game's review topics broken down by
|
|
89
|
+
the language each review was written in.
|
|
90
|
+
--min-reviews <number> Evidence floor applied to the distinct
|
|
91
|
+
review count behind a row, 10-200
|
|
92
|
+
(server default 30).
|
|
93
|
+
--include-insufficient Also return rows below that floor, capped
|
|
94
|
+
by the server, with coverage reporting
|
|
95
|
+
the cut.
|
|
96
|
+
|
|
97
|
+
Read data.evidenceState first. ready means at least one topic x language row
|
|
98
|
+
cleared the floor; insufficient_evidence means rows exist but none cleared
|
|
99
|
+
it; not_analyzed means no rows exist. The last two are thin evidence and no
|
|
100
|
+
data — never report either as zero mentions or absent sentiment.
|
|
101
|
+
|
|
102
|
+
Coverage is the analyzed subset only (about 2,500 titles today), selected
|
|
103
|
+
for review analysis rather than sampled from the catalog. It is not a
|
|
104
|
+
full-catalog population measurement, so do not extrapolate a share of Steam
|
|
105
|
+
from it.
|
|
106
|
+
|
|
107
|
+
Review language is the language a review was written in. It is not a
|
|
108
|
+
country, a region, a market, or a culture, and must not be reported as one.
|
|
109
|
+
|
|
110
|
+
data.rows[].counts and .rates are observed; data.rows[].estimates are
|
|
111
|
+
sample-expanded and carry samplingWeightMethod. Keep the two apart, and date
|
|
112
|
+
every claim with data.snapshot (periodStart/periodEnd/analysisVersion/
|
|
113
|
+
generatedAt).
|
|
114
|
+
|
|
115
|
+
Examples:
|
|
116
|
+
gmc games language-topics --source steam 730 --json
|
|
117
|
+
gmc games language-topics --source steam 730 --min-reviews 50 --json
|
|
118
|
+
gmc games language-topics --source steam 730 --include-insufficient --json
|
|
119
|
+
|
|
120
|
+
Review-count history:
|
|
121
|
+
gmc games review-history --source steam <externalId> --json
|
|
122
|
+
One game's full daily total-review
|
|
123
|
+
series, plus the collected lifecycle and
|
|
124
|
+
announcement events and the observed
|
|
125
|
+
major-discount windows beside it.
|
|
126
|
+
|
|
127
|
+
There are no parameters beyond the external id. The whole series is always
|
|
128
|
+
returned; window it yourself and state the window you chose. A --range,
|
|
129
|
+
--from, --to, --limit or --locale is rejected as a usage error rather than
|
|
130
|
+
ignored, so a narrowing you asked for can never be silently dropped.
|
|
131
|
+
|
|
132
|
+
data.series is published-run-only and contamination-filtered: an observation
|
|
133
|
+
more than 2% below the highest earlier one for the same game is withheld as
|
|
134
|
+
invalid. Differences taken from it are safe to report, but the newest point
|
|
135
|
+
can lag the game's headline review count until that day's run is published.
|
|
136
|
+
Collection can have real gaps, so scale by date and never by array index.
|
|
137
|
+
|
|
138
|
+
Empty data.events or data.discountWindows mean no events were COLLECTED for
|
|
139
|
+
those sources — never that no releases, announcements, or discounts
|
|
140
|
+
happened. Announcements come from official Steam feeds, capped at the most
|
|
141
|
+
recent 1000 items, and are clustered to one event per UTC day.
|
|
142
|
+
|
|
143
|
+
A discount window is an observed state at the >=20% collection threshold,
|
|
144
|
+
not an exact Steam sale period. endDate is EXCLUSIVE (the first observation
|
|
145
|
+
back below the threshold), a null endDate means no end observed yet, and
|
|
146
|
+
discountPercent is the opening observation.
|
|
147
|
+
|
|
148
|
+
Events support temporal comparison only. A review-count movement beside an
|
|
149
|
+
event is co-occurrence, never attribution.
|
|
150
|
+
|
|
151
|
+
Examples:
|
|
152
|
+
gmc games review-history --source steam 730 --json
|
|
153
|
+
|
|
154
|
+
Steam tag trends:
|
|
155
|
+
gmc steam tag-trends --view <view> --json
|
|
156
|
+
Tag supply trends over one frozen monthly
|
|
157
|
+
generation: how the share of new paid
|
|
158
|
+
Steam releases carrying each tag moved
|
|
159
|
+
between two three-month periods.
|
|
160
|
+
--view <view> featured | board | group | table | tag.
|
|
161
|
+
Defaults to featured.
|
|
162
|
+
--family <family> Taxonomy family filter (board/group/table).
|
|
163
|
+
--q <term> Substring over tag slug and name
|
|
164
|
+
(board/group/table).
|
|
165
|
+
--supply-direction <direction> up | down | unresolved | insufficient
|
|
166
|
+
(board/group/table).
|
|
167
|
+
--sort <key> release_share_delta | current_share |
|
|
168
|
+
known_members | median_reviews | slug
|
|
169
|
+
(table only).
|
|
170
|
+
--order <asc|desc> Table sort direction (table only).
|
|
171
|
+
--limit <number> group 1-50, table 1-100.
|
|
172
|
+
--cursor <cursor> Continuation token (group/table).
|
|
173
|
+
--tag <tag_slug> Required for --view tag.
|
|
174
|
+
|
|
175
|
+
Parameters are allowlisted per view and fail closed. Passing one the view
|
|
176
|
+
does not accept is a 400 naming it, not a filter that is quietly ignored, so
|
|
177
|
+
a narrowing you asked for can never be dropped while the answer looks right.
|
|
178
|
+
|
|
179
|
+
Read data.status and data.readiness before quoting anything. status "stale"
|
|
180
|
+
means no newer generation published: the payload keeps its ORIGINAL asOf and
|
|
181
|
+
the values that were truthful then, so date every claim by data.asOf rather
|
|
182
|
+
than by when you ran the command. readiness "limited" is a successful
|
|
183
|
+
partial-data answer, not an error.
|
|
184
|
+
|
|
185
|
+
Report release share as the [lower, upper] interval. The width is UNMEASURED
|
|
186
|
+
titles, not noise: unknownTagMembers are titles with no complete tag
|
|
187
|
+
observation and are never titles known to lack the tag. A
|
|
188
|
+
releaseShareDifferenceRange containing 0 means the data cannot separate the
|
|
189
|
+
two periods.
|
|
190
|
+
|
|
191
|
+
All four directions are measurements. "unresolved" means the difference
|
|
192
|
+
interval spans zero and "insufficient" means the tag is below the evidence
|
|
193
|
+
floor — neither is missing data and neither is "no change".
|
|
194
|
+
|
|
195
|
+
Every observed* field is computed over current.observedReviewMembers titles,
|
|
196
|
+
not over the whole cohort; quote that denominator. item.titles is a bounded
|
|
197
|
+
display sample, not the tag's membership (use current.knownMembers).
|
|
198
|
+
|
|
199
|
+
Before the first generation publishes, the endpoint answers 404
|
|
200
|
+
TAG_TRENDS_UNAVAILABLE. That is the documented pre-publication state, not an
|
|
201
|
+
outage and not worth retrying on a schedule.
|
|
202
|
+
|
|
203
|
+
Examples:
|
|
204
|
+
gmc steam tag-trends --view featured --json
|
|
205
|
+
gmc steam tag-trends --view board --family mechanic --q cozy --json
|
|
206
|
+
gmc steam tag-trends --view table --sort current_share --limit 50 --json
|
|
207
|
+
gmc steam tag-trends --view tag --tag cozy --json
|
|
208
|
+
|
|
74
209
|
Binary aliases:
|
|
75
210
|
gmcp and game-market-copilot run the same CLI. Use them when a shell
|
|
76
211
|
alias shadows gmc (Oh My Zsh's git plugin defines gmc as
|
|
77
212
|
'git merge --continue').
|
|
78
213
|
|
|
214
|
+
Query-backed lists (--kind filter):
|
|
215
|
+
|
|
216
|
+
--filter takes the games API's camelCase filter object, e.g.
|
|
217
|
+
--filter '{"tags":["cozy"],"reviewsMin":500}'
|
|
218
|
+
|
|
219
|
+
It also accepts the version 2 query envelope, which pairs structured
|
|
220
|
+
conditions with an optional natural-language one:
|
|
221
|
+
|
|
222
|
+
{"version":2,"mode":"query",
|
|
223
|
+
"structured":{"tags":["cozy"],"reviewsMin":500},
|
|
224
|
+
"semanticQuery":"games about running a shop",
|
|
225
|
+
"semanticMode":"rank"}
|
|
226
|
+
|
|
227
|
+
structured decides membership. semanticQuery only orders results inside
|
|
228
|
+
that universe under semanticMode "rank" (the default); under "narrow" it
|
|
229
|
+
also narrows membership, and the reported total is then approximate or a
|
|
230
|
+
floor rather than an exact count. Read total_kind in the response before
|
|
231
|
+
quoting any number as exact.
|
|
232
|
+
|
|
233
|
+
A list with a semanticQuery needs a resolution before its games can be
|
|
234
|
+
read: "gmc lists games <id>" answers 409 RESOLUTION_REQUIRED until you run
|
|
235
|
+
"gmc lists resolve <id>". Resolve costs 2 credits every time, including
|
|
236
|
+
when an existing resolution is reused, and it never changes membership.
|
|
237
|
+
|
|
238
|
+
"gmc lists materialize <id> --confirm" FREEZES the list's current members.
|
|
239
|
+
After it the list no longer follows its definition, and the only way back
|
|
240
|
+
is to discard the frozen rows. It costs 2 credits, requires --confirm, and
|
|
241
|
+
takes an optional --expected-revision <n> compare-and-swap so a definition
|
|
242
|
+
edit landing after your resolve fails the call instead of freezing the
|
|
243
|
+
wrong query. A definition using catalogAsOf cannot be frozen at all --
|
|
244
|
+
400 SNAPSHOT_DEFINITION_UNSUPPORTED, nothing written, and retrying will
|
|
245
|
+
never succeed: a snapshot is a fixed set of games, while that predicate is
|
|
246
|
+
re-evaluated against a growing availability history. Read the list live.
|
|
247
|
+
|
|
79
248
|
Supported commands:
|
|
80
249
|
${SUPPORTED_BETA_COMMANDS.map((command) => ` ${command}`).join("\n")}
|
|
81
250
|
|
|
@@ -113,6 +282,35 @@ Filters:
|
|
|
113
282
|
--coverage <list> Research coverage levels: basic, partial, full.
|
|
114
283
|
Use --coverage full,partial to keep only games
|
|
115
284
|
with collected analysis data.
|
|
285
|
+
--has-demo <true|false> Filter on whether the app has a linked demo in
|
|
286
|
+
app_demo_map. false means no demo linkage was
|
|
287
|
+
observed in collected appdetails, not confirmed
|
|
288
|
+
absence.
|
|
289
|
+
--event-name <slug> Restrict to the current participants of one
|
|
290
|
+
Steam event (a steam_events.event_name slug).
|
|
291
|
+
Membership is resolved at query time, so the
|
|
292
|
+
cohort follows collection updates. Unknown slugs
|
|
293
|
+
return INVALID_EVENT with suggestions; list
|
|
294
|
+
valid slugs at GET /api/v1/events.
|
|
295
|
+
--catalog-as-of <date> YYYY-MM-DD. Keep only titles Game Market Copilot
|
|
296
|
+
had NOT observed as delisted on that date. Not a
|
|
297
|
+
snapshot dial: --as-of picks which metrics are
|
|
298
|
+
read, this picks which titles exist, and the two
|
|
299
|
+
combine. Incomplete on purpose -- a title with no
|
|
300
|
+
availability observation by that date is KEPT, so
|
|
301
|
+
a real-data result carries the warning
|
|
302
|
+
catalog_as_of_observation_bounded (plus
|
|
303
|
+
catalog_as_of_predates_coverage when the date is
|
|
304
|
+
older than the observation window) and is not a
|
|
305
|
+
complete historical catalog. A static-fixture
|
|
306
|
+
result carries catalog_as_of_filter_unavailable
|
|
307
|
+
instead: there is no availability history behind
|
|
308
|
+
fixtures, so the filter was not applied at all.
|
|
309
|
+
--ai-disclosure <value> disclosed, absent, or unconfirmed. absent means
|
|
310
|
+
no AI-use disclosure was observed in collected
|
|
311
|
+
data -- not confirmed non-use. unconfirmed means
|
|
312
|
+
Game Market Copilot has not yet successfully
|
|
313
|
+
observed a disclosure state either way.
|
|
116
314
|
|
|
117
315
|
Sorting:
|
|
118
316
|
--sort <key> reviews_desc, reviews_asc, rating_desc,
|
|
@@ -134,11 +332,20 @@ Count and aggregation:
|
|
|
134
332
|
Use gmc games count when you only need the number of matching games.
|
|
135
333
|
Use gmc games aggregate for grouped metrics such as count by year,
|
|
136
334
|
median reviews by year, or count by an explicit price/review/rating bucket.
|
|
335
|
+
Add --as-of to read a past published snapshot, and --compare-as-of to get a
|
|
336
|
+
per-app-paired comparison between two dates in data.comparison. Report the
|
|
337
|
+
comparison's exclusions, paired_beyond_lookback and insufficient_coverage
|
|
338
|
+
rather than inferring a trend from them. --compare-as-of does not support
|
|
339
|
+
--group-by tag, primary_market_tag, or ai_disclosure, nor the
|
|
340
|
+
--ai-disclosure filter. It DOES combine with --event-name and
|
|
341
|
+
--catalog-as-of: the comparison cohort applies the same Steam event
|
|
342
|
+
participation and catalog-availability predicates as the rows beside it.
|
|
137
343
|
|
|
138
344
|
Examples:
|
|
139
345
|
gmc games search --source steam --release-year 2025 --reviews-min 1000 --json
|
|
140
346
|
gmc games count --source steam --release-year 2025 --reviews-gt 1000 --json
|
|
141
347
|
gmc games aggregate --source steam --metric count,median_reviews --group-by release_year --reviews-gt 1000 --json
|
|
142
348
|
gmc games aggregate --source steam --metric count --group-by price_bucket --bucket price:0,5,10,20,40 --json
|
|
349
|
+
gmc games aggregate --source steam --metric count --group-by release_year --as-of 2026-08-01 --compare-as-of 2026-06-01 --json
|
|
143
350
|
`);
|
|
144
351
|
}
|