@overcrow/mcp 0.1.0 → 0.1.2

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.
Files changed (53) hide show
  1. package/README.md +1 -1
  2. package/dist/bootstrap/pin.json +43 -43
  3. package/dist/content/docs/en/cli.md +446 -31
  4. package/dist/content/docs/en/creator-space.md +78 -0
  5. package/dist/content/docs/en/guide.md +3 -4
  6. package/dist/content/docs/en/manifest.md +13 -6
  7. package/dist/content/docs/en/mcp.md +1 -1
  8. package/dist/content/docs/en/publish-a-widget.md +94 -0
  9. package/dist/content/docs/en/publish-keys.md +95 -0
  10. package/dist/content/docs/en/publishing.md +5 -0
  11. package/dist/content/docs/en/testing.md +3 -3
  12. package/dist/content/docs/en/verified-domain.md +46 -0
  13. package/dist/content/docs/en/widget-listing.md +65 -0
  14. package/dist/content/docs/en/widget-review.md +57 -0
  15. package/dist/content/docs/en/widget-statistics.md +134 -0
  16. package/dist/content/docs/fr/cli.md +467 -32
  17. package/dist/content/docs/fr/creator-space.md +83 -0
  18. package/dist/content/docs/fr/guide.md +3 -4
  19. package/dist/content/docs/fr/manifest.md +15 -6
  20. package/dist/content/docs/fr/mcp.md +1 -1
  21. package/dist/content/docs/fr/publish-a-widget.md +101 -0
  22. package/dist/content/docs/fr/publish-keys.md +97 -0
  23. package/dist/content/docs/fr/publishing.md +5 -0
  24. package/dist/content/docs/fr/testing.md +3 -3
  25. package/dist/content/docs/fr/verified-domain.md +49 -0
  26. package/dist/content/docs/fr/widget-listing.md +69 -0
  27. package/dist/content/docs/fr/widget-review.md +59 -0
  28. package/dist/content/docs/fr/widget-statistics.md +141 -0
  29. package/dist/content/examples/countdown/manifest.json +1 -1
  30. package/dist/content/examples/fps/submission.json +8 -0
  31. package/dist/content/examples/media/submission.json +12 -0
  32. package/dist/content/examples/notes/submission.json +12 -0
  33. package/dist/content/examples/performance/submission.json +12 -0
  34. package/dist/content/examples/playervox-journal/submission.json +12 -0
  35. package/dist/content/examples/playervox-rating/submission.json +12 -0
  36. package/dist/content/examples/playervox-reviews/submission.json +8 -0
  37. package/dist/content/examples/playervox-score/submission.json +8 -0
  38. package/dist/content/examples/session/submission.json +8 -0
  39. package/dist/content/examples/stopwatch/submission.json +12 -0
  40. package/dist/content/examples/twitch-chat/submission.json +12 -0
  41. package/dist/content/examples/warframe-market/submission.json +24 -0
  42. package/dist/content/examples/weather/manifest.json +1 -1
  43. package/dist/content/examples/weather/submission.json +17 -0
  44. package/dist/content/index.json +106 -2
  45. package/dist/content/reference/errors.json +224 -12
  46. package/dist/content/reference/manifest.md +1 -1
  47. package/dist/hidden.js +47 -0
  48. package/dist/texts.js +1 -1
  49. package/dist/tools/project.js +5 -0
  50. package/dist/tools/submission.js +1 -1
  51. package/dist/version.js +1 -1
  52. package/npm-shrinkwrap.json +2 -2
  53. package/package.json +1 -1
@@ -7,11 +7,11 @@ OverCrow runs when it installs and starts a widget: a package it accepts is
7
7
  a package OverCrow reads.
8
8
 
9
9
  ```sh
10
- overcrow-widget init my-widget --template counter
10
+ overcrow-widget init my-widget --template counter --id nova.my-widget
11
11
  cd my-widget
12
12
  overcrow-widget check
13
13
  overcrow-widget package
14
- overcrow-widget inspect dist/com.example.my-widget-0.1.0.ocpkg
14
+ overcrow-widget inspect dist/nova.my-widget-0.1.0.ocpkg
15
15
  overcrow-widget doctor
16
16
  overcrow-widget dev
17
17
  overcrow-widget test
@@ -26,10 +26,14 @@ overcrow-widget test
26
26
  | [`dev`](#dev) | Runs the widget in OverCrow and reloads it when you save. |
27
27
  | [`test`](#test) | Plays the project's test scenarios and compares their images. |
28
28
  | [`doctor`](#doctor) | Says what your setup has and lacks. |
29
- | [`admit`](#admit) | Runs the admission of the marketplace on your submission. |
29
+ | [`admit`](#admit) | Runs the admission of the creator space on your sources, a folder or a ZIP. |
30
+ | [`diff`](#diff) | Compares two versions of a widget's sources. |
31
+ | [`submit`](#submit) | Sends a version to the creator space with a publish key, and follows its checks. |
32
+ | [`status`](#status) | Shows the versions of a widget, their checks and their review. |
30
33
 
31
34
  Every command takes the project directory as its argument and uses the
32
- current directory without one.
35
+ current directory without one. [Machine-readable output](#machine-readable-output)
36
+ and [exit status](#exit-status) are stable for scripts.
33
37
 
34
38
  ## Installing
35
39
 
@@ -96,15 +100,15 @@ Keep the version the tool embeds (`overcrow-widget --version`).
96
100
  | `logic.ts` or `logic.js` | [The logic](logic.md), one module; bundled with the SDK into `logic.js`. | bundled |
97
101
  | `locales/en.json`, `locales/fr.json` | [Messages](logic.md#messages); both or neither, with the same keys. | yes |
98
102
  | `LICENSE` | The license text of the package. The templates start with MIT; choose your own. | yes |
99
- | `assets/` | PNG, JPEG or WebP images; optional. | yes |
103
+ | `assets/` | PNG, JPEG or WebP images; optional. Hidden files (`.DS_Store`) and what the creator tools never send (`dist/`…) are skipped, as in [source archives](#source-archives). | yes |
100
104
  | `package.json`, `tsconfig.json` | Tooling only: TypeScript and the SDK types. | no |
101
- | `listing.json` | The marketplace text of a [submission](publishing.md#the-listing); read by `admit`. | no |
105
+ | `listing.json` | The marketplace text of a [submission](publishing.md#the-listing); read by `admit`. In the creator space, where the listing is edited, only a proposal to import. | no |
102
106
  | `tests/` | [Scenarios](testing.md#scenarios) (`tests/<name>.scenario.json`), their reference images (`tests/reference/`) and your unit tests. `tests/output/` holds the images of failed runs. | no |
103
107
 
104
108
  ## init
105
109
 
106
110
  ```sh
