ravensight-playtest 0.5.1 → 0.6.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.
Files changed (101) hide show
  1. package/README.md +297 -14
  2. package/addons/ravensight_driver/driver.gd +406 -8
  3. package/addons/ravensight_simulate/simulate.gd +360 -0
  4. package/docs/godot-driver.md +70 -8
  5. package/package.json +4 -3
  6. package/src/api/README.md +4 -1
  7. package/src/api/client.js +94 -4
  8. package/src/api/errors.js +17 -1
  9. package/src/api/http.js +56 -20
  10. package/src/assets/formats.js +267 -0
  11. package/src/assets/index.js +260 -0
  12. package/src/assets/integration.js +429 -0
  13. package/src/assets/inventory.js +337 -0
  14. package/src/assets/measure.js +392 -0
  15. package/src/cli.js +209 -0
  16. package/src/commands/assets.js +62 -0
  17. package/src/commands/build.js +81 -0
  18. package/src/commands/check.js +4 -1
  19. package/src/commands/create.js +734 -0
  20. package/src/commands/fakeCore.js +16 -1
  21. package/src/commands/feature.js +845 -0
  22. package/src/commands/fix.js +578 -68
  23. package/src/commands/hosted.js +39 -0
  24. package/src/commands/init.js +19 -3
  25. package/src/commands/profile.js +25 -6
  26. package/src/commands/replay.js +204 -0
  27. package/src/commands/resume.js +7 -0
  28. package/src/commands/run.js +200 -24
  29. package/src/commands/template.js +70 -0
  30. package/src/commands/validate.js +414 -0
  31. package/src/commands/validateHosted.js +292 -0
  32. package/src/create/scaffold.js +192 -0
  33. package/src/hosted/archivePreflight.js +240 -0
  34. package/src/hosted/buildUpload.js +118 -0
  35. package/src/hosted/recordedRun.js +191 -0
  36. package/src/run/acceptance.js +212 -0
  37. package/src/run/args.js +18 -1
  38. package/src/run/checks.js +705 -0
  39. package/src/run/dimension.js +95 -0
  40. package/src/run/drivers/godot-observation.js +59 -11
  41. package/src/run/drivers/godot-project.js +201 -31
  42. package/src/run/drivers/godot.js +532 -45
  43. package/src/run/drivers/web.js +18 -0
  44. package/src/run/evidence.js +170 -0
  45. package/src/run/featureLoop.js +288 -0
  46. package/src/run/fixLoop.js +82 -12
  47. package/src/run/git.js +110 -20
  48. package/src/run/json.js +65 -9
  49. package/src/run/labsOutcome.js +136 -0
  50. package/src/run/liveWork.js +103 -0
  51. package/src/run/model.js +105 -5
  52. package/src/run/openPr.js +107 -0
  53. package/src/run/paths.js +4 -1
  54. package/src/run/pendingRegister.js +81 -0
  55. package/src/run/personaLoop.js +111 -4
  56. package/src/run/profile.js +68 -7
  57. package/src/run/replay.js +236 -0
  58. package/src/run/repoTools.js +227 -27
  59. package/src/run/report.js +7 -1
  60. package/src/run/resume.js +19 -1
  61. package/src/run/secretScan.js +35 -0
  62. package/src/run/settle.js +41 -0
  63. package/src/run/tools.js +33 -4
  64. package/src/run/trace.js +124 -0
  65. package/src/simulation/godotPack.js +112 -0
  66. package/src/ui/index.js +61 -9
  67. package/src/upload/allowlist.js +6 -2
  68. package/src/upload/index.js +5 -4
  69. package/templates/godot-2d/README.md +36 -0
  70. package/templates/godot-2d/addons/ravensight/LICENSE +21 -0
  71. package/templates/godot-2d/addons/ravensight/Ravensight.gd +1823 -0
  72. package/templates/godot-2d/export_presets.cfg +27 -0
  73. package/templates/godot-2d/gitignore +10 -0
  74. package/templates/godot-2d/project.godot +58 -0
  75. package/templates/godot-2d/scenes/main.tscn +67 -0
  76. package/templates/godot-2d/scripts/autoload/game_config.gd +83 -0
  77. package/templates/godot-2d/scripts/autoload/game_state.gd +44 -0
  78. package/templates/godot-2d/scripts/autoload/telemetry.gd +37 -0
  79. package/templates/godot-2d/scripts/main.gd +32 -0
  80. package/templates/godot-2d/scripts/player.gd +10 -0
  81. package/templates/godot-2d/scripts/state_hook.gd +16 -0
  82. package/templates/godot-2d/template.json +14 -0
  83. package/templates/godot-2d/tools/inject_release_key.sh +19 -0
  84. package/templates/godot-2d/tools/selftest.gd +70 -0
  85. package/templates/godot-3d/README.md +49 -0
  86. package/templates/godot-3d/addons/ravensight/LICENSE +21 -0
  87. package/templates/godot-3d/addons/ravensight/Ravensight.gd +1823 -0
  88. package/templates/godot-3d/export_presets.cfg +27 -0
  89. package/templates/godot-3d/gitignore +10 -0
  90. package/templates/godot-3d/project.godot +56 -0
  91. package/templates/godot-3d/scenes/main.tscn +154 -0
  92. package/templates/godot-3d/scripts/autoload/game_config.gd +83 -0
  93. package/templates/godot-3d/scripts/autoload/game_state.gd +44 -0
  94. package/templates/godot-3d/scripts/autoload/telemetry.gd +37 -0
  95. package/templates/godot-3d/scripts/beacon.gd +20 -0
  96. package/templates/godot-3d/scripts/main.gd +49 -0
  97. package/templates/godot-3d/scripts/player.gd +19 -0
  98. package/templates/godot-3d/scripts/state_hook.gd +25 -0
  99. package/templates/godot-3d/template.json +16 -0
  100. package/templates/godot-3d/tools/inject_release_key.sh +19 -0
  101. package/templates/godot-3d/tools/selftest.gd +77 -0
