@hyprune/schema 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -434,3 +434,32 @@ Draft only; no version changes. `v0.10/object.schema.json` and the validator:
434
434
  ## @hyprune/schema 0.9.0 (2026-10-13)
435
435
 
436
436
  Publishes IPC 0.24: `objects.catalog` entries carry a placed machine's declared inputs (`machine`), and a new `live` state key reports each placed machine's source, status and per-input values (published only on change). Inherited from 0.23 otherwise; no new grant. Also the object 0.10 draft additions for gauges: the `average` mapping modifier, `levels` slots (fill/slide with spring) and stack rate, cap 100 and signed spacing.
437
+
438
+ ## IPC 0.25 (draft): companions (RFC-0010 companions amendment)
439
+
440
+ - Methods (grant `objects.control`): `companion.set {ref}` (a companion-capable
441
+ library or user catalog ref), `companion.clear {}` and `companion.mode {mode:
442
+ follow|stay}`; each returns `{revision}`. Existing methods take the reserved
443
+ object id `companion`: `npcs.bind` (a route or a standing spot), `paths.draw
444
+ {bind}` and `interaction.choose`. No new grant, no new event.
445
+ - Required state key `companion {ref|null, name|null (<=32), state
446
+ (none|loading|unavailable|active|waiting|hidden), reason|null (<=64), mode
447
+ (follow|stay|route), path|null (qualified path ref), activity|null
448
+ (following|walking|running|idle|talking|sitting|waiting|carried),
449
+ position|null, carried}`.
450
+ - `objects.catalog` entries gain required `companion`: null, or `{capable,
451
+ name, reason|null}`.
452
+ - `npcs.aimed.interactions[].type` gains `companion` (Stay and Follow).
453
+ - Everything else is inherited from 0.24 unchanged; `session.hello` reports
454
+ `0.25`. Inheritance test included.
455
+
456
+ ## Object format 0.10 (draft): companion block
457
+
458
+ - Optional `companion {name? (1-32), followDistance? (1.5-2.5 m), idles?
459
+ (<=4 unique clip names), say? (<=8 lines of <=160 characters)}`, only on
460
+ characters; idle variants must be clips of `traits.character` and not
461
+ canonical RFC-0010 clip names (`talk` is a new canonical name).
462
+
463
+ ## @hyprune/schema 0.10.0 (2026-10-13)
464
+
465
+ Publishes IPC 0.25: companions. `companion.set`, `companion.clear` and `companion.mode` (follow or stay), a required `companion` state key, a companion capability on catalog entries and the aimed interaction type `companion`; and the object 0.10 draft `companion` block (name, followDistance, idles, say). Inherits 0.24.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
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
4
 
5
- Versioned contracts for Hyprune, a world-driven Hyprland desktop: world packages (formats 0.1–0.9), the IPC protocol (0.1–0.24), object and library manifests (0.9, draft 0.10), 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/).
5
+ Versioned contracts for Hyprune, a world-driven Hyprland desktop: world packages (formats 0.1–0.9), the IPC protocol (0.1–0.25, 0.25 draft), object and library manifests (0.9, draft 0.10), 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
6
 
7
7
  ## Install
8
8
 
@@ -212,6 +212,13 @@ raw value, condition (`fresh`, `stale`, `missing`, `error`) and `publishedAt`
212
212
  grant; every other 0.23 definition is unchanged. See the RFC-0013 amendment
213
213
  "Live state in IPC 0.24".
214
214
 
215
+ IPC **0.25** (draft, the RFC-0010 companions amendment) adds the companion: a
216
+ required `companion` state key (the chosen ref and name, its state, mode
217
+ `follow`/`stay`/`route`, bound path, activity and position), a `companion`
218
+ capability on catalog entries, the aimed interaction type `companion`, and
219
+ `companion.set/clear/mode` (objects.control). Object format 0.10 (draft) gains
220
+ the optional `companion` block. Every other 0.24 definition is unchanged.
221
+
215
222
  ## Objects and libraries (RFC-0011)
216
223
 