107
- overcrow-widget init my-widget --template list --id com.example.my-widget --name "My widget"
111
+ overcrow-widget init my-widget --template list --id nova.my-widget --name "My widget"
108
112
  ```
109
113
 
110
114
  Writes a new project into the directory, which must not exist or must be
@@ -117,8 +121,12 @@ empty: `init` never overwrites a file.
117
121
  | `list` | A keyed checklist: `for`, handlers with arguments, `t()` with parameters. |
118
122
  | `chart` | A live chart updated by a timer. |
119
123
 
120
- The ID defaults to `com.example.<dir>`; pass `--id` with a reverse-DNS ID
121
- under a domain you control (`com.playervox.*` is reserved). Every template
124
+ Pass `--id` with your widget's ID: `<handle>.<name>`, your publisher handle
125
+ in the OverCrow creator space and a name (`nova.lol-timers`), or a reverse
126
+ domain you verified and a name (`gg.nova.lol-timers`); see
127
+ [the manifest](manifest.md#identity-and-version). Without `--id`, the ID is
128
+ `yourhandle.<dir>`: replace `yourhandle` before you submit, as `admit`
129
+ refuses it. `com.playervox.*` is reserved. Every template
122
130
  comes with a test scenario, `tests/example.scenario.json`, and `counter`,
123
131
  `list` and `chart` with its reference images.
124
132
 
@@ -158,6 +166,10 @@ overcrow-widget package --out build/my-widget.ocpkg
158
166
  Runs `check`, then writes the package to `dist/<id>-<version>.ocpkg`, or to
159
167
  `--out`. It prints the path, the size and the SHA-256 of the archive.
160
168
 
169
+ With `--source-map FILE`, it also writes [the code map](#the-code-map) of
170
+ `logic.js` to that file. The map never goes into the package: the package
171
+ is the same with or without it.
172
+
161
173
  Packaging is deterministic: the same sources and the same version of the
162
174
  tool give the same bytes on every run and every system. What the package
163
175
  holds is described in [the package](package.md).
@@ -165,7 +177,7 @@ holds is described in [the package](package.md).
165
177
  ## inspect
166
178
 
167
179
  ```sh
168
- overcrow-widget inspect dist/com.example.my-widget-0.1.0.ocpkg
180
+ overcrow-widget inspect dist/nova.my-widget-0.1.0.ocpkg
169
181
  ```
170
182
 
171
183
  Validates a package as OverCrow does, then shows it as a reviewer sees it:
@@ -270,37 +282,361 @@ Options: `--format json`, `--deny-warnings`.
270
282
  ## admit
271
283
 
272
284
  ```sh
