aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/plans/2026-10-23-companion.md5
-rw-r--r--docs/superpowers/specs/2026-10-23-companion-design.md9
2 files changed, 9 insertions, 5 deletions
diff --git a/docs/superpowers/plans/2026-10-23-companion.md b/docs/superpowers/plans/2026-10-23-companion.md
index 371e9fa..3543b88 100644
--- a/docs/superpowers/plans/2026-10-23-companion.md
+++ b/docs/superpowers/plans/2026-10-23-companion.md
@@ -281,6 +281,9 @@ for (let i = 0; i < ladder.length; i++) {
assert.strictEqual(state(all), ladder[i][0], "everything from " + ladder[i][0] + " down");
}
+// Shoved has a frame of its own: knocked off balance, glaring at the balloon.
+assert.deepStrictEqual(M.pick(calm({ shoved: true })), { state: "shoved", frame: "shoved" });
+
// Idle levels and their frames.
assert.deepStrictEqual(M.pick(calm({ idle: 1 })), { state: "bored", frame: "sleepy" });
assert.deepStrictEqual(M.pick(calm({ idle: 2 })), { state: "yawn", frame: "yawn" });
@@ -396,7 +399,7 @@ function pick(s) {
if (since < T.destruct) return st("destruct", "base");
if (since < T.destruct + T.scorched) return st("scorched", "scorched");
if (s.dodging) return st("dodge", "base");
- if (s.shoved) return st("shoved", "mad");
+ if (s.shoved) return st("shoved", "shoved");
if (s.recording) return st("listen", "listen");
if (s.busy) return st("think", "think");
if (s.now - s.repliedAt < T.waveHold) return st("wave", "wave");
diff --git a/docs/superpowers/specs/2026-10-23-companion-design.md b/docs/superpowers/specs/2026-10-23-companion-design.md
index 8af7b69..8acffbf 100644
--- a/docs/superpowers/specs/2026-10-23-companion-design.md
+++ b/docs/superpowers/specs/2026-10-23-companion-design.md
@@ -111,13 +111,14 @@ base, so every frame descends from one reference.
| --- | --- |
| klein edit of `base-sitting.png` | `base`: "make her stand upright, facing the viewer, arms relaxed at her sides" |
| img2img from `base`, strength 0.75 | `smile`, `mad`, `smirk`, `blush1`, `blush2`, `blush3`, `sleepy` |
-| klein edit of `base` | `wave`, `watch`, `point`, `yawn`, `lying`, `listen`, `think`, `muse`, `stretch` |
+| klein edit of `base` | `wave`, `watch`, `point`, `yawn`, `lying`, `listen`, `think`, `muse`, `stretch`, `shoved` |
| klein edit of the dress frame | every `leotard/<name>`: "her skirt is gone, revealing a plain white leotard; change nothing else" |
| klein edit of `leotard/base` | `scorched`, leotard only: the moment after the explosion |
Each leotard frame is made from its own dress frame rather than from
-`leotard/base`, so the pose comes along unchanged. 17 frames a set, 35 in
-all with `scorched`.
+`leotard/base`, so the pose comes along unchanged. 18 frames a set, 37 in
+all with `scorched`. Every prompt is in `desktop/companion/frames.txt`,
+and `gen-frames` makes them through the running sd-server.
Dodging, shoving, the drop-in and the explosion are QML motion, not
frames. She is drawn 128 px tall; both monitors are at scale 1. No size
@@ -134,7 +135,7 @@ timers.
| --- | --- | --- | --- | --- |
| 1 | Self-destruct | 7th click of a burst | glow, flash, explosion, then `leotard/scorched` | see below |
| 2 | Dodge | pointer rests on her 0.6 s with no click | slides out of the corner | returns after 5 s |
-| 3 | Shoved | a balloon is on screen on her monitor | `mad`, slid left by the stack's width | balloons gone |
+| 3 | Shoved | a balloon is on screen on her monitor | `shoved`, slid left by the stack's width | balloons gone |
| 4 | Assistant | recording / working / reply arrived | `listen` / `think` / `wave` | state ends; wave lasts 3 s |
| 5 | Clicks | clicks 1-6 of a burst; a burst ends after 1.5 s without one | `smile`, `blush1` to `blush3` | 2 s after the last click |
| 6 | Mock | BackSpace, at most once in 20 s | `smirk`, `point` | 2.5 s |