@hyprune/schema 0.0.0-stage → 0.5.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 (78) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/LICENSE +21 -0
  3. package/README.md +140 -2
  4. package/bin/validate.mjs +19 -0
  5. package/examples/extension.json +22 -0
  6. package/examples/ipc/error.json +11 -0
  7. package/examples/ipc/movement.set.request.json +8 -0
  8. package/examples/ipc/movement.set.response.json +7 -0
  9. package/examples/ipc/runtime.exit.request.json +6 -0
  10. package/examples/ipc/runtime.exit.response.json +7 -0
  11. package/examples/ipc/runtime.notice.notification.json +9 -0
  12. package/examples/ipc/session.hello.request.json +17 -0
  13. package/examples/ipc/session.hello.response.json +23 -0
  14. package/examples/ipc/session.ping.request.json +6 -0
  15. package/examples/ipc/session.ping.response.json +7 -0
  16. package/examples/ipc/session.revoked.notification.json +7 -0
  17. package/examples/ipc/shell.claim.request.json +10 -0
  18. package/examples/ipc/shell.claim.response.json +8 -0
  19. package/examples/ipc/shell.overlay.request.json +11 -0
  20. package/examples/ipc/shell.overlay.response.json +7 -0
  21. package/examples/ipc/shell.release.request.json +8 -0
  22. package/examples/ipc/shell.release.response.json +7 -0
  23. package/examples/ipc/state.delta.notification.json +18 -0
  24. package/examples/ipc/state.snapshot.request.json +8 -0
  25. package/examples/ipc/state.snapshot.response.json +37 -0
  26. package/examples/ipc/state.subscribe.request.json +10 -0
  27. package/examples/ipc/state.subscribe.response.json +38 -0
  28. package/examples/ipc/state.unsubscribe.request.json +8 -0
  29. package/examples/ipc/state.unsubscribe.response.json +7 -0
  30. package/examples/ipc/surface.focus.request.json +9 -0
  31. package/examples/ipc/surface.focus.response.json +7 -0
  32. package/examples/ipc/world.load.request.json +9 -0
  33. package/examples/ipc/world.load.response.json +7 -0
  34. package/examples/placement-input.json +169 -0
  35. package/examples/screen-type.json +24 -0
  36. package/examples/world.json +111 -0
  37. package/extensions/hud-style-manifest.schema.json +17 -0
  38. package/extensions/hud-style.schema.json +118 -0
  39. package/lib/validate.d.mts +37 -0
  40. package/lib/validate.mjs +221 -0
  41. package/package.json +57 -4
  42. package/v0/common.schema.json +85 -0
  43. package/v0/extension.schema.json +121 -0
  44. package/v0/ipc.schema.json +1725 -0
  45. package/v0/screen-type.schema.json +115 -0
  46. package/v0/world.schema.json +363 -0
  47. package/v0.10/ipc.schema.json +8811 -0
  48. package/v0.11/ipc.schema.json +8863 -0
  49. package/v0.12/ipc.schema.json +9541 -0
  50. package/v0.13/ipc.schema.json +10032 -0
  51. package/v0.14/ipc.schema.json +10127 -0
  52. package/v0.15/ipc.schema.json +10534 -0
  53. package/v0.16/ipc.schema.json +10550 -0
  54. package/v0.17/ipc.schema.json +10703 -0
  55. package/v0.18/ipc.schema.json +10801 -0
  56. package/v0.19/ipc.schema.json +11587 -0
  57. package/v0.2/common.schema.json +86 -0
  58. package/v0.2/ipc.schema.json +3570 -0
  59. package/v0.2/world.schema.json +363 -0
  60. package/v0.3/common.schema.json +477 -0
  61. package/v0.3/ipc.schema.json +4044 -0
  62. package/v0.3/world.schema.json +390 -0
  63. package/v0.4/common.schema.json +477 -0
  64. package/v0.4/ipc.schema.json +5561 -0
  65. package/v0.4/world.schema.json +496 -0
  66. package/v0.5/common.schema.json +477 -0
  67. package/v0.5/ipc.schema.json +5781 -0
  68. package/v0.5/world.schema.json +790 -0
  69. package/v0.6/common.schema.json +478 -0
  70. package/v0.6/input.schema.json +519 -0
  71. package/v0.6/ipc.schema.json +7375 -0
  72. package/v0.6/world.schema.json +1062 -0
  73. package/v0.7/common.schema.json +478 -0
  74. package/v0.7/ipc.schema.json +7905 -0
  75. package/v0.7/world.schema.json +1062 -0
  76. package/v0.8/ipc.schema.json +7945 -0
  77. package/v0.9/input.schema.json +518 -0
  78. package/v0.9/ipc.schema.json +8613 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,144 @@