273
- overcrow-widget admit
274
- overcrow-widget admit --package dist/com.example.my-widget-0.1.0.ocpkg
285
+ overcrow-widget admit --publisher nova
286
+ overcrow-widget admit lol-timers.zip --publisher nova --previous lol-timers-1.0.0.ocpkg
287
+ overcrow-widget admit --publisher nova --package dist/nova.my-widget-0.1.0.ocpkg
275
288
  ```
276
289
 
277
- Runs the static admission that a marketplace submission goes through,
278
- exactly as the marketplace runs it. It never runs your code or `tsc`:
290
+ Runs the static admission that the creator space runs on every version you
291
+ send. The sources are the project folder or a ZIP of it, read as the
292
+ creator space receives them ([source archives](#source-archives)). It
293
+ never runs your code or `tsc`:
279
294
 
280
- 1. the directory is built as `package` builds it;
295
+ 1. the sources are built as `package` builds them;
281
296
  2. with `--package`, that archive's compiled view must be byte for byte
282
297
  what `view.ocml` compiles to;
283
- 3. the ID is not reserved, `listing.json` is valid, its preview is a
284
- packaged PNG of at most 256 KiB;
298
+ 3. the ID belongs to the publisher given by `--publisher` (its
299
+ `<handle>.<name>` IDs, and with `--domain`, the IDs under a domain it
300
+ verified); without `--publisher`, it is neither reserved, nor an example
301
+ ID (`nova.*`, `yourhandle.*`, `gg.nova.*`, `com.example.*`…), nor under a
302
+ handle nobody can register (`admin.*`, `com.*`). `listing.json` is
303
+ valid, its preview is a packaged PNG of at most 256 KiB;
285
304
  4. the authority the widget asks for is listed for the reviewer:
286
305
  capabilities (the sensitive ones marked), network routes with their
287
- response bound, clipboard writes, storage and game events.
306
+ response bound, clipboard writes, storage and game events;
307
+ 5. with `--previous`, the last approved version (its `manifest.json`, its
308
+ package, its folder or its ZIP): the ID must be the same and the version
309
+ higher, and the report lists the
310
+ [permission keys](#permission-keys) added, widened and removed, and the
311
+ review the version needs.
288
312
 
289
313
  | Code | Severity | Meaning |
290
314
  | --- | --- | --- |
291
- | `admission.reserved_id` | error | A `com.playervox.*` ID, reserved for PlayerVox. |
292
- | `admission.listing_missing`, `admission.listing` | error | No `listing.json`, or one that breaks the listing's rules. |
293
- | `admission.preview` | error | `preview` does not name a packaged PNG within bounds. |
294
- | `admission.license` | error | A PlayerVox widget whose license is not MIT. |
315
+ | `admission.reserved_id` | error | A `com.playervox.*` ID, reserved for PlayerVox; without `--publisher`, also an ID under a reserved handle (`playervox.*`, `admin.*`…). |
316
+ | `admission.placeholder_id` | error | An example ID, without `--publisher`. |
317
+ | `admission.id_not_owned` | error | The ID does not belong to the publisher, or, without `--publisher`, cannot belong to any. |
318
+ | `admission.listing_missing`, `admission.listing` | error | No `listing.json`, or one that breaks the listing's rules (a warning with `--listing optional`). |
319
+ | `admission.preview` | error | `preview` does not name a packaged PNG within bounds (a warning with `--listing optional`). |
320
+ | `admission.license` | error | A PlayerVox widget whose license is not MIT (a warning with `--listing optional`). |
295
321
  | `admission.view_not_reproducible` | error | The submitted compiled view differs from what `view.ocml` compiles to. |
322
+ | `admission.previous` | error | The previous version cannot be read. |
323
+ | `admission.previous_mismatch` | error | The previous version is another widget. |
324
+ | `admission.version_not_newer` | error | The version is not above the previous one. |
296
325
  | `admission.package_rebuilt` | warning | The submitted archive differs from the rebuild in other files. |
297
326
  | `admission.not_rebuilt` | warning | An archive was admitted without its sources. |
298
327
 
299
- Options: `--package FILE`, `--out DIR` (writes the admitted package, its
300
- listing and a report into an empty directory), `--format json`,
301
- `--deny-warnings`. `admit <file.ocpkg> --listing FILE` checks an archive
302
- without its sources. Exit status: 0 admitted, 1 refused, 2 on a usage or
303
- file error. See [publishing and review](publishing.md).
328
+ Options: `--publisher HANDLE`, `--domain DOMAIN` (repeatable), `--previous
329
+ FILE`, `--package FILE`, `--source-map FILE` ([the code map](#the-code-map),
330
+ written when the sources are admitted), `--out DIR` (writes the admitted
331
+ package, its listing and a report into an empty directory), `--format
332
+ json`, `--deny-warnings`. `admit <file.ocpkg> --listing FILE` checks an
333
+ archive without its sources.
334
+
335
+ `--listing required|optional` is for sources. `required`, the default,
336
+ refuses sources without a valid `listing.json`. `optional` is the creator
337
+ space's way: the listing is edited there, so `listing.json` may be absent,
338
+ and one with a problem is left out (no listing in the report or in
339
+ `--out`) with warnings instead of refusing the sources. Exit status: 0 admitted, 1 refused, 2 on a
340
+ usage or file error. See [publishing and review](publishing.md).
341
+
342
+ ### Permission keys
343
+
344
+ Each permission has a stable key, the same in the creator space:
345
+
346
+ | Key | Permission |
347
+ | --- | --- |
348
+ | `network:GET https://api.nova.gg/v1/timers` | A network route: method, origin and path. |
349
+ | `storage` | Storage. |
350
+ | `clipboardWrite` | Clipboard writes. |
351
+ | `capability:<name>` | A capability. |
352
+ | `gameEvent:<name>` | A game event. |
353
+
354
+ A key is *added* when the previous version did not have it, *widened* when
355
+ its route stays but its rule changes (path or query constraints, response
356
+ bound), and *removed* when it goes. An added or widened key calls for a
357
+ **full** review; otherwise the review is **quick**.
358
+
359
+ ## diff
360
+
361
+ ```sh
362
+ overcrow-widget diff lol-timers-1.0.0.zip .
363
+ overcrow-widget diff old/ new/ --format json
364
+ ```
365
+
366
+ Shows what changed between two versions of a widget's sources, each a
367
+ folder or a ZIP, read as `admit` reads them: the files the creator space
368
+ receives. Files are sorted by path; each added, modified or removed file
369
+ comes with its unified changes (three lines of context) and its added and
370
+ removed line counts. A file that is not UTF-8 text is binary: only its
371
+ SHA-256 is compared. So is a text above 1 MiB or 20,000 lines, or once
372
+ 200,000 lines were compared in one diff (`tooLarge`). When both versions have a valid manifest, the
373
+ [permission keys](#permission-keys) the new version adds, widens and
374
+ removes are listed, with the review it needs.
375
+
376
+ Option: `--format json`. Exit status: 0 when both versions were read,
377
+ whether or not they differ; 1 when one is refused; 2 on a usage or file
378
+ error (a version missing or unreadable).
379
+
380
+ ## submit
381
+
382
+ ```sh
383
+ overcrow-widget submit --dry-run --submission submission.json
384
+ overcrow-widget submit --submission submission.json
385
+ ```
386
+
387
+ Sends a version of your widget to the OverCrow creator space, from a
388
+ terminal, a CI job or the OverCrow MCP server, then follows its checks. It
389
+ never asks a question: what is missing is said, with a stable
390
+ [exit status](#exit-status). It takes the widget folder (the current one
391
+ without argument) or a ZIP of it.
392
+
393
+ ### The publish key
394
+
395
+ - Create it in the creator space (Publisher, Publish keys). A key can only
396
+ submit versions of one widget, for 1 to 365 days (90 by default), and is
397
+ shown once.
398
+ - `submit` and `status` read it from the environment variable
399
+ `OVERCROW_PUBLISH_KEY`, and only there: never from an argument or a file
400
+ of the project. In a CI, keep it as a secret.
401
+ - The tool never shows it: any `ocw_pub_…` text is masked in its output,
402
+ its errors and its logs. Whatever the command, it removes the variable
403
+ from the environment of the programs it starts (TypeScript, the runtime).
404
+ - A key that expires within 14 days gives a warning. An expired or revoked
405
+ key ends with status 2: create a new one and replace the secret.
406
+ - Every request names the widget of the sources' `manifest.json` (header
407
+ `Overcrow-Widget`). A key that covers several widgets of its publisher
408
+ (reserved to PlayerVox for now) submits the one named; `status` then
409
+ takes `--widget`.
410
+
411
+ ### What it does
412
+
413
+ 1. It checks the key, and reads what the creator space needs for this
414
+ widget: the last approved version, the lowest version it takes now, the
415
+ submissions left (20 over 24 hours), whether the listing has a privacy
416
+ policy.
417
+ 2. It checks exactly what it will send. The folder is zipped as the
418
+ creator space reads it ([source archives](#source-archives)), read back
419
+ and admitted as the creator space admits it, `listing.json` being
420
+ optional; a ZIP given instead is sent byte for byte. The manifest ID
421
+ must be the key's widget and the version above the last approved one.
422
+ Each permission the version adds or widens (each permission, for a first
423
+ version) needs a justification, by its [key](#permission-keys). The
424
+ texts must follow the creator space's rules. If anything is wrong,
425
+ nothing is sent (status 1).
426
+ 3. It sends the archive, then follows the six checks of the creator space,
427
+ about a minute: manifest, version number, code analysis, package build,
428
+ permissions, size and resources.
429
+ 4. It ends when the version enters review (status 0), when a check fails
430
+ (status 1: each problem is shown on the line of your file), or when the
431
+ version passed its checks but waits in the creator space for what only
432
+ the creator space takes (status 3): a privacy policy when the widget
433
+ uses the network, a complete listing for a first version, or the review
434
+ slot of a new publisher. The link to finish there is shown.
435
+
436
+ ### A version the creator space already has
437
+
438
+ Before checking anything else, `submit` looks for a version of the same
439
+ number in the creator space. When it has the same sources (byte for byte,
440
+ as `submit` zips them) or, once admitted, the same package, nothing is
441
+ sent: the run ends on that version's state, with `outcome`
442
+ `already_known`.
443
+
444
+ - Status 0: it is published, approved, in review, or waits for your answer
445
+ to requested changes.
446
+ - Status 3: it waits in the creator space (the link to finish is shown).
447
+ - Status 1: it failed its checks, was refused, withdrawn or discarded:
448
+ raise the version in `manifest.json` to send other sources.
449
+ - A version still being checked is followed, as after a submission.
450
+
451
+ The same number with another package is refused before sending
452
+ (`submit.version_known_differs`): raise the version in `manifest.json`.
453
+ A CI job can therefore run `submit` on every push: a version already sent
454
+ changes nothing.
455
+
456
+ Ctrl+C while the checks run stops following them; they go on in the
457
+ creator space, and `overcrow-widget status --version 1.3.1 --wait` follows
458
+ them again (status 4). A run cut short before the end (network, Ctrl+C)
459
+ resumes the same submission when you run the same command again; changed
460
+ sources or texts make a new submission. A submission not finished within
461
+ an hour expires, and every submission counts in the daily limit.
462
+
463
+ | Option | Effect |
464
+ | --- | --- |
465
+ | `--submission FILE` | The texts of the version ([below](#the-texts-file)). |
466
+ | `--release-notes-en TEXT`, `--release-notes-fr TEXT`, `--review-message TEXT` | Replace those of the file. |
467
+ | `--dry-run` | Steps 1 and 2 only, nothing sent: what the creator space will ask for (justifications, privacy policy, review type, lowest version, submissions left) and the archive's SHA-256. For a first version, the creator space also checks the whole listing, which only it knows: a dry run that ends with 0 may still end with 3. |
468
+ | `--expect-sha256 HEX` | Sends only an archive with this SHA-256, the `archive.sha256` of a `--dry-run`: what is sent is what was checked. |
469
+ | `--no-wait` | Ends after the upload (status 4). |
470
+ | `--format json` | One JSON object ([machine-readable output](#machine-readable-output)). |
471
+ | `--verbose` | One line per request on the error output: method, address without its query, status and time; never a header, a key or a body. |
472
+
473
+ ### The texts file
474
+
475
+ <!-- source: docs/content/examples/weather/submission.json -->
476
+ ```json
477
+ {
478
+ "releaseNotes": {
479
+ "en": "First version: the forecast of your city, in metric or imperial units.",
480
+ "fr": "Première version : les prévisions de votre ville, en unités métriques ou impériales."
481
+ },
482
+ "justifications": [
483
+ {
484
+ "permission": "network:GET https://api.example.com/v1/forecast/{city}",
485
+ "text": "Reads the forecast of the city the player chose, every 30 minutes at most."
486
+ },
487
+ {
488
+ "permission": "storage",
489
+ "text": "Keeps the chosen city and units between two games."
490
+ }
491
+ ],
492
+ "reviewMessage": "The forecast API needs no account and receives only the city."
493
+ }
494
+ ```
495
+
496
+ | Key | Value |
497
+ | --- | --- |
498
+ | `releaseNotes` | The public notes of the version, shown to players: `en` (needed as soon as there are notes) and `fr`, 500 characters each, plain text, line breaks allowed. |
499
+ | `justifications` | For the reviewer, one `{permission, text}` per new or widened permission, by its [key](#permission-keys); 500 characters each. |
500
+ | `reviewMessage` | A private message to the reviewer, 2,000 characters. |
501
+
502
+ Every key is optional; any other key is refused. The OverCrow MCP server
503
+ writes this file.
504
+
505
+ ### In a CI job
506
+
507
+ A GitHub Actions workflow that installs the tool ([installing](#installing))
508
+ and submits the example widget `nova.weather` on every version tag, with
509
+ the key in the repository's secrets:
510
+
511
+ <!-- source: docs/content/examples/weather/.github/workflows/submit.yml -->
512
+ ```yaml
513
+ # Sends the widget to the OverCrow creator space when a version tag is
514
+ # pushed. The publish key is a secret of the repository, and the OverCrow
515
+ # release whose creator tools to use is a variable of the repository.
516
+ name: Submit to OverCrow
517
+
518
+ on:
519
+ push:
520
+ tags: ["v*"]
521
+
522
+ permissions:
523
+ contents: read
524
+
525
+ jobs:
526
+ submit:
527
+ runs-on: ubuntu-24.04
528
+ env:
529
+ OVERCROW_VERSION: ${{ vars.OVERCROW_VERSION }}
530
+ steps:
531
+ - uses: actions/checkout@v4
532
+ - name: Install overcrow-widget
533
+ run: |
534
+ tools="overcrow-creator-tools-$OVERCROW_VERSION-linux-x86_64"
535
+ curl --fail --location --silent --show-error --remote-name \
536
+ "https://github.com/Valhallab/playervox-overcrow-releases/releases/download/v$OVERCROW_VERSION/$tools.zip"
537
+ unzip -q "$tools.zip"
538
+ (cd "$tools" && sha256sum --check --quiet SHA256SUMS)
539
+ install -D -m 755 "$tools"/overcrow-widget-*-linux-x86_64 "$HOME/.local/bin/overcrow-widget"
540
+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
541
+ - name: Submit to OverCrow
542
+ run: overcrow-widget submit --submission submission.json
543
+ env:
544
+ OVERCROW_PUBLISH_KEY: ${{ secrets.OVERCROW_PUBLISH_KEY }}
545
+ ```
546
+
547
+ The job fails on any status but 0. `OVERCROW_API_URL` points `submit`
548
+ and `status` to another API, for tests only: `https://`, or `http://` to
549
+ `127.0.0.1`, `localhost` or `[::1]`, with a warning every time. Never set
550
+ it in a real job; the OverCrow MCP server never sets it.
551
+
552
+ ## status
553
+
554
+ ```sh
555
+ overcrow-widget status
556
+ overcrow-widget status --version 1.3.1 --wait
557
+ ```
558
+
559
+ Shows the versions of the key's widget, with their state and review type.
560
+ With `--version`, one version, by its number (the latest of that number)
561
+ or its ID: its six checks and their problems, what keeps it out of review,
562
+ the reviewer's remarks and the review delay. `--wait` follows a version
563
+ still being checked. `--widget ID` names the widget, for a key that covers
564
+ several (status 2 without it, with the widgets the key covers). Options:
565
+ `--widget ID`, `--version VERSION|ID`, `--wait`, `--format json`,
566
+ `--verbose`. Status: 0 when read, 2 on an error; with `--wait`, the
567
+ statuses of `submit`.
568
+
569
+ | State | Meaning |
570
+ | --- | --- |
571
+ | `checking` | The checks run. |
572
+ | `checks_failed` | A check failed: nothing reached the reviewers. |
573
+ | `ready` | The checks passed; the version waits in the creator space. |
574
+ | `in_review` | A person reviews it. |
575
+ | `changes_requested`, `approved`, `rejected` | The review's decision. |
576
+ | `published` | In the catalog. |
577
+ | `superseded`, `discarded` | Replaced by a newer submission, or abandoned. |
578
+ | `withdrawn`, `suspended` | Out of the catalog. |
579
+
580
+ ## Source archives
581
+
582
+ `admit` and `diff` take the widget folder or a ZIP of it (its name ends in
583
+ `.zip`), as the creator space receives it. The ZIP may hold the files
584
+ directly, or one folder that holds them all, as Windows and macOS make it.
585
+ It may carry a short archive comment (1,024 bytes at most), as GitHub's
586
+ "Download ZIP" and `git archive` write it; the comment is never read.
587
+
588
+ Left out of both, and never sent by the creator tools: hidden files and
589
+ folders (`.env`, `.git/`, `assets/.DS_Store`…), `node_modules/`, `dist/`,
590
+ `tests/output/`, `__MACOSX/`, built packages, key files and system files,
591
+ and, in a folder, links and names that are not portable ASCII. In a ZIP,
592
+ they still count toward the bounds below and are checked like the rest. A
593
+ name that holds a character Windows forbids (`\ : * ? " < > |`) is
594
+ refused, in a folder too.
595
+
596
+ | Bound | Value |
597
+ | --- | --- |
598
+ | Archive | 32 MiB |
599
+ | Uncompressed | 64 MiB |
600
+ | Files | 2,000 |
601
+
602
+ Everything is checked before a byte is written: a refused archive writes
603
+ nothing, and an admitted one is written only into a private work folder,
604
+ removed at the end.
605
+
606
+ | Code | The archive holds |
607
+ | --- | --- |
608
+ | `sources.archive_size` | More than 32 MiB. |
609
+ | `sources.too_large`, `sources.too_many_files` | More than 64 MiB or 2,000 files once uncompressed. |
610
+ | `sources.unsafe_name` | A name that could leave the widget folder (`../`, `/` first), or that some system cannot use: a character Windows forbids (`\`, `:`, `*`, `?`, `"`, `<`, `>`, \|), anything but printable ASCII, a final dot or space, `CON`, `NUL`, `COM1`… The message names the character and the file. |
611
+ | `sources.backslash` | Folders separated by `\`, as Windows PowerShell 5.1 `Compress-Archive` writes them. Send the widget folder itself in the creator space, or use [`submit`](#submit), which makes a correct ZIP. |
612
+ | `sources.duplicate_name` | Two names that differ only by case, or a file that is also a folder. |
613
+ | `sources.link`, `sources.special_file` | A link, or a device, a FIFO or a socket. |
614
+ | `sources.bomb` | An entry that inflates far beyond its compressed size, or beyond its declared size. |
615
+ | `sources.read` | The file cannot be read (exit status 2). |
616
+ | `sources.encrypted` | An encrypted entry. |
617
+ | `sources.zip64` | ZIP64, which sources never need. |
618
+ | `sources.archive` | Anything else a ZIP should not hold: a comment above 1,024 bytes or holding an end record, bytes before, between or after the entries or after an entry's compressed data, another name in an extra field, sizes or checksums that disagree. |
619
+
620
+ ## The code map
621
+
622
+ `--source-map FILE` writes a map from each position of the shipped
623
+ `logic.js`, bundled and minified, back to the file, line and column of
624
+ your sources: a [Source Map v3](https://tc39.es/ecma426/). The creator
625
+ space keeps it private and uses it to show you the errors of your widget
626
+ in your own code.
627
+
628
+ - `sources`: `logic.ts` (or `logic.js`), the files of `@overcrow/sdk`
629
+ (listed in `ignoreList`) and `overcrow:view-table`, the expression table
630
+ generated from `view.ocml`, whose text is in `sourcesContent`.
631
+ - `x_overcrow_functions`: the named functions of the sources,
632
+ `{"source", "name", "start": [line, column], "end": [line, column]}`,
633
+ zero-based, columns in UTF-16 units like `mappings`. The function of a
634
+ position is the innermost one around it. The expressions of the view
635
+ table are named `view expression <n>`, `<n>` being their index in
636
+ `view.json`.
637
+
638
+ The same sources always give the same map. It is never part of the
639
+ package, and `logic.js` does not point to it.
304
640
 
305
641
  ## Diagnostics
306
642
 
@@ -330,7 +666,9 @@ The code is `<domain>.<category>`:
330
666
  | `typecheck` | TypeScript | `tsc` (TypeScript's own message), `skipped`, `sdk_version`, `timeout` |
331
667
  | `package` | The package read back | `archive_size`, `file_size` and the categories of OverCrow's package reader |
332
668
  | `test` | Scenarios | `scenario`, `scenario_name`, `too_many_scenarios` |
669
+ | `sources` | A source archive | see [source archives](#source-archives) |
333
670
  | `init`, `doctor`, `admission` | Those commands | listed above |
671
+ | `submit` | What `submit` checks before sending | `widget_not_submittable`, `agreement_required`, `limit_reached`, `version_too_low`, `justification_missing`, `archive_too_large`, `archive_mismatch`, `release_notes`, `justification`, `review_message` |
334
672
 
335
673
  - Lines and columns start at 1; a column counts characters, not bytes.
336
674
  - An unknown name comes with the closest name that exists.
@@ -338,16 +676,93 @@ The code is `<domain>.<category>`:
338
676
  standard output:
339
677
  `{"severity","code","file","line","column","message","help"}`, with
340
678
  `null` for what is unknown. `package --format json` ends with one
341
- `{"package","bytes","sha256","logicBytes"}` object.
679
+ `{"package","bytes","sha256","logicBytes","sourceMap"}` object; `admit`
680
+ and `diff` print one report ([machine-readable output](#machine-readable-output)).
342
681
  - Texts that come from a widget (its logs, its names) are shown with
343
682
  terminal control characters neutralized.
344
683
 
345
684
  Scripts should match the codes: messages and help texts may be reworded.
346
685
 
686
+ ## Machine-readable output
687
+
688
+ With `--format json`, `admit`, `diff`, `submit` and `status` print one
689
+ JSON object on one line. Fields are only ever added; a `formatVersion`
690
+ change announces any other change.
691
+
692
+ `admit`:
693
+
694
+ | Field | Value |
695
+ | --- | --- |
696
+ | `formatVersion` | `1`. |
697
+ | `admitted` | Whether the sources are admitted. |
698
+ | `publisher` | The `--publisher` handle, or `third-party`. |
699
+ | `id`, `version`, `reservedId` | The widget; `null` when the sources were refused before the build. |
700
+ | `package` | `bytes`, `sha256` and each file's `bytes` and `sha256`. |
701
+ | `reproducible` | `viewJson` and `archive`, compared with `--package`, else `null`. |
702
+ | `listing` | `bytes`, `sha256`, `spdxLicense` and `preview` of `listing.json`. |
703
+ | `sources` | `kind` (`folder` or `archive`), `files`, `bytes`, `ignored` (`path`, `reason`) and, for a ZIP, `sha256` and `prefix` (the wrapping folder). |
704
+ | `review` | The authority to review, one object per item (`kind`, then its fields). |
705
+ | `permissions` | `keys`; with `--previous`, also `previous` (`id`, `version`), `added`, `changed`, `removed` and `reviewType` (`full` or `quick`), else `null`. |
706
+ | `listingPolicy` | `required` or `optional` (`--listing`). |
707
+ | `diagnostics` | The diagnostics, as above. |
708
+
709
+ `diff`:
710
+
711
+ | Field | Value |
712
+ | --- | --- |
713
+ | `formatVersion` | `1`. |
714
+ | `compared` | `false` when a version is refused; then only `diagnostics` follows. |
715
+ | `old`, `new` | `kind`, `files`, `bytes`, `sha256`, `prefix`, `ignored`, `id` and `version` of each version. |
716
+ | `files` | Changed files by path: `path`, `status` (`added`, `modified`, `removed`), `binary`, `tooLarge`, `oldSha256`, `newSha256`, `additions`, `deletions` and `hunks` (`oldStart`, `oldLines`, `newStart`, `newLines`, `lines`, each line starting with ` `, `-`, `+` or `\`). |
717
+ | `totals` | `added`, `modified`, `removed`, `additions`, `deletions`. |
718
+ | `permissions` | `added`, `changed`, `removed` and `reviewType`, or `null` without two valid manifests. |
719
+ | `diagnostics` | The diagnostics. |
720
+
721
+
722
+ `submit` and `status`:
723
+
724
+ | Field | Value |
725
+ | --- | --- |
726
+ | `formatVersion`, `command` | `1`; `submit` or `status`. |
727
+ | `outcome`, `exitCode` | How the run ended (below) and its [exit status](#exit-status). |
728
+ | `dryRun` | `submit`: whether nothing was to be sent. |
729
+ | `key` | `name`, `hint` (the four characters after `ocw_pub_`), `expiresAt`, `expiresSoon`, `widgets` (the widgets the key covers). |
730
+ | `widget` | `id`; `submit`: `publisher`, `status`; `status`: `name`. |
731
+ | `archive` | `submit`: `kind` (`folder`, zipped by the tool, or `archive`), `bytes`, `sha256`, `files`, `uncompressedBytes`, `ignored`. |
732
+ | `local` | `submit`: `admitted`, `version`, `minimumVersion`, `previousVersion`, `permissions` (`keys`, `added`, `changed`, `removed`, `reviewType`), `diagnostics`. |
733
+ | `requirements` | `submit`: `justifications` (`required`, `given`, `missing`, `unused`), `privacyPolicy` (`required`, `present`), `reviewType`, `submissions` (`limit`, `remaining`, `nextSubmissionAt`), `review` (`available`, `blockedBy`), `agreement` (`version`, `accepted`), `blockers` (`code`). |
734
+ | `known` | `submit`: the version the creator space already has (nothing was sent): `versionId`, `state`, `match` (`sources` or `package`). |
735
+ | `submission` | `submit`: `id`, `state`, `resumed`, `quota`. |
736
+ | `version` | The creator space's version, its fields in camelCase: `id`, `version`, `state`, `reviewType`, `checks` (`key`, `status`, `diagnostics`), `reviewBlockers`, `completeInPortal` (`message`, `url`), `permissions`, `remarks`, `deadline`, `history`… |
737
+ | `versions` | `status` without `--version`: every version. |
738
+ | `error` | `code`, `message` and, when known, `httpStatus`, `retryAfter`, `nextSubmissionAt`, `minimumVersion`, `expiredAt`, `fields`; else `null`. |
739
+
740
+ `outcome` is `ready_to_send` (`--dry-run`), `refused_locally`, `refused`
741
+ (the creator space refused the submission), `complete_in_portal`,
742
+ `already_known` (nothing sent, see `known`), `error`, or the version's
743
+ state; `status` without `--wait` has none. Error codes
744
+ are the creator space's (`version_not_newer`, `submission_limit_reached`,
745
+ `publish_key_expired`, `publish_key_revoked`, `widget_required`,
746
+ `publish_key_widget_not_covered`…) or the tool's:
747
+ `publish_key_missing`, `invalid_publish_key`, `api_url_invalid`,
748
+ `submission_file`, `sources`, `sources.read`, `network`, `timeout`,
749
+ `server`, `response`, `redirect`, `upload_refused`, `build_failed`,
750
+ `submission_state`, `not_found`, `internal`. Problems found before sending
751
+ are diagnostics: `sources.*`, `project.missing_file` (not the widget's
752
+ folder), `admission.*` and `submit.*` (`widget_not_submittable`,
753
+ `agreement_required`, `limit_reached`, `version_too_low`,
754
+ `justification_missing`, `archive_too_large`, `archive_mismatch`,
755
+ `version_known_differs`, `release_notes`, `justification`,
756
+ `review_message`).
757
+
347
758
  ## Exit status
348
759
 
349
760
  | Status | Meaning |
350
761
  | --- | --- |
351
- | 0 | Success. Warnings are allowed unless `--deny-warnings`. |
352
- | 1 | Errors were found; `admit` refused the submission; a scenario of `test` failed; the overlay ended a `dev` session. |
353
- | 2 | A usage or file error; no overlay for `dev`; no runtime for `test`. |
762
+ | 0 | Success. Warnings are allowed unless `--deny-warnings`. `diff` read both versions, whether or not they differ. `submit`: the version is in review (with `--dry-run`, it would enter review), or already past it (approved, published, withdrawn), or the creator space already had it in review, with changes requested, approved or published. |
763
+ | 1 | Errors were found; `admit` refused the sources; `diff` refused a version; a scenario of `test` failed; the overlay ended a `dev` session. `submit`: something to fix (a check before sending, a refusal of the creator space, a failed check, a version the creator space already refused, withdrew or discarded). |
764
+ | 2 | A usage or file error; no overlay for `dev`; no runtime for `test`. `submit`, `status`: the key (missing, invalid, expired, revoked), the network or the server. |
765
+ | 3 | `submit`, `status --wait`: the version passed its checks and waits in the creator space. |
766
+ | 4 | `submit`, `status --wait`: the version is still being checked (Ctrl+C, `--no-wait`, or 15 minutes). |
767
+
768
+ These meanings do not change from one version of the tool to the next.
@@ -0,0 +1,78 @@
1
+ # Getting started in the creator space
2
+
3
+ The creator space of PlayerVox OverCrow, at `creators.playervox.com`,
4
+ is where you publish widgets: you create your publisher once, reserve your widgets' IDs,
5
+ send their versions and follow their review. It is open by invitation for
6
+ now.
7
+
8
+ ## Sign in
9
+
10
+ Sign in with your PlayerVox account: the creator space sends you to
11
+ playervox.com, which asks you to confirm, then brings you back. You never
12
+ type your password in the creator space. The session lasts while you use
13
+ it, up to 14 days; you can close it on playervox.com, in
14
+ **Connected devices**.
15
+
16
+ The interface is in English or French: choose in the account menu. The
17
+ addresses stay the same in both languages.
18
+
19
+ ## Turn on two-factor authentication
20
+
21
+ Publishing requires two-factor authentication on your account. The first
22
+ visit turns it on:
23
+
24
+ 1. Open an authenticator app (Aegis, 2FAS, Google Authenticator,
25
+ 1Password…).
26
+ 2. Scan the QR code on a computer, or tap **Add to my app** on a phone or a
27
+ tablet. You can also type the key by hand.
28
+ 3. Enter the 6-digit code the app shows.
29
+
30
+ You then get ten recovery codes, shown once: each signs you in once if you
31
+ lose your phone. Keep them somewhere safe. Creating a publish key or
32
+ deleting your publisher asks for a fresh code again.
33
+
34
+ ## Create your publisher
35
+
36
+ The publisher is the name your widgets appear under.
37
+
38
+ - **Display name**: shown to players. A name that reads as PlayerVox,
39
+ OverCrow or Valhallab is refused.
40
+ - **Handle**: 3 to 32 lowercase letters, digits and hyphens, without a
41
+ hyphen at either end. It is **permanent**: it can never be changed, and a
42
+ handle is never given to anyone else, even after a deletion. Your
43
+ widgets' IDs start with it.
44
+ - **Contact e-mail**: for PlayerVox to reach you. It is never shown.
45
+ - **Website** and **logo** (square, PNG or WebP): optional, shown on your
46
+ publisher page. Type the website as you know it (`example.com`):
47
+ `https://` is added for you.
48
+
49
+ Your public profile (name, about, website, logo) appears with the next
50
+ publication of the catalog: until then the creator space says
51
+ **Visible after the next publication**.
52
+
53
+ Then read the creator agreement, summed up in six points on the screen, and
54
+ accept it. Your space is ready.
55
+
56
+ ## Reserve your first widget's ID
57
+
58
+ A widget ID is `<handle>.<name>`: `nova.lol-timers` for the handle `nova`.
59
+ With a [verified domain](verified-domain.md), it can also start with your
60
+ domain reversed: `gg.nova.lol-timers` for `nova.gg`. The name is lowercase
61
+ letters, digits and hyphens. An ID is permanent and never reused.
62
+
63
+ In **Widgets**, **New widget** reserves the ID. Create the project with the
64
+ same ID:
65
+
66
+ ```sh
67
+ overcrow-widget init lol-timers --id nova.lol-timers
68
+ ```
69
+
70
+ Try it in your game with the [development channel](dev-channel.md): nothing
71
+ is published.
72
+
73
+ ## Next
74
+
75
+ - Send a version: [publishing and review](publishing.md).
76
+ - Send from a terminal or a CI job: [publish keys and CI](publish-keys.md).
77
+ - Get the verified badge and IDs under your domain:
78
+ [verified domain](verified-domain.md).
@@ -239,10 +239,9 @@ locally stays unverified; users get widgets from the signed catalog. See
239
239
 
240
240
  ## 12. Submit
241
241
 
242
- Add a `listing.json` with the marketplace text, run the admission yourself,
243
- then open a pull request that adds your widget under `widgets/<dir>/` on the
244
- `candidate` branch of the
245
- [public repository](https://github.com/Valhallab/playervox-overcrow-releases):
242
+ Add a `listing.json` with the marketplace text and run the admission
243
+ yourself. Widgets are no longer proposed by pull request: you will send
244
+ yours from the OverCrow creator space when it opens.
246
245
 
247
246
  ```sh
248
247
  overcrow-widget admit