@idle-screens/schema 2.3.0 → 3.0.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
@@ -122,7 +122,7 @@ trails, long-exposure light). 0.85–0.95 is the useful range; 0 (default) is of
122
122
  | `blend` | `lighter` \| `screen` \| `multiply` | source-over | additive glow / gentle additive / darkening |
123
123
  | `region` | `{x?, y?}` ranges 0..1 | full viewport | fractional spawn window (placement only, not travel) |
124
124
  | `pulse` | `{amp ≤ 0.5, period ≥ 500, wave?}` | none | opacity breathing; `wave: {wavelength, angle?}` turns it into a traveling wave across the field |
125
- | `spin` | number ±360 deg/sec | none | per-entity rotation (seeded start angle) |
125
+ | `spin` | number \| `[min,max]` ±360 deg/sec | none | per-entity rotation (seeded start angle); a range gives each entity a seeded speed (confetti, tumbling debris) |
126
126
  | `grow` | `{amp ≤ 0.8, period ≥ 500}` | none | size breathing (seeded phase) |
127
127
  | `trail` | `{length ≤ 5000, fade?}` | none | analytic afterglow trail (ms of history) |
128
128
  | `links` | see below | none | inter-entity lines |
@@ -225,23 +225,38 @@ zero-dependency, renderer-free analysis tool.
225
225
  (background gradient + entities + link lines, blend-aware), with coverage,
226
226
  visual-mass centroid, and **row/column deviation profiles** (1D transects of
227
227
  the composition).
228
- - `renderBrailleMap(grid)` — the picture: 12 lines × 40 braille chars, each
229
- char a 2×4 dot cell, ordered-dithered with auto-exposure. An agent reads the
230
- whole frame at once instead of reconstructing it entity by entity.
228
+ - `renderBrailleMap(grid)` — the compact picture: 12 lines × 40 braille chars,
229
+ each char a 2×4 dot cell, ordered-dithered with auto-exposure. An agent reads
230
+ the whole frame at once instead of reconstructing it entity by entity.
231
+ - `renderDensityMap(grid)` — a **higher-fidelity** picture: one ASCII density
232
+ char (` .:-=+*#%@`) per grid cell, so it's 1:1 with the grid. Pair with a
233
+ larger `cols`/`rows` (e.g. `{cols: 120, rows: 48}`) to resolve structure the
234
+ braille map smears — concentric rings, grids, text blocks. This is the sharper
235
+ read when composition detail matters.
231
236
  - `dominanceRanking(spec, opts)` — layers ranked by estimated visual weight
232
237
  (area × alpha × contrast × glow/motion boosts; links count) — *where the eye
233
- goes*, normalized to shares.
238
+ goes*, normalized to shares. Thin-but-bright structures (rings, streaks, link
239
+ lines) get a line-salience boost so they aren't crushed by filled discs.
234
240
  - `motionStats(spec, opts)` — per-layer mean/max on-screen speed from analytic
235
241
  displacement — choreography as numbers.
242
+ - `textSprites(spec, opts)` — the literal strings and rendered sizes of every
243
+ text layer. Glyphs are invisible in the luminance maps, so this is the only
244
+ way to confirm *what words* are on screen and how big. (Also on
245
+ `perceiveScene().text`.)
236
246
  - `diffScenes(a, b, opts)` — **relative sight**: coverage/luminance deltas,
237
247
  visual-balance shift, 3×3 region deltas, dominance-rank movement, and
238
248
  advisory codes added/removed. Agents judge "is B better than A" far more
239
249
  reliably than "is A good"; this is the edit loop's primary instrument.
240
250
 
241
- Known approximations (deliberate): trails and ghosting are not sampled, soft
242
- circles use a linear falloff, text ink is estimated from font size × string
243
- length. Good enough to perceive composition, focus, balance, and motion —
244
- not a substitute for a human (or VLM) judgement of beauty.
251
+ Coverage is **additive-glow-calibrated**: soft circles drawn with
252
+ `blend: lighter`/`screen` bloom past their radius (as they do on the real
253
+ canvas), so `coverage` tracks what the audience sees instead of under-reporting
254
+ glow-heavy scenes by an order of magnitude.
255
+
256
+ Known approximations (deliberate): trails and ghosting are not sampled, text ink
257
+ is estimated from font size × string length. Good enough to perceive
258
+ composition, focus, balance, and motion — not a substitute for a human (or VLM)
259
+ judgement of beauty.
245
260
 
246
261
  ## Examples
247
262
 
