@idle-screens/schema 3.8.0 → 3.9.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/FORMAT.md CHANGED
@@ -678,6 +678,9 @@ interpolation, and background drift is sampled at rest. These are documented
678
678
  trade-offs for a zero-dependency, renderer-free analysis tool.
679
679
 
680
680
  - `perceiveScene(spec, {t?, viewport?, seed?})` — one-call bundle: everything below.
681
+ **`t` is in milliseconds** (the MCP `previewScene` tool takes seconds and
682
+ converts; passing seconds here reads a self-typing block as one that never
683
+ finishes typing).
681
684
  - `perceiveSequenceFrame(seq, T, {viewport?, seed?, releasedBelow?})` — the
682
685
  same bundle for one frame of a **sequence** at global time `T`: resolves the
683
686
  segment (reported as `segment: {index, key, localT, held?}`) and, when the
package/dist/index.d.ts CHANGED
@@ -1894,6 +1894,14 @@ declare function segmentRenderSeed(seq: IdleSequence, index: number): number | u
1894
1894
  * `SpecInstance`. `undefined` when there's no bed or no derivable seed.
1895
1895
  */
1896
1896
  declare function bedRenderSeed(seq: IdleSequence): number | undefined;
1897
+ /**
1898
+ * Whether any scene in the sequence — the sequence itself or any segment —
1899
+ * declares a `finish`. Mirrors `SequenceInstance`'s construction-time check:
1900
+ * a finish anywhere allocates the presentation pass for the instance's whole
1901
+ * lifetime, so this is also what `sequenceSwapCompatible` must agree on
1902
+ * before and after a swap.
1903
+ */
1904
+ declare function sequenceWantsFinish(seq: IdleSequence): boolean;
1897
1905
  /**
1898
1906
  * Whether a republished sequence can be swapped into a live
1899
1907
  * `SequenceInstance` in place of `prev` without a remount
@@ -1909,6 +1917,15 @@ declare function bedRenderSeed(seq: IdleSequence): number | undefined;
1909
1917
  * the next boundary, leaving the room half-swapped;
1910
1918
  * - a `bed` on both sides or neither, structural twins with the same seed
1911
1919
  * when present;
1920
+ * - the same top-level `seq.seed`, compared normalized (like the mount-time
1921
+ * seed itself) so a change of an exact multiple of 2^32 isn't flagged —
1922
+ * even when every segment and the bed resolve their own seed (so
1923
+ * `segmentRenderSeed`/`bedRenderSeed` are unaffected), a sequence-level
1924
+ * `finish` grain resolves against the instance's mount-time seed
1925
+ * (`frameFinishSeed`), which a swap cannot update;
1926
+ * - the same finish presence (`sequenceWantsFinish`) — the presentation
1927
+ * pass is allocated once at construction, so a swap that adds or removes
1928
+ * every `finish` in the sequence cannot (de)allocate it;
1912
1929
  * - the same `loop` and `sync` (absent `sync` is `'mount'`);
1913
1930
  * - the same `duration`, `advance` (absent is `'auto'`) and `transition`
1914
1931
  * (absent is `cut`; `text` on a morph defaults to `'step'`) on every
@@ -2114,6 +2131,160 @@ declare const WARP_TUNNEL_SPEC: SaverSpec;
2114
2131
  */
2115
2132
  declare const THERMAL_FIELD_SPEC: SaverSpec;
2116
2133
 