package/README.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # ravensight-playtest
2
2
 
3
+ Hosted comparisons use a separate command from the local `run`:
4
+
5
+ ```sh
6
+ ravensight-playtest hosted quote --game GAME --build BUILD --profile PROFILE --persona curious-kid --video --transcript --output hosted-quote.json
7
+ ravensight-playtest hosted run hosted-quote.json
8
+ ```
9
+
10
+ The quote names the full Standard then Jev price, prepaid amount, evidence
11
+ options, expiry and refund rules. It charges nothing. `hosted run` confirms
12
+ that saved quote before one admission request. Its durable journal blocks an
13
+ automatic second POST after an uncertain outcome; preserve it for reconciliation.
14
+ A charged-blocked acknowledgement does not prove gameplay or a report. This
15
+ command does not top up funds, change local run/report files or ask for model
16
+ proxy permission on the CLI credential.
17
+
18
+ On a server that advertises it as ready, `hosted quote --standard-provider openai`
19
+ selects OpenAI for Standard. Explicit `anthropic` works the same way. The returned
20
+ provider and policy hash must match and remain in the saved consent; `hosted run`
21
+ has no provider override. Omitting the flag keeps the original default request
22
+ and consent wire. No choice falls back to another provider, and a CLI declaration
23
+ does not establish deployed provider or hosted engine readiness. Existing `run`
24
+ continues to use its local runner and original API contract.
25
+
26
+ The hosted build command source adds a local check before a paid upload:
27
+
28
+ ```sh
29
+ ravensight-playtest build preflight ./game.zip --format web --entrypoint index.html
30
+ ravensight-playtest build upload ./game.zip --game GAME --profile READY_PROFILE --entrypoint index.html --dry-run
31
+ ```
32
+
33
+ `preflight` seeks through bounded ZIP metadata; it does not load a multi-GB
34
+ archive into memory. A saved server profile can be supplied with `--capacity`
35
+ for its declared limits. Upload selects a currently advertised ready profile,
36
+ checks metadata and a streamed checksum, then asks for the separate $0.49
37
+ validation hold before requesting it. The server’s isolated validator remains
38
+ authoritative. A passing local check does not establish engine, GPU or license
39
+ compatibility.
40
+
41
+ The current upload protocol is one streamed presigned PUT. Multipart upload
42
+ and byte-range resume are not advertised. The original upload journal is kept
43
+ after an uncertain response, and repeating that upload cannot silently request
44
+ a second reservation. A different journal does not cancel or refund an earlier
45
+ upload. Reports and existing run-upload journals are left intact. Larger limits
46
+ and native executable formats are usable only when the server advertises a
47
+ ready profile and the corresponding upload and runtime support exists. This
48
+ source addition does not claim an accepted AAA engine run or a published CLI
49
+ release.
50
+
3
51
  AI personas play your game, then file a report you can read, mark up and argue
4
52
  with. The personas run on your machine, against your build; Ravensight stores
5
53
  the reports and renders them.
@@ -9,8 +57,8 @@ progression checks through your own game adapter. It runs locally without
9
57
  model calls and saves bounded results to the same Playtest workspace. See
10
58
  [Simulation Runner](docs/SIMULATION.md) for setup.
11
59
 
12
- You need a Ravensight account and Node 22 or newer. You do not need an
13
- Anthropic API key: model calls go through Ravensight under the same token you
60
+ You need a Ravensight account and Node 22 or newer. You do not need a model
61
+ provider's API key: model calls go through Ravensight under the same token you
14
62
  log in with, so there is one credential on your machine and you can revoke it