package/dist/index.d.ts CHANGED
@@ -115,8 +115,12 @@ interface LayerSpec {
115
115
  /**
116
116
  * Per-entity rotation speed in degrees/sec (positive = clockwise).
117
117
  * Each entity gets a seeded starting angle. Composes with any motion type.
118
+ * A scalar applies one speed to every entity; a `[min, max]` range gives each
119
+ * entity a seeded speed within the range (like `speed`/`alpha`) — confetti,
120
+ * tumbling debris, foliage. Existing scalar specs are unaffected (the range
121
+ * form draws one extra seeded value, only when present).
118
122
  */
119
- spin?: number;
123
+ spin?: number | [number, number];
120
124
  /**
121
125
  * Sinusoidal size breathing, parallel to `pulse` for opacity. `amp` is a
122
126
  * fraction of base size (0.3 = ±30 %). `period` in ms with the same
@@ -703,12 +707,33 @@ declare function luminanceGrid(spec: SaverSpec, opts?: LuminanceGridOptions): Lu
703
707
  * Encode a luminance grid as a braille "image": each output character is a 2×4
704
708
  * pixel cell, ordered-dithered so mid-tones render as dot density. A grid of
705
709
  * 80×48 becomes 12 lines of 40 chars — a picture a text model can read whole.
706
- *
707
- * Auto-exposure: most savers live in the bottom of the luminance range, so the
708
- * cells are normalized (min → 98th percentile) before dithering — like a
709
- * camera exposing for the scene. Stats on the grid itself stay raw.
710
710
  */
711
711
  declare function renderBrailleMap(grid: LuminanceGrid): string;
712
+ /**
713
+ * Encode a luminance grid as a one-char-per-cell ASCII density map. Unlike the
714
+ * braille map (compact, 2×4 dots/char) this is 1:1 with the grid, so pairing it
715
+ * with a larger `cols`/`rows` gives a non-vision agent a genuinely higher-detail
716
+ * read: 120×48 resolves concentric rings and text blocks braille smears into a
717
+ * blob. Shares the braille map's auto-exposure so both views agree.
718
+ */
719
+ declare function renderDensityMap(grid: LuminanceGrid): string;
720
+ interface TextSpriteInfo {
721
+ layerIndex: number;
722
+ key: string | undefined;
723
+ /** The literal strings this layer draws (glyphs are invisible in the maps). */
724
+ strings: string[];
725
+ /** How many entities carry text. */
726
+ count: number;
727
+ /** Representative rendered glyph height in px at the sample viewport. */
728
+ sizePx: number;
729
+ }
730
+ /**
731
+ * List every text layer's actual strings and rendered size. No grid resolution
732
+ * renders glyphs legibly, so a non-vision agent otherwise can't tell whether the
733
+ * words it wrote are on screen, how big, or whether they'll overlap. This closes
734
+ * that blind spot analytically.
735
+ */
736
+ declare function textSprites(spec: SaverSpec, opts?: PerceiveOptions): TextSpriteInfo[];
712
737
  interface DominanceEntry {
713
738
  rank: number;
714
739
  layerIndex: number;
@@ -789,8 +814,14 @@ interface SceneDiff {
789
814
  declare function diffScenes(a: SaverSpec, b: SaverSpec, opts?: LuminanceGridOptions): SceneDiff;
790
815
  interface ScenePerception {
791
816
  t: number;
792
- /** The picture: a braille luminance map (each char = 2×4 pixels). */
817
+ /** The picture: a braille luminance map (each char = 2×4 pixels), compact. */
793
818
  braille: string;
819
+ /**
820
+ * A one-char-per-cell ASCII density map at the grid resolution — higher
821
+ * fidelity than braille for structure (rings, grids, text blocks). Pair with
822
+ * a larger `cols`/`rows` for a sharper read.
823
+ */
824
+ density: string;
794
825
  coverage: number;
795
826
  meanLuminance: number;
796
827
  centroid: {
@@ -801,12 +832,15 @@ interface ScenePerception {
801
832
  colProfile: number[];
802
833
  dominance: DominanceEntry[];
803
834
  motion: LayerMotionStats[];
835
+ /** Literal strings + sizes of any text layers (glyphs don't show in the maps). */
836
+ text: TextSpriteInfo[];
804
837
  advisories: ReturnType<typeof adviseSpec>;
805
838
  }
806
839
  /**
807
840
  * Everything a non-vision agent needs to "see" a spec in one deterministic
808
- * call: the braille picture, composition transects, dominance ranking, motion
809
- * stats, and advisories. Intended as the payload behind an MCP previewScene.
841
+ * call: the braille picture, a higher-res density map, composition transects,
842
+ * dominance ranking, motion stats, the literal text on screen, and advisories.
843
+ * Intended as the payload behind an MCP previewScene.
810
844
  */
811
845
  declare function perceiveScene(spec: SaverSpec, opts?: LuminanceGridOptions): ScenePerception;
812
846
 
@@ -860,13 +894,21 @@ declare const LANTERNS_SPEC: SaverSpec;
860
894
  declare const SAKURA_SPEC: SaverSpec;
861
895
 
862
896
  /**
863
- * Control Center: a general-purpose ambient status HUD (home / ops / anything —
864
- * not dev-specific). Exercises the static/HUD subset at scale plus the
865
- * v1-ceiling features: `life` staggers the panels in like a boot sequence, a
866
- * grid-`layout` LED wall breathes behind everything via a traveling
867
- * `pulse.wave`, `ring` sprites form the central gauge, and a rect "equalizer"
868
- * animates with a wave-phased pulse. Every panel is keyed so an agent can
869
- * steer any reading live (`power-value`, `gauge-value`, `feed-1`, ...).
897
+ * Control Center — VIREO-9, Trans-Lunar Relay Operations.
898
+ *
899
+ * A mission-control WALL BOARD, laid out the way real ops rooms lay them out:
900
+ * framed zones with a clear reading order, one hero display (the orbital
901
+ * plot), dense-but-calm peripheral telemetry, and a boot sequence when the
902
+ * board comes up. The fiction: a small relay station somewhere past GEO,
903
+ * mid-shift, tracking a five-craft fleet (named for this library's own
904
+ * savers — the station runs our little universe).
905
+ *
906
+ * Composed against the validator's 36-layer ceiling deliberately — every
907
+ * layer earns its slot. Schema exercises: grid `layout` LED wall with a
908
+ * traveling `pulse.wave`, `orbit` motion with `trail`s and chain `links`
909
+ * (the relay web between the fleet), `ring` orbit guides, wave-phased rect
910
+ * meters, staged `life` boots per zone. Every reading is keyed so an agent
911
+ * can steer the fiction live (`signal-value`, `feed-1`, `alert`, ...).
870
912
  */
871
913
  declare const DASHBOARD_SPEC: SaverSpec;
872
914
 
@@ -893,6 +935,18 @@ declare const AURORA_SPEC: SaverSpec;
893
935
  */
894
936
  declare const MATRIX_RAIN_SPEC: SaverSpec;
895
937
 
938
+ /**
939
+ * Tarkovsky — Nostalghia's candle: a single point of devotion.
940
+ * Near-black warm ground; one small warm-white flame at center with grow/pulse
941
+ * wobble; faint smoke rising; sparse amber embers with long fading trails;
942
+ * a wide near-invisible halo breathing on a 10s cycle. Minimalism as tension —
943
+ * most of the screen is darkness.
944
+ *
945
+ * Note: `pulse.amp` is ADDED to base alpha (not multiplied), so the halo's amp
946
+ * must stay below its base alpha or the trough clamps to fully invisible.
947
+ */
948
+ declare const NOSTALGHIA_CANDLE_SPEC: SaverSpec;
949
+
896
950
  /**
897
951
  * Polygons: the classic Mystify-style bouncing-polygon saver, expressed as chain links + heavy
898
952
  * ghosting. Showcases `links.mode: 'chain'` with `closed` (vertices wired in order
@@ -929,4 +983,4 @@ declare const EXAMPLE_SPECS: SaverSpec[];
929
983
  /** Lookup by saver id. */
930
984
  declare const EXAMPLE_BY_ID: Readonly<Record<string, SaverSpec>>;
931
985
 
932
- export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COMETS_SPEC, CONSTELLATION_SPEC, type CycleSpec, DASHBOARD_SPEC, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SPECS, type Entity, type GradientStop, LANTERNS_SPEC, LIMITS, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, type MotionSpec, ORRERY_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PerceiveOptions, type Placed, RAIN_SPEC, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SNOWFALL_SPEC, type SaverSpec, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type SpecError, type SpecWarning, type SpriteSpec, type SteerDelta, type ValidationResult, WARP_NEAR, WARP_TUNNEL_SPEC, type WanderOsc, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSpec, buildEntities, compileSaver, describeScene, diffScenes, dominanceRanking, easeSmooth, headingAt, lerpSpec, lifeAlphaAt, linkEdges, linkPairs, luminanceGrid, manifestFor, motionStats, perceiveScene, positionAt, renderBrailleMap, resolveSpecPath, rotationAt, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, validateSpec };
986
+ export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COMETS_SPEC, CONSTELLATION_SPEC, type CycleSpec, DASHBOARD_SPEC, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SPECS, type Entity, type GradientStop, LANTERNS_SPEC, LIMITS, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, type MotionSpec, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PerceiveOptions, type Placed, RAIN_SPEC, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SNOWFALL_SPEC, type SaverSpec, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type SpecError, type SpecWarning, type SpriteSpec, type SteerDelta, type TextSpriteInfo, type ValidationResult, WARP_NEAR, WARP_TUNNEL_SPEC, type WanderOsc, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSpec, buildEntities, compileSaver, describeScene, diffScenes, dominanceRanking, easeSmooth, headingAt, lerpSpec, lifeAlphaAt, linkEdges, linkPairs, luminanceGrid, manifestFor, motionStats, perceiveScene, positionAt, renderBrailleMap, renderDensityMap, resolveSpecPath, rotationAt, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textSprites, validateSpec };