217
224
  Object manifests (`object.json`) and library manifests (`library.json`) use the
package/lib/validate.mjs CHANGED
@@ -423,6 +423,8 @@ function validateMachine(value, fail) {
423
423
  function traitCombinations(names, fail) {
424
424
  for (const a of names) for (const c of names) if (a < c && !(traitPairs[a] || []).includes(c)) fail(`traits: ${a} and ${c} can't be combined`);
425
425
  }
426
+ // RFC-0010 canonical character clip names (talk: the companions amendment).
427
+ const canonicalClips = ['idle', 'idle_fidget', 'walk', 'run', 'turn_left', 'turn_right', 'look_around', 'wave', 'nod', 'sit', 'sit_idle', 'stand', 'talk'];
426
428
  function objectTraitRules(traits, slots, fail, inside = () => {}) {
427
429
  const quat = (q, where) => { if (Math.abs(Math.hypot(...q) - 1) > 0.002) fail(`${where}: quaternion must be normalized`); };
428
430
  const unique = (items, field, label) => { const ids = items.map(v => v[field]); if (new Set(ids).size !== ids.length) fail(`${label}: duplicate ${field}`); };
@@ -473,6 +475,14 @@ function validateObjectManifest(value, version, options, fail, warn) {
473
475
  const traits = value.traits, slots = value.slots || {}, names = Object.keys(traits), b = value.bounds;
474
476
  if (options.directory !== undefined && options.directory !== value.id) fail(`id: "${value.id}" differs from its directory "${options.directory}"`);
475
477
  traitCombinations(names, fail);
478
+ // Companion block (object format 0.10 draft, RFC-0010 companions amendment).
479
+ if (value.companion) {
480
+ if (!traits.character) fail('companion: only characters can be companions');
481
+ else for (const clip of value.companion.idles || []) {
482
+ if (!(clip in traits.character.clips)) fail(`companion: idle variant "${clip}" is not a clip of traits.character`);
483
+ if (canonicalClips.includes(clip)) fail(`companion: "${clip}" is a canonical clip, not an idle variant`);
484
+ }
485
+ }
476
486
  for (let j = 0; j < 3; j++) if (b.min[j] >= b.max[j]) fail(`bounds: min ${'xyz'[j]} must be below max`);
477
487
  const t = objectLimits.boundsTolerance, surfaces = new Set(traits.movable ? traits.movable.surfaces || ['floor'] : []);
478
488
  const one = surfaces.size === 1 ? [...surfaces][0] : undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyprune/schema",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Versioned JSON Schemas for Hyprune world packages and the IPC protocol, with a validator and CLI for world authors",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -647,6 +647,45 @@
647
647
  "additionalProperties": false,
648
648
  "description": "Trait name to trait data. Unknown or reserved names reject the object."
649
649
  },
650
+ "companion": {
651
+ "type": "object",
652
+ "properties": {
653
+ "name": {
654
+ "type": "string",
655
+ "minLength": 1,
656
+ "maxLength": 32,
657
+ "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
658
+ },
659
+ "followDistance": {
660
+ "type": "number",
661
+ "minimum": 1.5,
662
+ "maximum": 2.5
663
+ },
664
+ "idles": {
665
+ "type": "array",
666
+ "items": {
667
+ "type": "string",
668
+ "minLength": 1,
669
+ "maxLength": 64,
670
+ "pattern": "^[a-z][a-z0-9_]*$"
671
+ },
672
+ "maxItems": 4,
673
+ "uniqueItems": true
674
+ },
675
+ "say": {
676
+ "type": "array",
677
+ "items": {
678
+ "type": "string",
679
+ "minLength": 1,
680
+ "maxLength": 160,
681
+ "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
682
+ },
683
+ "maxItems": 8
684
+ }
685
+ },
686
+ "additionalProperties": false,
687
+ "description": "Companion settings (RFC-0010 companions amendment, draft): display name, follow distance, idle variants (clips of traits.character) and Talk lines. Characters only."
688
+ },
650
689
  "slots": {
651
690
  "type": "object",
652
691
  "properties": {