15
63
  from the dashboard.
16
64
 
@@ -75,7 +123,7 @@ In CI, set `RAVENSIGHT_TOKEN` instead and skip `login` entirely.
75
123
 
76
124
  ## Commands
77
125
 
78
- Thirteen commands. Flags below are the ones the code accepts, not the ones the
126
+ Fourteen commands. Flags below are the ones the code accepts, not the ones the
79
127
  prose elsewhere describes; `--help` on any command prints the same list.
80
128
 
81
129
  Every command takes these four:
@@ -226,6 +274,11 @@ login).
226
274
  | `--game <gameId>` | The game to link. Optional with one visible game, or in a terminal. |
227
275
  | `--force` | Relink a repo that is already linked. |
228
276
 
277
+ A repository with a `project.godot` at its root is linked with `driver:
278
+ godot_driver` and `build: { kind: godot_project, ref: "." }`, so `run` needs no
279
+ `--driver` or `--godot-project`. The concurrency written is the one `check`
280
+ recommends for this machine.
281
+
229
282
  ### personas
230
283
 
231
284
  Lists the persona slugs `--personas` accepts, from the content pack this game
@@ -367,13 +420,15 @@ splitting the job in two is what gets everything played.
367
420
  | `--personas <list>` | Comma separated persona slugs. Defaults to one, `curious-kid`; `ravensight-playtest personas` lists them. |
368
421
  | `--driver <name>` | `playwright_web`, `godot_driver`, `cli_stdio`, or a native driver: `desktop_driver`, `unity_driver`, `unreal_driver`, `android_driver`, `ios_driver`. |
369
422
  | `--build-url <url>` | The web build to play. |
370
- | `--godot-project <dir>` | The Godot project directory. |
423
+ | `--godot-project <dir>` | The Godot project directory. A relative path is read from the repository root. |
424
+ | `--godot-path <path>` | Where Godot is, if it is not on the PATH. `RAVENSIGHT_GODOT` does the same. |
425
+ | `--realtime` | `godot_driver` only: let the game run in real time between actions. By default the game is paused while the persona decides and runs only while an action executes. |
371
426
  | `--driver-config <file>` | The native driver config, or the JSON-RPC bridge config for `cli_stdio`. |
372
427
  | `--skip-preflight` | Register without the free checks first: the build health check (any driver) and the automation probe (native drivers). The job is registered and charged even if the build or the automation server turns out to be down. |
373
428
  | `--cli <command>` | The command that starts a text build. |
374
429
  | `--max-actions <n>` | Lower the actions one persona may take. It can only lower the persona's own patience (and the server's per run ceiling), never raise it. |
375
430
  | `--long` | A long persona run: twice the actions, model budget and wall time of a standard run, at twice the price. The price is read from the estimate and confirmed before any charge. |
376
- | `--concurrency <n>` | Personas at once. Default 2; `check` recommends a number for this machine. |
431
+ | `--concurrency <n>` | Personas at once. Default the number `init` wrote, which is what `check` recommends for this machine. |
377
432
  | `--controller <name>` | One playthrough using `standard` or an available System One controller. The server must advertise and quote that exact choice. |
378
433
  | `--compare-with jev` | Separate agent/skill and Jev playthroughs for each chosen persona. Shows their combined quote before purchase. Comparisons run one playthrough at a time. |
379
434
  | `--record-video` | Capture the selected web or graphical Godot game locally. Does not upload the video. |
@@ -577,6 +632,11 @@ gives the finding, or a bare finding id.
577
632
  | `--max-actions <n>` | Cap the turns the fix may spend. Capped at 60 whatever you ask for. |
578
633
  | `--build-url <url>`, `--godot-project <dir>`, `--driver <name>` | Where the verify run plays, resolved exactly as `run` resolves them. |
579
634
  | `--json` | Print the changeset instead of the summary. |
635
+ | `--open-pr` | Fix v2 (Labs beta) only. After a fix the verify scored as fixed, ask, then commit the fix's files, push the branch and open a pull request with the evidence report. |
636
+ | `--no-labs` | Run the ordinary fix even when Fix v2 is on for the game. |
637
+ | `--allow-tests` | Fix v2: let the checks run the project's GUT or gdUnit4 tests, and run on edits to test files. Asked at a terminal when not given. |
638
+ | `--allow-tool-scripts` | Fix v2: let the checks import a project whose edits touched `project.godot`, `export_presets.cfg`, `override.cfg`, `addons/`, `.godot/` or a `@tool` script. |
639
+ | `--godot-path <file>` | The Godot binary for the verify run and the Fix v2 checks. |
580
640
 
581
641
  What happens, in order:
582
642
 