1
+ # Changelog
2
+
3
+
4
+ ## v0 / 0.1.0 — 2026-10-07 (proposed)
5
+
6
+ Initial JSON Schema 2020-12 family: world format `0.1`, IPC `0.1`, extension manifest/API `0.1`, screen descriptor `0.1`. Includes every core method's request and result plus notifications, offline examples and a Node validator. Identifiers are reserved for these contracts; incompatible changes require a new wire/format identifier and migration notes. No runtime compatibility is claimed yet.
7
+
8
+ ## 0.2.0 — 2026-10-07
9
+
10
+ Adds frozen `v0.2/` schemas for IPC 0.2 and world format 0.2; `v0/` stays unchanged. The validator accepts an optional fourth `version` argument (default `0.1`); CLI accepts `[response-method|-] [contract-version]`.
11
+
12
+ IPC adds camera get/set, waypoint/route, travel, autodrive, ui.open/close, data.publish/remove and presentation notifications. `location` and `integrations` are revisioned state keys. Publishing requires its own capability; scalar values, TTL, sequence and ownership are specified by RFC-0003. World 0.2 has the same manifest shape, with RFC-0004's sampler/transform/PBR material semantics. No mock-only protocol is accepted.
13
+
14
+ M1 shell reconciliation adds stable transition IDs, output identity, monotonic timestamps and indeterminate loading/failed phases. World-load destinations remain distinct from point/zone navigation targets.
15
+
16
+ ## 0.3.0 — first real session
17
+
18
+ Frozen IPC 0.3 adds verified shell Wayland-child binding, workspace activation,
19
+ revisioned safe inline map/metadata, selected-output descriptor and core-projected
20
+ markers. 0.1/0.2 and world formats remain frozen. New positive/negative tests cover
21
+ version isolation, reserved parameters, PID/workspace bounds and marker clipping.
22
+
23
+ ## 0.4.0 (M2)
24
+
25
+ - World format 0.3: workspace homes, typed mounts/frames/limits, reserved placement
26
+ volumes, camera-relative atmosphere, HDR bloom/exposure and static sky IBL.
27
+ - IPC 0.4: workspace bindings/focus, pull/place/return/recall, durable placement
28
+ rules, data-object bindings, atmosphere and FOV. Older wire contracts stay frozen.
29
+ - Added independent ownership/interaction/limits and version-isolation tests.
30
+
31
+ ## 0.5.0 (M3A)
32
+
33
+ Frozen IPC 0.5 adds revisioned interaction mode/tool state, workspace app metadata,
34
+ and custom surface pose/size placement rules. All prior schemas stay unchanged;
35
+ world format remains 0.3. Tests cover exact version isolation, closed objects,
36
+ bounded app/tool collections and complete custom placement records.
37
+
38
+ IPC 0.6 (M3B): independent input keymap v2, three variants per action, core-owned validated persistence and lease-bound capture; closed keymap/editor state, per-area paths and object transforms, scope FOV down to 3 degrees, Map opening intent. Older contracts remain byte-identical.
39
+
40
+ IPC 0.7 publishes the exact shell graphics handoff: discoverable presets/effects,
41
+ validated sparse `graphics.set`, effective settings and asynchronous GPU timings.
42
+ IPC 0.8 adds `keymap.holds` (monotonic start time and configured duration) for
43
+ shell-owned hold animation. Protocols through 0.7 retain their exact shapes;
44
+ world format remains 0.3. No compositor config reload is involved.
45
+
46
+ ## Climbing: world 0.4 and IPC 0.11
47
+
48
+ World 0.4 adds validated oriented climbable segments, climb-face normals,
49
+ feet-position exits, material type and optional speed. Runtime validates capsule
50
+ clearance against world collision. IPC 0.11 adds version-isolated movement
51
+ activity, ladder identity and interaction prompt fields. Previous versions stay
52
+ unchanged. See `test/climbing.test.mjs` and RFC-0004/0006.
53
+
54
+ ## IPC 0.12 — deterministic input and camera recordings
55
+
56
+ Extends frozen IPC 0.11 (climbing) with input.control-gated recording.start/stop/
57
+ mark/status and replay.start/stop/status, bounded assertion specs, and the
58
+ unbound record.toggle action in every input mode. Older keymaps are projected
59
+ without that action. Runtime records are private, versioned JSONL, with app
60
+ keystrokes masked by default. Replay uses a fixed 60 Hz clock; camera-only
61
+ replay never forwards input. Existing 0.11 movement activity remains inherited.
62
+
63
+ ## IPC 0.13 and world 0.5 — generic authoring and rendering controls
64
+
65
+ - Capability-gated photo-camera hold with normalized quaternion, 5–140° vertical
66
+ FOV, NDC lens shift and fixed render scale; camera.get reports actual lens state.
67
+ - Optional authored depth/normal ink style and Performance override/cost.
68
+ - Explicit visibility areas with bounds, scene-node subtrees and visibleFrom
69
+ lists. Unassigned geometry and cameras outside areas remain visible.
70
+ - Prior world and IPC schemas are unchanged; positive/negative tests cover the
71
+ new bounds, links, ownership and closed fields.
72
+
73
+ ## IPC 0.15 — tool slots, pocket queue and content sizing
74
+
75
+ Adds generic tool declarations, bounded pocket/client feedback, canonical shared
76
+ Primary/Secondary/Alternate/Cycle bindings and optional persistent placement
77
+ content dimensions. Earlier IPC schemas stay byte-for-byte frozen. World format
78
+ is unchanged (0.5).
79
+
80
+ ## World 0.7 — 2026-10-09
81
+
82
+ `v0.7/world.schema.json` (world.json shape as 0.6, `formatVersion: "0.7"`) and
83
+ `v0.7/common.schema.json` (0.6 definitions). New `scene` validation kind checks a
84
+ package's `scene.gltf` against its world format: 0.7 may require
85
+ `KHR_texture_basisu` (KTX2 material textures), `EXT_meshopt_compression` and
86
+ `KHR_mesh_quantization`, and must list those it uses in `extensionsRequired`;
87
+ lightmap textures stay PNG in every v0 format. Exports `atLeast()`,
88
+ `worldFormats` and `sceneExtensions()` so version gates are not hard-coded lists.
89
+ Inheritance test: every valid 0.6 document is valid as 0.7. IPC is unchanged.
90
+
91
+ ## IPC 0.16 — 2026-10-10
92
+
93
+ `v0.16/ipc.schema.json`: graphics `upscaler` setting (`fsr1` | `bilinear` |
94
+ null) in config, effective values, overrides, presets and `graphics.set`
95
+ patches; `session.hello` reports `0.16`. Inheritance test: every 0.15
96
+ definition exists in 0.16 and the graphics properties differ only by the new key.
97
+
98
+ ## IPC 0.17: debug capture notes
99
+
100
+ - `capture.annotate {captureId, note}` (shell.control): writes an optional note
101
+ (0..1000 code points, no control characters) into a debug capture's JSON and
102
+ the captures index. Result `{revision}`.
103
+ - `capture.taken {captureId, timestampMs, mode}` notification, sent to 0.17
104
+ shells when U (or the mode's capture binding) snapshots the world, before the
105
+ files are written.
106
+ - Everything else is inherited from 0.16 unchanged.
107
+
108
+ ## IPC 0.18: device-scaled offload power cap and offload device selection
109
+
110
+ - `offload_power_cap_w` in `graphicsConfig`/`graphicsPatch` is a number 20–1000
111
+ or `null` (was 20–100). `null`, the new default, is automatic: the battery
112
+ profile ceiling with a battery, otherwise 75 % of the offload GPU's enforced
113
+ power limit (80 W when the limit is unknown).
114
+ - New `offload_device`: `"auto"` (default) or the lowercase PCI address
115
+ (`domain:bus:device.function`, e.g. `0000:65:00.0`) of the GPU that runs the
116
+ offload renderer.
117
+ - `performance` (graphics.get/set) gains required `capSource` (`profile` |
118
+ `device` | `configured` | `fallback`) and `device` (`null` or `{pci, node,
119
+ name, enforcedLimitW, selection, drivesCompositor}`). `profile` is unchanged;
120
+ systems without a battery report `full-ac`.
121
+ - `session.hello` reports `0.18`. Everything else is inherited from 0.17
122
+ unchanged. Inheritance test: every 0.17 definition is identical except the
123
+ graphics properties (only the two offload keys differ), `performance` (only
124
+ the two new keys) and the hello protocol constant.
125
+
126
+ ## IPC 0.19: player settings, view bob and reticle
127
+
128
+ - `player.get {}` (state.read) and `player.set {patch}` (movement.control) return
129
+ `playerSettings {config, defaults, overrides, options, ranges, path, error}`.
130
+ `playerConfig` keys: `walk_speed`, `run_speed`, `view_bob`
131
+ (`off|subtle|normal`), `reticle_style`, `reticle_size`, `reticle_thickness`,
132
+ `reticle_gap`, `reticle_opacity`, `reticle_outline`, `reticle_colour`
133
+ (`"theme"` or RGB), `reticle_dynamic`, `reach_grab`, `reach_mount`,
134
+ `reach_placement`. `playerPatch` takes any subset (at least one key); `null`
135
+ removes a persisted override. `overrides` uses `playerOverrides` (the same
136
+ keys, never null, may be empty).
137
+ - `graphics` `fov` accepts 30..120 (was 30..110) in config and patches.
138
+ - `overlayStyle` gains `reticleColor`, `validColor` and `invalidColor` (RGB
139
+ 0..1; required in the result, optional in the params patch).
140
+ - `interaction.reticle {state, action}` (required): what the reticle shows
141
+ (`hidden|neutral|typing|target|valid|out_of_range|invalid|holding`) and the
142
+ action it would take (`""|click|grab|pocket|place|mount|select|path|drop`).
143
+ - Everything else is inherited from 0.18 unchanged, including the offload cap
144
+ and device keys; `session.hello` reports `0.19`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hyprune contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,141 @@
1
- # Temporary Holding Version
1
+ # Hyprune schemas · v0
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > **Hyprune** is an explorable, world-driven desktop environment for Hyprland: your workspaces become places you can walk through, with live windows on the walls. This repository holds the versioned **schemas** for world packages, IPC and manifests, and their validator. Install Hyprune through the [hyprune](https://github.com/hyprune/hyprune) repository (starter kits, Nix, Arch); learn more at [hyprune.com](https://hyprune.com). Licence: MIT.
4
+
5
+ Versioned contracts for Hyprune, a world-driven Hyprland desktop: world packages (formats 0.1–0.7), the IPC protocol (0.1–0.19), extension and screen-type manifests and the input keymap. JSON Schema dialect: **2020-12**. Every version is frozen once published; core, the shell and the SDK pin these exact files. Readable reference: [hyprune.com/reference/schema](https://hyprune.com/reference/schema/).
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ npm i -D @hyprune/schema
11
+ npx hyprune-validate world world.json - 0.7 # a world package manifest
12
+ npx hyprune-validate scene scene.gltf - 0.7 world.json # its glTF against the world format
13
+ ```
14
+
15
+ ```js
16
+ import { validate, worldFormats } from '@hyprune/schema';
17
+ import schema from '@hyprune/schema/v0.7/world.schema.json' with { type: 'json' };
18
+
19
+ const result = validate('world', manifest, undefined, worldFormats.at(-1));
20
+ if (!result.valid) console.error(result.errors.join('\n'));
21
+ ```
22
+
23
+ Every schema file is importable at `@hyprune/schema/v0.N/<name>.schema.json` (`v0/` holds the 0.1 contracts). For a full world authoring workflow (validate, pack, scaffold) use [`@hyprune/sdk`](https://github.com/hyprune/sdk).
24
+
25
+ | Schema | Contract |
26
+ | --- | --- |
27
+ | `v0/world.schema.json` | Data-only manifest, glTF entry, spawns, anchors, zones, navigation, collision, audio, lightmaps and provenance. |
28
+ | `v0/ipc.schema.json` | JSON-RPC request/response/error envelope, all 12 core methods with typed params/results, 3 notifications and state. |
29
+ | `v0/extension.schema.json` | Process entrypoint, contributions, requested grants and mandatory sandbox profile. |
30
+ | `v0/screen-type.schema.json` | Source kind, planar geometry, resolution, color/alpha, refresh ceiling and input support. |
31
+ | `v0/common.schema.json` | Shared IDs, versions, paths, poses, revisions and capabilities. |
32
+
33
+ [RFC source](https://github.com/hyprune/docs/tree/main/src/content/docs/rfcs) is normative for semantics. [RFC-0003](https://hyprune.com/rfcs/0003-ipc/) defines IPC; [RFC-0004](https://hyprune.com/rfcs/0004-world-format/) defines worlds. The `$id` URLs are mirrored by docs for authoring; this validator registers all schemas locally and never fetches them.
34
+
35
+ ## Validate
36
+
37
+ Use Node >=22.12 (CI pins 24.14.0), npm, and the committed lockfile:
38
+
39
+ ```sh
40
+ npm ci
41
+ npm test
42
+ npm run validate -- world examples/world.json
43
+ npm run validate -- extension examples/extension.json
44
+ npm run validate -- screen-type examples/screen-type.json
45
+ npm run validate -- ipc examples/ipc/state.delta.notification.json
46
+ npm run validate -- ipc examples/ipc/session.ping.response.json session.ping
47
+ cat examples/world.json | npm run validate -- world -
48
+ ```
49
+
50
+ Exit 0 = valid, 1 = contract violation, 2 = usage/read/parse failure. The CLI accepts one JSON document up to 1 MiB. Optional method context validates a response against the outstanding request's method, since JSON-RPC responses do not repeat method names. Error responses should be validated as envelopes without a success-method context. Clients must also correlate the response ID themselves.
51
+
52
+ **Why Node:** the docs toolchain already needs it, Ajv supports draft 2020-12 with strict compilation, and JavaScript matches the reference shell/SDK direction. The CLI adds no global install and uses pinned Ajv and SPDX parser dependencies. Python would add a second tool environment here.
53
+
54
+ ## Scope and limits
55
+
56
+ Schemas reject unknown fields outside explicit extension maps. The validator adds manifest-local semantic checks: duplicate IDs/material bindings, default spawn references, normalized quaternions, AABB ordering, SPDX expressions, required extension presence, contribution namespaces, advancing deltas and overlay/lease invariants.
57
+
58
+ This is not a runtime transport parser or package installer. It does not check duplicate JSON keys (JSON.parse retains the last), transport framing/depth/session ordering, live grants, asset existence/rights, attribution coverage, glTF indices/UV1, symlinks, archives, codecs, collision or spawn clearance. RFC-0002/0003/0004 require those checks in core and the future SDK. Do not use a passing manifest as proof a package is safe to execute or load.
59
+
60
+ `examples/world.json` is an original synthetic manifest exercising metadata; referenced scene/audio files are intentionally not supplied. It is not a playable package. IPC fixtures cover every request, success result, notification and an error; they are independent shape examples, not a chronological authenticated session. Tokens are omitted, so hello demonstrates negotiation shape, not privileged authentication.
61
+
62
+ ## Evolving contracts
63
+
64
+ Update RFC + schema + positive/negative tests + [CHANGELOG.md](CHANGELOG.md) together. Consumers pin a schema commit/release. New structural or semantic contracts get a new protocol/format identifier; never quietly redefine a released one. docs mirrors these exact files with a recorded source commit and checksums. M0/WIP commits are deliberately available before implementation.
65
+
66
+ MIT; see [LICENSE](LICENSE).
67
+
68
+ M1 contracts are frozen separately under `v0.2/`. Select them explicitly:
69
+
70
+ ```js
71
+ validate('ipc', frame, responseMethod, '0.2');
72
+ validate('world', manifest, undefined, '0.2');
73
+ ```
74
+
75
+ CLI: `npm run validate -- world world.json - 0.2`. Existing default calls continue validating 0.1. Wire protocol and package format versions are independent.
76
+
77
+ First-session IPC `0.3` lives in `v0.3/{common,ipc}.schema.json` and is selected with
78
+ `validate('ipc', frame, method, '0.3')`. It adds verified shell-child binding,
79
+ workspace locations and bounded map/projection/output descriptors. World format
80
+ selection remains 0.1/0.2; optional Map metadata is documented in RFC-0004/0008.
81
+
82
+ ## M3A contract
83
+
84
+ `v0.5/ipc.schema.json` adds hands-on interaction and workspace app state, plus
85
+ custom pose placements. Select version `0.5` explicitly; earlier contracts and
86
+ world format 0.3 remain frozen. App icons are theme names, not arbitrary URLs.
87
+
88
+ IPC **0.12** adds recording/replay control and `record.toggle`; 0.11 remains the
89
+ climbing contract. Both inherit the 0.10 Performance API. Record/replay mutations
90
+ require `input.control`; ordinary observers cannot start capture or replay.
91
+
92
+ IPC **0.13** adds dev-only `camera.author` grants (`camera.photo`/`camera.release`),
93
+ actual camera roll/FOV/lens shift, and Performance controls for ink and visibility.
94
+ World **0.5** adds optional `atmosphere.outline` and directed visibility regions.
95
+ Older schemas remain frozen. Photo grants are not part of a normal shell grant.
96
+
97
+ IPC **0.14** adds nullable `graphics.outline_quality` (`fast` or `smooth`).
98
+ Fast keeps a one-logical-pixel stroke; smooth honours the world's 1–4 px width.
99
+ Low/Medium inherit fast, High/Ultra smooth. This is a graphics-only revision;
100
+ world format remains 0.5 and previous IPC schemas remain frozen.
101
+
102
+ 0.14 also adds nullable `outline_width_px` (1–4) and `outline_colour` (three
103
+ 0–1 display RGB values). These are persistent user graphics overrides; null means
104
+ use the current world's authored style. The revision-response envelope uses
105
+ `anyOf` so shared `{revision:...}` responses are unambiguous; per-method validation
106
+ still supplies the result type.
107
+
108
+ World format **0.6** adds optional `playable` eye-position volumes (boxes or convex
109
+ hulls), per-area regions and maximum fly height, plus explicit `backdrop.farCards`
110
+ node declarations. IPC remains 0.15; authoring geometry is not added to IPC area
111
+ records. See RFC-0004 for composition, limits and motion semantics.
112
+
113
+ World format **0.7** keeps the 0.6 world.json shape and allows compressed and
114
+ optimised scene assets: `KHR_texture_basisu` (KTX2, material textures only),
115
+ `EXT_meshopt_compression` and `KHR_mesh_quantization`. Lightmaps stay PNG.
116
+ `validate('scene', gltf, undefined, worldFormat, {world})` (CLI:
117
+ `npm run validate -- scene scene.gltf - 0.7 world.json`) checks
118
+ `extensionsRequired` and lightmap textures against the world format. Version
119
+ gates use `atLeast()`; see RFC-0004 "world 0.7".
120
+
121
+ IPC **0.16** adds the `upscaler` graphics key (`"fsr1"`, `"bilinear"` or `null` to
122
+ inherit the preset) to `graphicsConfig`/`graphicsPatch`. Every 0.15 definition is
123
+ otherwise unchanged; earlier schemas stay frozen. See RFC-0003/0008 amendments.
124
+
125
+ IPC **0.17** adds debug capture notes: the `capture.taken` notification (capture ID,
126
+ time and input mode, sent to shells) and `capture.annotate {captureId, note}`
127
+ (shell.control; 0-1000 code points, no control characters). Every 0.16 definition
128
+ is unchanged. See the RFC-0008 amendment "IPC 0.17 capture notes".
129
+
130
+ IPC **0.18** scales the offload power cap to the device: `offload_power_cap_w`
131
+ accepts 20-1000 W or `null` (automatic, the new default), and the new
132
+ `offload_device` key is `"auto"` or a lowercase PCI address. `performance` reports
133
+ where its cap comes from (`capSource`) and the chosen GPU (`device`, or `null`).
134
+ Every 0.17 definition is otherwise unchanged. See the RFC-0009 amendment
135
+ "IPC 0.18 device-scaled offload power and device selection".
136
+
137
+ IPC **0.19** adds player settings (`player.get`/`player.set`: walk/run speed, view
138
+ bob, reticle style/size/colour and reach limits), widens graphics `fov` to 30-120,
139
+ adds `reticleColor`/`validColor`/`invalidColor` to the overlay style and the
140
+ required `interaction.reticle {state, action}`. Every other 0.18 definition is
141
+ unchanged. See the RFC-0006 amendment "IPC 0.19 player settings and reticle".
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from 'node:fs';
3
+ import { validate } from '../lib/validate.mjs';
4
+ const [kind, file, method, version, worldFile, ...extra] = process.argv.slice(2);
5
+ if (!kind || !file || extra.length || (worldFile && kind !== 'scene')) {
6
+ console.error('Usage: hyprune-validate <world|extension|screen-type|ipc> <file.json|-> [response-method|-] [contract-version]\n' +
7
+ ' hyprune-validate scene <scene.gltf> - <world-format> <world.json>\n(in this repository: npm run validate -- ...)');
8
+ process.exitCode = 2;
9
+ } else {
10
+ try {
11
+ const bytes = readFileSync(file === '-' ? 0 : file);
12
+ if (bytes.length > 1_048_576) throw new Error('Document exceeds 1 MiB');
13
+ const value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
14
+ const world = worldFile ? JSON.parse(readFileSync(worldFile, 'utf8')) : undefined;
15
+ const result = validate(kind, value, method === '-' ? undefined : method, version, { world });
16
+ if (result.valid) console.log(`VALID ${kind}: ${file}`);
17
+ else { console.error(result.errors.join('\n')); process.exitCode = 1; }
18
+ } catch (error) { console.error(error.message); process.exitCode = 2; }
19
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "manifestVersion": "0.1",
3
+ "id": "com.hyprune.clock",
4
+ "version": "0.1.0",
5
+ "name": "World clock",
6
+ "license": "MIT",
7
+ "apiVersion": "0.1",
8
+ "runtime": "process",
9
+ "entrypoint": "bin/clock",
10
+ "capabilities": [
11
+ "state.read"
12
+ ],
13
+ "contributes": {
14
+ "widgets": [
15
+ "com.hyprune.clock.widget"
16
+ ]
17
+ },
18
+ "sandbox": {
19
+ "required": true,
20
+ "network": false
21
+ }
22
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "1",
4
+ "error": {
5
+ "code": -32002,
6
+ "message": "Capability denied.",
7
+ "data": {
8
+ "retryable": false
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "8",
4
+ "method": "movement.set",
5
+ "params": {
6
+ "modeId": "com.hyprune.fly"
7
+ }
8
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "8",
4
+ "result": {
5
+ "revision": 1
6
+ }
7
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "12",
4
+ "method": "runtime.exit",
5
+ "params": {}
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "12",
4
+ "result": {
5
+ "revision": 1
6
+ }
7
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "method": "runtime.notice",
4
+ "params": {
5
+ "level": "info",
6
+ "code": "world.ready",
7
+ "message": "World ready."
8
+ }
9
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "1",
4
+ "method": "session.hello",
5
+ "params": {
6
+ "protocols": [
7
+ "0.1"
8
+ ],
9
+ "client": {
10
+ "id": "com.hyprune.shell",
11
+ "name": "Hyprune shell"
12
+ },
13
+ "capabilities": [
14
+ "state.read"
15
+ ]
16
+ }
17
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "1",
4
+ "result": {
5
+ "protocol": "0.1",
6
+ "sessionId": "session-1",
7
+ "capabilities": [
8
+ "state.read"
9
+ ],
10
+ "methods": [
11
+ "session.hello",
12
+ "session.ping",
13
+ "state.subscribe",
14
+ "state.snapshot",
15
+ "state.unsubscribe"
16
+ ],
17
+ "events": [
18
+ "state.delta",
19
+ "runtime.notice",
20
+ "session.revoked"
21
+ ]
22
+ }
23
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "2",
4
+ "method": "session.ping",
5
+ "params": {}
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "2",
4
+ "result": {
5
+ "monotonicMs": 1000
6
+ }
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "method": "session.revoked",
4
+ "params": {
5
+ "reason": "Grant revoked."
6
+ }
7
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "9",
4
+ "method": "shell.claim",
5
+ "params": {
6
+ "outputs": [
7
+ "output-1"
8
+ ]
9
+ }
10
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "9",
4
+ "result": {
5
+ "leaseId": "lease-1",
6
+ "revision": 1
7
+ }
8
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "11",
4
+ "method": "shell.overlay",
5
+ "params": {
6
+ "leaseId": "lease-1",
7
+ "outputId": "output-1",
8
+ "visible": true,
9
+ "exclusiveInput": true
10
+ }
11
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "11",
4
+ "result": {
5
+ "revision": 1
6
+ }
7
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "10",
4
+ "method": "shell.release",
5
+ "params": {
6
+ "leaseId": "lease-1"
7
+ }
8
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "10",
4
+ "result": {
5
+ "revision": 1
6
+ }
7
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "method": "state.delta",
4
+ "params": {
5
+ "subscriptionId": "sub-1",
6
+ "sessionId": "session-1",
7
+ "baseRevision": 0,
8
+ "revision": 1,
9
+ "changes": {
10
+ "runtime": {
11
+ "active": true,
12
+ "outputs": [
13
+ "output-1"
14
+ ]
15
+ }
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "4",
4
+ "method": "state.snapshot",
5
+ "params": {
6
+ "subscriptionId": "sub-1"
7
+ }
8
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "4",
4
+ "result": {
5
+ "snapshot": {
6
+ "sessionId": "session-1",
7
+ "revision": 0,
8
+ "state": {
9
+ "runtime": {
10
+ "active": false,
11
+ "outputs": [
12
+ "output-1"
13
+ ]
14
+ },
15
+ "world": null,
16
+ "surfaces": [],
17
+ "movement": {
18
+ "modeId": "com.hyprune.fly",
19
+ "position": [
20
+ 0,
21
+ 1,
22
+ 0
23
+ ],
24
+ "orientation": [
25
+ 0,
26
+ 0,
27
+ 0,
28
+ 1
29
+ ]
30
+ },
31
+ "shell": {
32
+ "leases": []
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "jsonrpc": "2.0",
3
+ "id": "3",
4
+ "method": "state.subscribe",
5
+ "params": {
6
+ "topics": [
7
+ "state"
8
+ ]
9
+ }
10
+ }