2134
+ /**
2135
+ * Sparse Night — emptiness, declared as intent.
2136
+ * A star-grain field (radius under 0.001 — the rung FORMAT.md's ladder calls
2137
+ * texture, never the subject) over near-black, one faint linked pentagon as
2138
+ * the only figure, and a single satellite that flares for three seconds out of
2139
+ * every eighteen. Measured coverage sits around one percent, which `adviseSpec`
2140
+ * would flag as `sparse-scene` at every legal count — the spec's
2141
+ * `density: 'sparse'` declaration is the point of this example: it withholds
2142
+ * that advisory AND opts the scene into `density-mismatch` instead, so the
2143
+ * emptiness is a claim the perception API checks rather than a gap it nags
2144
+ * about. Before `density` shipped, restraint like this could not pass advise
2145
+ * clean; the one-mark house style sat at the suite floor for exactly this
2146
+ * reason.
2147
+ */
2148
+ declare const SPARSE_NIGHT_SPEC: SaverSpec;
2149
+
2150
+ /**
2151
+ * Typed Cue — textBlock.reveal, both moods.
2152
+ * Two self-typing captions over near-black. The upper one types at ten
2153
+ * graphemes a second with a blinking caret (`mode: 'typewriter'` — the classic
2154
+ * terminal reveal; `speed` makes progress a pure function of scene time, so
2155
+ * every viewer types the same line on the same clock from its own mount). The
2156
+ * lower one arrives as a wave of overlapping fades (`mode: 'glyphFade'`,
2157
+ * `fade: 0.4` — each glyph ramps in over 40% of the progress window, which
2158
+ * reads as a soft dissolve rather than typing) and carries no caret. Both
2159
+ * blocks declare `opacity` so the path is steerable, and layout always runs on
2160
+ * the FULL text — reveal only masks glyphs, so lines never reflow mid-type.
2161
+ *
2162
+ * Trap, documented in the playbook and true here too: at t = 0 a self-typing
2163
+ * block has typed nothing, so `previewScene` at the default instant looks
2164
+ * empty — preview at t ≥ 10 s to see the words. To swap the line live, glide
2165
+ * `reveal.progress` to 0, step the `text`, glide back (one `setTrack` call).
2166
+ *
2167
+ * The scan band is the one non-text layer, and it is load-bearing twice over:
2168
+ * a screensaver of two static text blocks is a document, not a screensaver
2169
+ * (`text-heavy`), and the band gives the words something to sit on — a slow
2170
+ * refresh sweep passing under the type. Note the units: `perceiveScene` takes
2171
+ * `t` in MILLISECONDS while the MCP `previewScene` tool takes seconds (the
2172
+ * worker converts); passing seconds to the library reads as a block that
2173
+ * never finishes typing.
2174
+ */
2175
+ declare const TYPED_CUE_SPEC: SaverSpec;
2176
+
2177
+ /**
2178
+ * Signal Board — the instrument panel, laid out by the format.
2179
+ * A 3×3 table of data bars with their labels in a matching table, one
2180
+ * monospace caption, and a phosphor sweep crossing the frame every ~90
2181
+ * seconds. The teaching layer is `layout: { type: 'table', columns: 3 }`:
2182
+ * nine bars and nine labels are TWO layers, not eighteen positioned blocks —
2183
+ * entity i reads `values[i]` / `strings[i]` in reading order, and each bar
2184
+ * draws `length × values[i] / max` from its cell. `values` are paint, so
2185
+ * `setParam("readout.sprite.values", [...])` glides every bar at once, which
2186
+ * is the whole point of the shape: a live readout that never re-publishes.
2187
+ */
2188
+ declare const SIGNAL_BOARD_SPEC: SaverSpec;
2189
+
2190
+ /**
2191
+ * Phase Duet — three layers on one clock.
2192
+ * A grid of sixty dots ripples as a traveling wave (`pulse.wave`), three rings
2193
+ * swell, and one soft heart breathes — and none of them drift apart, because
2194
+ * all three declare the same `clock`. `clock` is the format's answer to
2195
+ * coincidence: without it, `pulse`, `grow` and `cycle` run on per-entity
2196
+ * seeded phases, so two layers with the same period never line up (they are
2197
+ * a room full of people, not a duet). With one shared `clock: { phase: 0,
2198
+ * rate: 1 }` they breathe in step and stay there — period ÷ rate must stay
2199
+ * ≥ 1000 ms, which is why every layer here runs a 6000 ms cycle.
2200
+ */
2201
+ declare const PHASE_DUET_SPEC: SaverSpec;
2202
+
2203
+ /**
2204
+ * Web Work — a randomised graph that fades with distance.
2205
+ * Forty-four drifting nodes wired `mode: 'random'` (a fixed deterministic
2206
+ * wiring, not k-nearest — the difference is topology: nearest gives
2207
+ * crystalline clusters, random gives a web that crosses itself) with
2208
+ * `falloff: true`, so an edge's alpha fades toward `maxDist` instead of
2209
+ * popping in at the cutoff. The second layer is a row of `orient: true`
2210
+ * strokes: the mark's +x axis turns to follow the entity's heading, so each
2211
+ * one reads as a wind tick rather than a stamp. Both are the difference
2212
+ * between "lines between dots" and a drawing.
2213
+ */
2214
+ declare const WEB_WORK_SPEC: SaverSpec;
2215
+
2216
+ /**
2217
+ * Shard Fall — tumbling shapes and a passing shadow.
2218
+ * Two features nothing else here uses. `rotate` is STATIC per-entity rotation
2219
+ * (a range seeded per entity), which is not the same as `spin: [0, 0]` — a
2220
+ * zero spin speed renders the seeded start angle as 0, so "tilted but not
2221
+ * turning" was previously inexpressible; here the shards are thrown at
2222
+ * `rotate: [-180, 180]` AND tumbling on their own `spin` range, so no two
2223
+ * facets agree on an angle. The shadow layer demonstrates `blend:
2224
+ * 'multiply'`: two large soft discs darkening a pale plate as they wander,
2225
+ * which is how the format does shadow and silhouette — `lighter` adds light,
2226
+ * `multiply` removes it, and neither needs a sprite that looks like darkness.
2227
+ * The polygons use `points` (unit coordinates scaled by `radius`), which are
2228
+ * paint, so two shards with the same point count will morph into each other.
2229
+ */
2230
+ declare const SHARD_FALL_SPEC: SaverSpec;
2231
+
2232
+ /**
2233
+ * Murmur — a flock with no birds in it.
2234
+ * Six hundred and twenty entities: two registers of streaks (260 each) on
2235
+ * harmonic `wander` with `coherence` near 1, so each layer folds and wheels as
2236
+ * one body, and a static grain layer behind them. Nothing here
2237
+ * interacts — no entity reads another's position — which is the trick the
2238
+ * format is built on: a shared harmonic set plus a wide speed range reads as
2239
+ * a murmuration while staying a pure function of (seed, t), so it replays
2240
+ * identically and seeks instantly. `density: 'dense'` is doing real work:
2241
+ * past 500 entities `adviseSpec` raises `dense-scene`, and the declaration
2242
+ * says the crowding is the subject rather than a mistake — while still opting
2243
+ * into `density-mismatch` if the scene ever measures as empty instead.
2244
+ */
2245
+ declare const MURMUR_SPEC: SaverSpec;
2246
+
2247
+ /**
2248
+ * Three Movements — one ground, three scenes, two kinds of transition.
2249
+ *
2250
+ * The sequence envelope, exercised end to end:
2251
+ *
2252
+ * - **bed.** A drifting field with a few motes, drawn under every segment on
2253
+ * the SEQUENCE clock — it does not reset at a boundary and a
2254
+ * `sequence.segment` steer cannot rewind it. That is the fix for the
2255
+ * boundary rewind every ambient sequence suffers: put the motion that must
2256
+ * be continuous in the bed, the slide content in the segments. (Segments
2257
+ * deliberately declare no `background`: over a bed it is never painted on
2258
+ * the web, and the validator warns `bed-hides-segment-background` — the
2259
+ * native tvOS player, which ignores the bed, will show them over black
2260
+ * until it learns the field. Prefer a bed the piece can survive without.)
2261
+ * - **morph + text crossfade.** Segments 1 → 2 are structural twins differing
2262
+ * only in colour and words, so the transition can MORPH: every numeric and
2263
+ * hex value glides over 2500 ms, and because the words differ and the
2264
+ * transition declares `text: 'crossfade'`, the outgoing caption fades under
2265
+ * the incoming one instead of switching whole-frame. Without the crossfade
2266
+ * declaration a morph steps strings on its first frame — it reads as a cut
2267
+ * and the validator says `morph-nothing-morphable`.
2268
+ * - **fade.** Segments 2 → 3 have nothing structurally in common, so a morph
2269
+ * is impossible and a `fade` is the honest transition: the outgoing scene
2270
+ * keeps animating on its own canvas for 3000 ms while the incoming one
2271
+ * fades up. The cost is two live segments during the window, which is why
2272
+ * the lowest capability tier degrades a fade to a cut
2273
+ * (`fade-degrades-on-low-tier` — informational, and this sequence keeps the
2274
+ * fade because the web and native players both honour it).
2275
+ * - **finish.** One grain-and-dither pass over the composed frame — bed,
2276
+ * segment and any fade together — the sequence-level screen no segment can
2277
+ * override.
2278
+ *
2279
+ * The final segment carries no duration, so it holds indefinitely; `loop` is
2280
+ * therefore false (`loop: true` is incompatible with a durationless segment).
2281
+ * `sync: 'mount'` is the default and the reason a joiner always sees movement
2282
+ * one: pre-roll semantics. An `epoch` sequence would instead start every
2283
+ * viewer at the room's shared clock — right for a wall of screens, wrong for
2284
+ * a piece that should start when you look at it.
2285
+ */
2286
+ declare const THREE_MOVEMENTS_SEQUENCE: IdleSequence;
2287
+
2117
2288
  /** Catalog entry for a bundled schema example. */