@@ -595,15 +655,21 @@ What happens, in order:
595
655
  7. `changeset.json` and `report.md` are written, uploaded and attached to the
596
656
  fix run, and the pull request command is printed.
597
657
 
598
- **It never pushes and never commits.** There is no `git commit`, no `git push`
599
- and no forge client anywhere in the command. You are left on the branch with
658
+ **It never pushes and never commits** unless you pass `--open-pr` to a Fix v2
659
+ attempt and answer yes at its prompt (see below). You are left on the branch with
600
660
  the change in your working tree, and the last thing printed is the command to
601
661
  open the pull request once you have read the diff.
602
662
 
603
- A fix attempt is one unit. It is refunded when the finding turns out to be
604
- design intent, and refunded when the attempt changes nothing, in both cases
605
- without a model turn being spent on the edit itself. The verify run is included
606
- in the price.
663
+ A fix attempt is one unit, refunded in full in three cases: the finding turns
664
+ out to be design intent, the attempt changes nothing, or the game did not boot
665
+ for the verify run, in which case the $5.00 comes back because the fix could
666
+ not be verified. The verify run is included in the price, and the CLI always
667
+ completes the verify run before the fix run so the server can read it.
668
+
669
+ An account gets 5 refunds in any 30 days of a fix attempt that used model time,
670
+ counting a cancel or any other failure. Past that the attempt is kept, and the CLI
671
+ prints the server's note saying so instead of a refund. An attempt that used no model
672
+ time always comes back. A persona run has the same rule with 20 refunds, and a game profile with 5.
607
673
 
608
674
  **A verify can only mean something against a build this machine serves.** The
609
675
  change exists in your working tree and nowhere else, so a `--build-url`
@@ -615,6 +681,90 @@ branch locally before the verify, or skip it.
615
681
  The verdict is printed in words: fixed below 0.35, still reproduced above 0.65,
616
682
  unknown in between, and "not verified" when there was no verify run.
617
683
 
684
+ #### Fix v2 (Labs beta)
685
+
686
+ When Ravensight Labs is on for the game and the server reports Fix v2 as live,
687
+ `fix` adds four things. Without that answer from the server, `fix` is exactly
688
+ the command described above.
689
+
690
+ - **An acceptance contract before any edit.** The CLI writes
691
+ `{ expected, actual, reproSteps, regressionPersonas }` from the finding,
692
+ prints it before the price, and sends it when the job is registered. The
693
+ server freezes it on the job. The apply step reads it and cannot change it,
694
+ and the verify brief is built from it alone. If the server does not freeze
695
+ it, the attempt carries on as an ordinary fix and says so.
696
+ - **Named checks, never a shell.** The apply step may call `run_check` with one
697
+ of three names, and the CLI runs all three after every apply:
698
+
699
+ | Check | What runs |
700
+ |---|---|
701
+ | `godot_import` | `godot --headless --path <copy> --import`, then every script error in the log |
702
+ | `godot_script_check` | `--check-only` on each changed `.gd` file, after the import |
703
+ | `project_tests` | GUT (`addons/gut`) or gdUnit4 (`addons/gdUnit4`), whichever the project ships |
704
+
705
+ Each runs on a fresh temporary copy of the project (no `.git`, no
706
+ `.ravensight`), with a time limit and an output cap, and the copy is
707
+ deleted afterwards. A check that cannot run (no Godot, no tests) is reported
708
+ as unavailable, not as passed. **A fix whose `godot_import` or
709
+ `godot_script_check` still fails after its repairs is never uploaded:** the
710
+ fix run is completed as failed, the unit comes back, the edit stays on the
711
+ branch and the evidence stays in the run directory. Project tests that still
712
+ fail do not block: the change uploads, the unit is kept, and the report's
713
+ first line and the terminal name the failing checks.
714
+ - **What a fix can never touch.** The model's tools refuse, whatever a file in
715
+ the repository asks for: anything outside the repository or through a symbolic
716
+ link; `.git`; credential files by name (`.env`, keys, `.netrc`, `secrets.json`,
717
+ `export_presets.cfg` and the like); gitignored files, which are neither read nor
718
+ written because git would never show the change; a nested repository or
719
+ submodule; git's own controls, hooks and CI (`.gitignore`, `.gitattributes`,
720
+ `.husky`, `.github/workflows`, the directory `core.hooksPath` names and so on);
721
+ art, audio and anything that is not UTF-8 text; and a file name with control or
722
+ invisible characters. Each refusal goes back to the model as an answer.
723
+ - **What runs on your machine.** The checks and the verify run execute the
724
+ edited project on this machine, and the price confirmation says so. A
725
+ Godot import runs editor-side code, and tests run your test code with the
726
+ model's edits in place, so:
727
+ - every check gets a reduced environment: `PATH` and the locale from yours,
728
+ and `HOME`, the temp directories and Godot's user-data directory pointed
729
+ into the check's own temp root. No token, provider key, SSH agent, cloud
730
+ or GitHub credential is passed on. The verify run's Godot gets the
731
+ driver's own short allowlist, as before.
732
+ - no check runs when the edits touched `project.godot`,
733
+ `export_presets.cfg`, `override.cfg`, anything under `addons/` or
734
+ `.godot/`, or a `@tool` script, unless you pass `--allow-tool-scripts`;
735
+ nor when they touched test files (`test/`, `tests/`, `test_*.gd`,
736
+ `*Test.gd`, `*_test.gd`, or a directory in `.gutconfig.json`) unless you
737
+ allow tests. The result is `check_refused`, and the fix is not uploaded.
738
+ - `project_tests` runs only with `--allow-tests`, or a yes at a terminal;
739
+ otherwise it is unavailable.
740
+ - the temp copy leaves out credential files, and a check's process group is
741
+ killed with it at its time limit and at Ctrl-C
742
+ - on macOS, when `sandbox-exec` exists, each check runs under a profile
743
+ that denies all network access and every write outside its temp root.
744
+ On Linux and Windows no OS sandbox is applied: the reduced environment
745
+ and the temp copy are the whole of the isolation.
746
+ - **Bounded repair.** A failed check, or a verify that still reproduces the
747
+ finding (above 0.65), starts one more apply turn set inside the same run
748
+ budget, with the failure in front of the model and the contract unchanged.
749
+ At most two repairs. A repair after a verify needs a spare verify run from
750
+ the server to judge it; without one the result is reported, not repaired.
751
+ - **An evidence report as the pull request body.** `report.md` carries the
752
+ contract, the checks with their results and times, the files, the verify
753
+ before and after, the remaining risks, and keeps verified facts (what the
754
+ CLI and git measured) apart from model judgement (the hypothesis, the
755
+ description, the verify score).
756
+
757
+ `--open-pr` is the one way this command pushes. It needs Fix v2, a verify that
758
+ scored the fix as fixed, `gh auth status` to pass and a yes at its own prompt
759
+ (`--yes` agrees to the price, not to publishing). It commits only the files the
760
+ fix changed, pushes with a plain `git push -u origin <branch>`, never forced,
761
+ and runs `gh pr create` with the evidence report as the body. Later runs in this
762
+ repository check that pull request with your own `gh`, in the background, and tell
763
+ the job whether it was merged, reverted or abandoned. The URL stays in the local
764
+ journal, the check never holds up or fails a command, and no charge or refund reads
765
+ the answer. A revert pushed directly rather than through a pull request reads as
766
+ merged.
767
+
618
768
  **A fix cannot be resumed.** Ctrl-C, or cancelling the job from the dashboard,