2118
2289
  interface SchemaExample {
2119
2290
  id: string;
@@ -2122,9 +2293,24 @@ interface SchemaExample {
2122
2293
  }
2123
2294
  /** Ordered catalog of bundled schema examples. Add new specs as standalone files, then register here. */
2124
2295
  declare const SCHEMA_EXAMPLES: readonly SchemaExample[];
2296
+ /** Catalog entry for a bundled idle-sequence example. */
2297
+ interface SequenceExample {
2298
+ id: string;
2299
+ label: string;
2300
+ sequence: IdleSequence;
2301
+ }
2302
+ /**
2303
+ * Ordered catalog of bundled idle-sequence examples.
2304
+ *
2305
+ * Deliberately separate from SCHEMA_EXAMPLES: that catalog is typed
2306
+ * `SaverSpec[]` and its consumers (manifests, batch compile, the MCP examples
2307
+ * resource) rely on that. A sequence is a different top-level format, so it
2308
+ * gets its own list rather than widening theirs.
2309
+ */
2310
+ declare const EXAMPLE_SEQUENCES: readonly SequenceExample[];
2125
2311
  /** All example specs in catalog order (tests, batch compile). */
2126
2312
  declare const EXAMPLE_SPECS: SaverSpec[];
2127
2313
  /** Lookup by saver id. */
2128
2314
  declare const EXAMPLE_BY_ID: Readonly<Record<string, SaverSpec>>;
2129
2315
 
2130
- export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COHESION_T, COMETS_SPEC, CONSTELLATION_SPEC, type CapabilityTier, type CohesionRead, type CycleSpec, DASHBOARD_SPEC, DITHER_ALPHA, DITHER_TILE, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SPECS, type Entity, FACETS_SPEC, FIELD_BUCKET_MS, FIELD_DRIFT_DEFAULT_AMOUNT, FIELD_RASTER_SHORT_SIDE, FIELD_RASTER_SHORT_SIDE_LOW, FINISH_ANIMATE_HZ, type FieldBackground, type FieldDrift, type FinishPass, type FinishSpec, GRAIN_ALPHA, GRAIN_TILE, type GradientStop, HAIKU_SPEC, type IdleSequence, LANTERNS_SPEC, LIMITS, LOBBY_TALK_SPEC, type LayerCohesion, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, type MotionEase, type MotionSpec, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, PINGS_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PerceiveOptions, type PerceiveSequenceOptions, type Placed, RAIN_SPEC, RELAY_BOARD_SPEC, type ResolveOptions, type ResolvedSegment, type RevealState, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SNOWFALL_SPEC, type SaverSpec, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type ScreenOp, type SequenceFramePerception, type SequenceMountContext, type SequenceSaverInstance, type SequenceSaverPlugin, type SequenceSegment, type SequenceTransition, type SpecError, type SpecMountContext, type SpecWarning, type SpriteSpec, type SteerDelta, THERMAL_FIELD_SPEC, type TextBlockAnchor, type TextBlockLine, type TextMetricsClass, type TextRevealInput, type TextRevealSpec, type TextRole, type TextSpriteInfo, type ValidationResult, WARP_MAX_SCALE, WARP_NEAR, WARP_TUNNEL_SPEC, type WanderOsc, type WarningBox, adviseSequence, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSequence, assertValidSpec, bayerMatrix, bayerTilePixels, bedRenderSeed, breakTextBlock, buildEntities, canMorph, cohesionOf, compileSaver, compileSequence, createFinishPass, createSceneCanvas, describeScene, diffScenes, dominanceRanking, easeSmooth, emitEnvelope, emitWindow, fieldAt, fieldOctaves, fieldRgb, fieldRgbAt, fieldSampleTime, finishStrength, grainOffset, grainTilePixels, graphemeClusters, hasHotSwapSequence, headingAt, hexToRgb255, latticeHash, layerCohesion, lerpSpec, lifeAlphaAt, linkEdges, linkPairs, luminanceGrid, manifestFor, morphChainRoot, morphNothingMorphable, motionStats, normalizeSeed, perceiveScene, perceiveSequenceFrame, pickScreenOp, positionAt, presentWithFinish, renderBrailleMap, renderDensityMap, resolveSegment, resolveSpecPath, revealState, rgb255Luma, rotationAt, seamCauseOf, seamsWorthWarning, segmentRenderSeed, segmentStart, sequenceSteerablePaths, sequenceSwapCompatible, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textBlockAnchorOffset, textMetricsClassFor, textSprites, textStringsDiffer, textStringsOf, textWidthEm, validateSequence, validateSpec };
2316
+ export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COHESION_T, COMETS_SPEC, CONSTELLATION_SPEC, type CapabilityTier, type CohesionRead, type CycleSpec, DASHBOARD_SPEC, DITHER_ALPHA, DITHER_TILE, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SEQUENCES, EXAMPLE_SPECS, type Entity, FACETS_SPEC, FIELD_BUCKET_MS, FIELD_DRIFT_DEFAULT_AMOUNT, FIELD_RASTER_SHORT_SIDE, FIELD_RASTER_SHORT_SIDE_LOW, FINISH_ANIMATE_HZ, type FieldBackground, type FieldDrift, type FinishPass, type FinishSpec, GRAIN_ALPHA, GRAIN_TILE, type GradientStop, HAIKU_SPEC, type IdleSequence, LANTERNS_SPEC, LIMITS, LOBBY_TALK_SPEC, type LayerCohesion, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, MURMUR_SPEC, type MotionEase, type MotionSpec, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, PHASE_DUET_SPEC, PINGS_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PerceiveOptions, type PerceiveSequenceOptions, type Placed, RAIN_SPEC, RELAY_BOARD_SPEC, type ResolveOptions, type ResolvedSegment, type RevealState, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SHARD_FALL_SPEC, SIGNAL_BOARD_SPEC, SNOWFALL_SPEC, SPARSE_NIGHT_SPEC, type SaverSpec, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type ScreenOp, type SequenceExample, type SequenceFramePerception, type SequenceMountContext, type SequenceSaverInstance, type SequenceSaverPlugin, type SequenceSegment, type SequenceTransition, type SpecError, type SpecMountContext, type SpecWarning, type SpriteSpec, type SteerDelta, THERMAL_FIELD_SPEC, THREE_MOVEMENTS_SEQUENCE, TYPED_CUE_SPEC, type TextBlockAnchor, type TextBlockLine, type TextMetricsClass, type TextRevealInput, type TextRevealSpec, type TextRole, type TextSpriteInfo, type ValidationResult, WARP_MAX_SCALE, WARP_NEAR, WARP_TUNNEL_SPEC, WEB_WORK_SPEC, type WanderOsc, type WarningBox, adviseSequence, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSequence, assertValidSpec, bayerMatrix, bayerTilePixels, bedRenderSeed, breakTextBlock, buildEntities, canMorph, cohesionOf, compileSaver, compileSequence, createFinishPass, createSceneCanvas, describeScene, diffScenes, dominanceRanking, easeSmooth, emitEnvelope, emitWindow, fieldAt, fieldOctaves, fieldRgb, fieldRgbAt, fieldSampleTime, finishStrength, grainOffset, grainTilePixels, graphemeClusters, hasHotSwapSequence, headingAt, hexToRgb255, latticeHash, layerCohesion, lerpSpec, lifeAlphaAt, linkEdges, linkPairs, luminanceGrid, manifestFor, morphChainRoot, morphNothingMorphable, motionStats, normalizeSeed, perceiveScene, perceiveSequenceFrame, pickScreenOp, positionAt, presentWithFinish, renderBrailleMap, renderDensityMap, resolveSegment, resolveSpecPath, revealState, rgb255Luma, rotationAt, seamCauseOf, seamsWorthWarning, segmentRenderSeed, segmentStart, sequenceSteerablePaths, sequenceSwapCompatible, sequenceWantsFinish, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textBlockAnchorOffset, textMetricsClassFor, textSprites, textStringsDiffer, textStringsOf, textWidthEm, validateSequence, validateSpec };