619
769
  abandons the attempt and gives the unit back: whatever was written stays on the
620
770
  branch for you to read or delete, and nothing is committed. That is different
@@ -811,12 +961,14 @@ reasoning, exactly as `profile` already does, and the same guards apply: a file
811
961
  that trips the secret scan is withheld rather than read, and both files a fix
812
962
  writes are scanned again before they are uploaded.
813
963
 
964
+ Your art and audio stay on your machine. The `assets` command sends nothing. During a `feature` job the model reads, through the same proxy, a list of each asset's path, type, size and measurements, and a model can never read an art or audio file's content. What uploads with the job is `changeset.json` and `report.md` as for a fix, plus how many files, how many used and unused, and how many of each kind of warning, in `report.md`, with no file names. The model writes the pull request text in `report.md`, so it may name a file it used. Placeholders are uploaded by name, because they are what you are being asked to supply. `assets-report.md` and `assets.json`, which name every file, are not on the allowlist.
965
+
814
966
  Run `upload --dry-upload` or `run --dry-upload` to see the exact file list and
815
967
  byte count before anything leaves the machine.
816
968
 
817
- Model calls go to Ravensight's proxy rather than to Anthropic, under the token
818
- you logged in with. No Anthropic key exists on your machine, and the CLI builds
819
- its client with `apiKey` explicitly null, so an `ANTHROPIC_API_KEY` already in
969
+ Model calls go to Ravensight's proxy rather than to a model provider, under the
970
+ token you logged in with. No provider key exists on your machine, and the CLI
971
+ builds its client with `apiKey` explicitly null, so a provider key already in
820
972
  your environment is never picked up and never sent anywhere.
821
973
 
822
974
  Before anything is written to a run directory, the transcript and `usage.json`
@@ -946,6 +1098,137 @@ feedback and timing-sensitive gameplay.
946
1098
 
947
1099
  Browser and Godot runners share the paid playtest lifecycle with desktop, Unity/Unreal export, Android/iOS and custom JSON-RPC adapters. Native adapters require a locally configured automation server and remain experimental until validated against your build. See [adapter setup and validation boundaries](docs/ADAPTERS.md) and the [native runner starter](docs/NATIVE_RUNNER.md); `check` probes the automation server for free before a paid native run.
948
1100
 
1101
+ ## Validate changes (Labs beta)
1102
+
1103
+ Godot only, and only when Ravensight Labs is on for the game. Plays a branch and its base with the same personas on the same seeds and compares them. Your source stays on your machine; the commits are extracted to temp directories, and both must start before a price is shown.
1104
+
1105
+ ```sh
1106
+ ravensight-playtest validate my-branch --base main --runs 5
1107
+ ravensight-playtest replay <runId> --ref my-branch --baseline
1108
+ ```
1109
+
1110
+ Each persona run is one standard Playtest purchase of 5 AI units, and the whole plan is charged once at the start. Below five runs a side the result says not significant and shows a direction only. A run that does not earn its unit is refunded and does not count in the comparison. If one side ends with no usable run there is nothing to compare, and the runs on the other side that played and reported keep their units, because those runs happened and their reports are real. `--extend-to <n>` buys more pairs only when the first answer was too small to call. `--fail-on-regression` exits 1 for CI. A replay makes no model call and is free. See [what a replay does and does not prove](docs/REPLAY.md).
1111
+
1112
+ ## Create a game (Labs, Experimental)
1113
+
1114
+ Godot 2D only, and only when the platform has Create a game switched on. It is for owners and admins, and for an account that has added at least $10 in top-ups. The balance has to reach the plan's start balance, the whole plan's price plus 25 percent, at least $2 extra, rounded up to a whole dollar, and only the price is charged. The balance has to cover the whole plan you declare, and the command shows that total before you confirm. It may not produce a game you want.
1115
+
1116
+ ```bash
1117
+ ravensight-playtest create "A keeper walks a dark hall and lights each lamp in turn" --name "Lantern Sweep" --milestones 3 --size medium
1118
+ # read the design and approve it in the dashboard, then, from the project folder:
1119
+ ravensight-playtest create <job-id>
1120
+ ```
1121
+
1122
+ The first command makes a new game, with its key in `ravensight_key.cfg`, which git ignores, and asks for a game design. A person approves or rejects that in the dashboard. Rejecting it gives the whole charge back, within the refund limit below. To change a design, reject it and start again from a better brief.
1123
+
1124
+ The second command writes the scaffold and checks in Godot that it imports and starts. Then it builds one milestone at a time, each an ordinary Build a feature job with its own charge, refund rules and branch, landing on `main` when it validates. A milestone that does not validate stops the run: its branch holds the attempt, and the same command tries again, which uses up another declared milestone if that attempt kept its charge. The run always stops at the declared count, however many milestones the design lists.
1125
+
1126
+ When every declared milestone has validated, a persona plays the finished game. Playable means Ravensight's own records show that run finished cleanly, and the game itself reports at least one completed core loop. A persona is a model playing the game, not a player, so play it yourself before you ship it.
1127
+
1128
+ **Stopping.** Ctrl-C, or `create <job-id> --stop` later, closes the plan. What finished stays paid for, the playable check comes back if it never started, and a milestone that was never started was never charged. If the process dies without that, run the same command to carry on. A plan left alone closes after 14 days.
1129
+
1130
+ **The refund limit.** Once the model has been used on a plan, an account can get its first charge back twice in any 30 days. Past that, a brief that is declined, a design you reject and a plan that stops before its scaffold boots all keep that charge, and the plan's page and this command say so. The persona run that never played still comes back. The command states how many you have left before you confirm.
1131
+
1132
+ **The hourly limit.** A studio has an hourly model spend limit, and a large milestone's budget can pass it. The job pauses until the top of the next hour, says how long, and carries on. Ctrl-C ends the wait. The wait costs no model time, but it does count toward the run's own time limit, so a run that passes that limit while it waits stops there and its job's refund rules apply.
1133
+
1134
+ **Your own art and audio.** Ravensight does not make any. The first command says where the files go, inside the new project: `assets`, or the folder you name with `--assets-dir`. Put them there before the second command, and each milestone reads what was measured about them and can use them, as in [Your own art and audio](#your-own-art-and-audio). Anything missing stays a placeholder. If you add files after the scaffold is written, commit them before you carry on, because a milestone only starts from a clean tree.
1135
+
1136
+ **The scaffold** is a Godot 4 2D project from the template in this package, with the public Ravensight SDK unmodified, a key loader, a player opt-out in its settings, build-time key injection for a public build, events that always say what they mean through `rs_kind`, and a `_ravensight_state()` node a playtest reads. Every visual is a placeholder primitive. Studios bring their own art and audio: nothing is generated. `README.md` in the project says how each part works, and `tools/selftest.gd` checks them.
1137
+
1138
+ | Flag | What it does |
1139
+ |---|---|
1140
+ | `--name <title>` | The working title. |
1141
+ | `--dir <path>` | Where to make the project, default `./<title>`. It has to be new or empty. |
1142
+ | `--milestones <n>` | How many milestones to buy at most, default 3. |
1143
+ | `--size <size>` | The largest a milestone may be: `small`, `medium` or `large`. |
1144
+ | `--personas <list>` | Persona slugs. |
1145
+ | `--godot-path <path>` | Where Godot is, if it is not on the `PATH`. |
1146
+ | `--headless` | Play headless: no screenshots, and no mouse or GUI input reaches the game. |
1147
+ | `--allow-tool-scripts` | Let the checks import edits to `project.godot`, addons, `.godot` or `@tool` scripts. |
1148
+ | `--stop` | Close the plan now. |
1149
+ | `--assets-dir <dir>` | The folder inside the project that holds your art and audio, default `assets`. |
1150
+
1151
+ ## Build a feature (Labs beta)
1152
+
1153
+ 2D Godot projects only, and only when Ravensight Labs is on for the game and the platform has Build a feature switched on. The specification and the job are separate, so a person approves what will be built before any code is bought.
1154
+
1155
+ ```sh
1156
+ ravensight-playtest feature "Hold shift to sprint, draining stamina that refills at rest"
1157
+ # read, edit and approve it on the Labs page in the dashboard, then:
1158
+ ravensight-playtest feature <spec-id> --godot-project .
1159
+ ```
1160
+
1161
+ Writing a specification is one AI unit. It covers requirements, acceptance criteria, affected systems, proposed files, the SDK events to add, and up to three test scenarios. A brief bigger than the large size, outside the bounded gameplay systems (movement, health, stamina, inventory, scoring, simple enemy behaviour, HUD widgets), or needing 3D is declined and costs nothing. A CLI token cannot edit or approve a specification.
1162
+
1163
+ Building it needs an account that has added at least $10 in top-ups, a clean working tree, and a balance at the plan's start balance (the whole plan's price plus 25 percent, at least $2 extra, rounded up to a whole dollar), shown before you confirm with only the price charged. The plan is a price set by the specification's size, plus one persona run per test scenario, charged once. Everything then happens on your machine, on a new branch that is never committed or pushed for you: plan, edits (at most 8 files for a small feature, 20 for a medium one and 40 for a large one, counted across the repairs too), the named checks, a persona playing each scenario, and a summary. A failed check or a failed scenario starts a repair, at most two, and the specification frozen on the job never moves.
1164
+
1165
+ The whole plan comes back if nothing changed or the change does not pass its checks, up to three times in any 30 days per account once a job has used model time. Past that the feature's own price is kept, the command and the job say so, and scenario runs that did not play still come back. A job that used no model time is always refunded. The unit is kept once a change is delivered, verified or not, and the report says which. Verified means the server's own records show every scenario's persona run finished with an accepted report, no script errors and no blocker or major finding; those personas are model players, so play it yourself before you ship it. After a repair, a scenario that already passed replays its recorded inputs for free, and if they no longer replay the same it stops counting as passed.
1166
+
1167
+ Studios bring their own art and audio. See [Your own art and audio](#your-own-art-and-audio). If the feature needs an asset the project lacks, it is built with a placeholder primitive and named in the report.
1168
+
1169
+ | Flag | Effect |
1170
+ |---|---|
1171
+ | `--game <gameId>` | The game, when this repo is not linked. |
1172
+ | `--assets-dir <dir>` | The folder inside the project that holds your art and audio, default `assets`. |
1173
+ | `--branch <name>` | The branch to create, default `ravensight/feature-<title>-<hex>`. |
1174
+ | `--personas <list>` | Who plays the scenarios, used in turn. |
1175
+ | `--godot-project <dir>`, `--godot-path <path>` | Where the project and Godot are. |
1176
+ | `--headless` | Play the scenarios headless: no screenshots, and no mouse or GUI input reaches the game. |
1177
+ | `--allow-tests`, `--allow-tool-scripts` | The same two permissions a fix asks for. |
1178
+ | `--open-pr` | After a verified feature, ask, then commit its files, push the branch and open a pull request with your own `gh`. |
1179
+ | `--max-actions <n>` | A lower ceiling on model turns in the apply loop. |
1180
+
1181
+ ### Your own art and audio
1182
+
1183
+ Ravensight does not make art or audio, and there is no separate price for using yours. Put your files in a folder inside the project, `assets` unless you say otherwise (`--assets-dir`, or `assets_dir` in `.ravensight/config.json`), and a feature uses them.
1184
+
1185
+ ```sh
1186
+ ravensight-playtest assets
1187
+ ravensight-playtest assets --assets-dir art --grid 32
1188
+ ```
1189
+
1190
+ `assets` reads that folder on your machine and prints each file with what was measured. It needs no login, sends nothing and costs nothing, so run it as often as you like.
1191
+
1192
+ | What | Measured for |
1193
+ |---|---|
1194
+ | Type and size | Every file |
1195
+ | Width, height, transparency, pixel pitch, layout guess (one picture, a tile, a strip or a sheet) | PNG |
1196
+ | Format, channels, sample rate, length | WAV and Ogg |
1197
+
1198
+ Other formats are listed by type and size only. `--grid <n>` warns about any PNG that does not measure `n` art pixels across.
1199
+
1200
+ The warnings come from wiring real art into a real game:
1201
+
1202
+ - **The real pixel pitch.** Measured from the pixels, not from what a file was meant to be. A file described as a 32 grid can be 100 or more art pixels across.
1203
+ - **Alpha before trimming.** Faint, nearly invisible pixels can reach the edge of the canvas, so a trim keeps almost all of it. The warning gives the box both ways.
1204
+ - **Tiles with their own frame.** A frame around each tile draws a grid across the floor. Use tiles with no per-tile frame, or one seamless texture.
1205
+ - **Sound Godot will not import.** Opus in an Ogg file, compressed WAV and WAV saved with the extended header.
1206
+ - **Smooth filtering on pixel art.** Pixel art blurs when the project's default filter is smooth, unless the node drawing it sets the nearest filter.
1207
+
1208
+ During a feature job the model reads a list of those measurements, never the files. It cannot read or quote an art or audio file, and it cannot write one, or anything else in the declared folder except the `.import` settings beside a file. Three more checks join the others: `asset_references` (every asset the change names exists, with that exact case, inside the project), `asset_import` (real Godot imports it) and `pixel_art_settings` (pixel art the change names has the nearest filter and clean import settings). A reference that does not resolve or a file that does not import blocks the change, and the job is refunded, once its repairs are used. A pixel art setting that stays wrong is listed as a risk. Only what the change names can fail a job.
1209
+
1210
+ The report says what was wired in, what the project uses, what is unused and which placeholders are left for you to supply. The names are in `assets-report.md` in the run directory, which stays on your machine.
1211
+
1212
+ ## 3D proof of concept (Labs, Alpha)
1213
+
1214
+ Labs beta is Godot 2D. There is one 3D template, for trying Build a feature and Validate changes on a 3D project. That is the whole of the Alpha: `create` does not make a 3D game from a brief and refuses to try, and how well a real model builds 3D has not been measured. It has no switch of its own, needing the same Labs opt-in and capability switches, and no price of its own: the jobs cost what they cost on a 2D project.
1215
+
1216
+ ```sh
1217
+ ravensight-playtest template godot-3d --game <gameId> --dir beacon-walk --name "Beacon Walk"
1218
+ cd beacon-walk
1219
+ ravensight-playtest feature "Each beacon is worth two points" --alpha-3d
1220
+ # read, edit and approve it on the Labs page in the dashboard, then:
1221
+ ravensight-playtest feature <spec-id> --alpha-3d
1222
+ # commit the branch, then:
1223
+ ravensight-playtest validate <branch> --base main --alpha-3d
1224
+ ```
1225
+
1226
+ **The template** is a small project of primitive meshes: walk to a beacon, it moves, and that is one pass of the core loop. It has the public Ravensight SDK, unmodified, the same key loader, opt-out and `tools/selftest.gd` as the 2D template, and a `_ravensight_state()` node that reports positions in three axes. It is written with no key, so the SDK does nothing until you add this game's key. Writing it costs nothing and no model is involved.
1227
+
1228
+ **`--alpha-3d`** is how you ask. Without it, `feature` and `validate` refuse a project whose main scene has a 3D root, for free. With it on a 2D project they refuse too, and a specification written for one kind of project does not build on the other.
1229
+
1230
+ **What works differently.** A persona reads positions as `@(x,y,z)` in world units, and can click a node by its path, where the active camera draws it. It plays with keys and input actions: it cannot steer a camera with the mouse, so a feature that needs mouse look cannot be played by a persona. Headless, as in 2D, no mouse input reaches the game. Your own models are listed by `assets` by type and size, are never read by the model, and the checks confirm that Godot imports the ones a change names. See [docs/REPLAY.md](docs/REPLAY.md) for what replays on 3D.
1231
+
949
1232
  ## Simulation Runner
950
1233
 
951
1234
  Available since `0.4.0`. Simulation Runner requires macOS or Linux (including WSL); native Windows is refused before purchase.