Repository navigation
Releases: promptityourself/piy-dial-countdown
Release list
5.0.0 — Dial It Countdown, the first release
The first release of Dial It Countdown: countdown timers for Stream Deck dials and keys, from
Prompt It Yourself.
Added
-
A countdown timer on every dial and every key. Each control keeps its own timer, its own
presets, its own colour theme and its own display. -
The dial: turn for seconds, push the dial in and turn for minutes, press to start or pause.
-
Three gestures, the same on the touchscreen and on a key: tap to pause or resume, tap twice
to reset to full, hold to put the clock right and then to go to the next preset. -
A preset can be a list. Type
40, 10, 10and each step starts when the last one ends. Up to
twenty steps, each from one second to twenty-four hours. -
An alert at the end of every step. A press silences it and does nothing else. The dial
shows a bell and a key saysringingwhile it sounds. -
Seven colour themes, a ring or a bar on the touchscreen, a name for each timer and the
finish time on screen.
Internal
-
A new plugin, not an update of Dial Countdown. It has its own identifier,
com.promptityourself.dial-it-countdown, and its own Marketplace listing, so nothing carries
across from Dial Countdown: its users place the actions again and type their presets again. The
code is Dial Countdown 4.5.0 under the new identifier. Dial Countdown stays on its own listing,
frozen at 4.5.0, and its settings panel points here. -
One test holds every copy of the identifier to the manifest.
test/identity.test.ts
checks the folder name, both action identifiers, the two@actiondecorators, and the build,
release, icon, mock-host, version and CI files. It goes red if one copy is left behind. -
docs/releasing.mdrecords all three identifiers — the original one (spent when its listing
was deleted),-v2(frozen at 4.5.0), and this one — and why a rename alone never justifies a
new one.
4.5.0 — the last release of this plugin
The last release of this plugin. Dial It Countdown carries on as a new plugin with its own
Marketplace listing.
Changed
-
The plugin says it has moved. The settings panel opens with a notice: install Dial It
Countdown from the Marketplace, because this plugin gets no more updates. The listing
description says the same. Every timer, setting and button keeps working as before. -
The name is Dial Countdown again. 4.4.0 renamed it to Dial It Countdown, but that name now
belongs to the new plugin. With both installed, the actions list shows two different names.
Internal
- The diagnostics report and the release page read the plugin's name from the manifest, as they
already read its version. The name changed three times in two days, and each change had to find
every copy.
4.4.0 — the plugin is now called Dial It Countdown, and its mark is D|C
Changed
-
The plugin is now called Dial It Countdown, and its mark is D|C. The actions list, the
category and the property inspector say Dial It Countdown. An idle clock shows the D|C mark in
the middle of its ring, and every icon is drawn from it. It is the P|Y mark of Prompt It
Yourself, the same letters' face and the same cursor, with the plugin's own initials. The brand
is still Prompt It Yourself: the author, the colour theme and the links do not change.Nothing else moves. The plugin keeps its identifier, so every installed copy updates in place and
every configured dial and key keeps its settings.
Internal
-
The mark is
assets/dc-mark.svg, replacingassets/piy-mark.svg. It is built by the recipe
that builds P|Y,motion/brand.mjsinmergodon/piy-short-production: Fira Code Medium, its
glyph grid at +35% letter spacing, and the cursor 15% past the capitals. The same recipe run on
P and Y reproduces the old file byte for byte, so the two marks are siblings and not a redraw.
render.testnow fingerprints the D. -
A release title keeps its capitals.
npm run releaselowered the whole headline, so the 3.9.1
and 3.10.0 titles said "stream deck" and 4.3.0's said "prompt it yourself". It now lowers only the
first letter. The three published titles were corrected by hand. -
The licence and the README's trademark line now name Prompt It Yourself. 4.3.0 missed both:
the search that should have found them used?in a basic regex, where it matches a literal?.
4.3.0 — the plugin now carries the Prompt It Yourself brand
Changed
-
The plugin now carries the Prompt It Yourself brand, which replaces Mate Wish Key. An idle
clock shows the new P|Y mark in the middle of its ring, and the icons in the Stream Deck
application, on the keys and in the preferences are drawn from the same mark. The author is now
Prompt It Yourself, and the plugin's website link goes to
promptityourself.com. -
The brand colour theme is now called Prompt It Yourself. Its colours did not change. A
dial or key already set to the old Mate Wish Key theme moves to it on its own, and does not
fall back to the default.Nothing else moves. The plugin keeps its identifier, so every installed copy updates in place and
every configured dial and key keeps its settings.
Internal
-
The repository is
promptityourself/piy-dial-countdown, renamed frommwk-dial-countdown.
GitHub does not redirect every old link — an issue under the old name returns 404 — so every link
in this file, the docs and the published release notes was rewritten to the new name. Release
pages are now written topro-piy-dial-countdown/on the shared drive, since the folder is
derived from the remote; the pages already cut stay where they were. -
A test can import the action subclasses now, and does. The blocker was never the Stream Deck
SDK — it imports in under a tenth of a second and needs no connection. It was that the tests ran
on Node's type stripping, which erases types and leaves@actiondecorators standing, so
importing either subclass was aSyntaxError.test/ts-resolve.mjstranspiles through
TypeScript's own compiler instead — the one rollup already uses for the shipped bundle — and
test/actions-live.test.tsdrives the realDialCountdownandKeyCountdownthrough their own
events: rotation, the press that did not turn, the release with no press, the hold on the knob,
the tap on the glass, the key's double-press window, and a step running out and being silenced
while the next one keeps counting. Closes the gap #12
was opened on.Reintroducing the 4.1.0 bug — the ringing flag set and nothing rendering it — now fails two of
those tests as well as four intest/frame.test.ts. This commit leaves the packaged plugin
untouched — its own source edits are comments, which minification strips.The
2ca616ec…that stood here was the wrong baseline. That is what v4.2.0 shipped, and the
refactor above had already moved the bundle off it, so the id was stale the moment it was written.
Measured since: v4.2.0's published asset is2ca616ec…, and everything from the refactor onward
builds530160038f…, differing inbin/plugin.jsalone and by 46 bytes. Nothing a user can see
changed, so this still is not a release — but the claim that the bytes were identical was false,
and that claim is the one the release rule turns on. -
What each control puts on screen is now a value, in
src/frame.ts, and is tested directly.
Bothdrawmethods built their payload inline, inside classes no test can import — the@action
decorator survives type stripping — so nothing about what the user actually sees was reachable.
The scripted demo covered part of it and could never cover this part: a Linux box has no audio
player, so no alert rings here and nothing downstream of one runs. That is how 4.1.0 shipped with
a ringing state that existed in the code and appeared nowhere on the screen, through a green suite
and a green demo.test/frame.test.tsasserts the frame being sent rather than the flag behind it. Reintroducing
the 4.1.0 bug exactly — the flag set, nothing reading it — now fails four of its tests. No
behaviour changed, so this is not a release; it travels with the next one. -
The release page is one folder per version again, named for the version and not the day. It was
<date>_v<version>, so cutting the same version twice across midnight wrote a second folder beside
the first, with nothing in the index to say which was current. That is not cosmetic: mate has the
only hardware and opens these by browsing the index, and2026-09-20_v4.1.0described a design —
a Keep ringing until pressed checkbox, no hold on the knob, alerts only at the end of a job —
that had been replaced by the morning of the 21st. A re-cut now overwrites the page in place. The
date is still on the page, under the title, where it cannot multiply. Folders cut before this keep
their names so the links in old issues still resolve. Closes
#19. -
A failing test no longer takes the whole suite down with it. The render loop is a 4 Hz
setIntervalthat nothing unrefs, so an instance left running holds the event loop open and the
test file never finishes —--test-timeoutdoes not catch it, because the test itself completed.
Teardown at the end of a test body cannot prevent that: a failing assertion throws before the line
is reached, so exactly when a test has something to report is when it hangs instead. The rule was
written inCLAUDE.mdand in the file's own header, and followed by two tests out of thirty-seven.It cost a real CI run: on 2026-09-21 a timing-sensitive precondition failed and the job sat silent
for fourteen minutes until its 15-minute ceiling killed it, taking the assertion detail with it.driver(t)now registers the teardown itself, so the next test added is covered by having been
written at all. Breaking that assertion on purpose used to hang past a 90-second ceiling; it now
fails in 2.4 seconds withactual: 2, expected: 99on screen. -
The test that failed was one late tick from failing on any loaded machine. It waited 1,200 ms
for a 1 s step, but a step boundary is only noticed on a render tick — those are 250 ms apart and
can only ever run late, so the margin was 200 ms against a 250 ms tick. It waits 1,500 ms now.
4.2.0 — you can now see that it is ringing
Added
-
You can now see that it is ringing. The dial draws a bell in the middle of its ring, and a key
saysringingon its one line — a key cannot have the bell, because the middle of a key is where
its clock is drawn. It is there for as long as the sound is, and gone the moment the sound is,
whether you silenced it or it ran out on its own.The bell outranks whatever the clock itself is doing, and that is the whole point of it. On
40m, 10m, 10mthe forty runs out, its alarm starts, and the first ten starts counting in the
same breath — so the timer is running, and until now the screen showed you a running timer and
nothing else. It was true and it was no use: the thing to know is that there is a noise and that a
press will take it away.
Fixed
- A frame is now compared against what is actually being drawn, rather than against a hand-written
list of the things a frame was thought to depend on. Nothing failed when that list fell behind:
the screen simply stopped being able to change for whichever field had been left out. The bell
above would have been the next one caught by it — a sounding alert changes nothing else about a
frame, so at a step boundary the clock behind it reads the same second and the frame is judged
identical and dropped. The list is gone rather than extended, because a list can go stale and the
picture cannot.
Internal
-
Publishing no longer waits to be asked.
npm run releasewith no flag is the procedure, and
the Marketplace form is the only step left to a human.docs/releasing.mdkeeps the reasoning it
replaced rather than deleting it, and also now warns that a release run rewrites the hand-over
page'sREADME.md, so anything hand-written into it has to be re-applied afterwards. -
Three claims in this file were wrong. 4.1.0 was dated the day the entry was written rather
than the day it shipped, and both the Unreleased compare link and 4.0.0's own link pointed at a
v4.0.0tag that has never existed — measured, 404 — so a heading that reads as a link to a
release led to a GitHub error page.
4.1.0 — a press silences an alert that is playing, and does nothing else
Added
-
A press silences an alert that is playing, and does nothing else. That is what makes a high
repeat count usable — up to sixty now — because an alarm meant to outlast you walking back to the
desk is no good if it cannot be called off. The press will not start, pause or reset the clock, so
you cannot quieten a sound into changing what the timer was doing; press again for the gesture you
meant, or press and hold to silence it and put the timer right in one go. Turning the dial
silences it too, and still adjusts.Every step of a multi-step preset gets its own silenceable alert. There is no keep ringing
switch: it existed for one unreleased build and it was a second idea of the repeat count in a
different vocabulary, with a rule reconciling the two that got it backwards — only the end of the
whole job could be silenced. On40m, 10m, 10m, 10mthat is the wrong way round: the end of the
forty is the moment you must not miss, the ten after it is already counting by the time you hear
it, and the press made to quieten the alert went through to the clock and paused that ten. One
count and one rule cannot disagree with themselves.The trade, stated plainly: with the default single chime, a press made inside those two seconds is
spent on silencing and the clock does not move. Press again. -
Holding the dial's own knob puts the clock right, the same as holding the touchscreen: back to
the top of the preset, and on to the next one only when there was nothing to put right. It is also
how a dial silences a ringing alarm and resets it in one gesture, the hold being the one gesture
a ring does not swallow — until now that needed the touchscreen, because the knob had no hold.The threshold is measured on release, never by a timer running while your finger is down, and
that is the whole reason the dial can have a hold at all. Pushing the knob in is how you ask for
minutes, so a timer firing mid-press would go off in the pause between pushing in and starting to
turn, silently loading a preset under a wind that began a beat late. A press that turned the dial
is already discarded as the end of a wind, so what reaches the threshold can only be a finger that
went in, stayed, and came back up with the clock untouched. The trade: a slow, deliberate press
meant as a pause reads as a hold, and costs one more hold to undo. -
Quieter after the third play. One checkbox: the first three plays sound at the volume you set,
everything after at half of it. Half of your volume, not a fixed level, so a quiet alarm does not
get louder as it goes on.
Fixed
-
Repeats no longer play on top of each other. Set to three, the alert was heard as one chime,
then two at once, then three — stacking up and never going past three. Every repeat was scheduled
at a fixed 900 ms from the first, and the bundledchime.wavis 2.00 s long, so the second play
started while the first was still sounding. A play now begins when the previous one has ended,
which is right for a sound file of any length, on either platform, including your own. -
A step running out no longer layers its alert over the previous step's. Two runs playing at
once sound exactly like the bug above. -
The inspector's Test button is a toggle. Clicking it while a preview was still going used to
start a second one underneath the first — bearable at three plays, and most of a minute of chime at
sixty. -
Closing the property inspector stops whatever it was auditioning. A preview is reachable only
through the panel, so closing it mid-audition left the sound running with the button that would
have stopped it gone from the screen. The reason the repeat count could be raised at all is that
no setting may produce a noise there is no way to call off; this was the hole in that.
Internal
- The code and the docs now state what is true today; the changelog keeps the history.
src/
lost a third of its comment volume to passages narrating designs that had already been replaced,
docs/how-it-works.mdlost its archaeology, and aCLAUDE.mdwas added carrying the constraints a
tidy-up would otherwise undo. Nothing was deleted until it had been located by name elsewhere. One
live defect fell out of it:src/plugin.tscarried a truncated comment describing a per-minute
cost report that no longer exists. The packaged plugin is unaffected — same content id before and
after.
3.11.0 — the fault that prompted most of the last two days was never in this plugin
The fault that prompted most of the last two days was never in this plugin. A Stream Deck + was
drawing 500 mA through a Studio Display's hub — the documented ceiling for that port, and not
enough for a touchscreen, eight LCD keys and four dials. Moved to a port on the Mac, everything
works: the dials, the keys, and the built-in actions that had also stopped.
So the instrumentation built to find it comes back out. The bug fixes stay, because none of them were
ever about the hardware.
Removed
- The per-minute health report, and everything that fed it. Two timers ran for the life of the
process — an event-loop sampler twice a second and a report every sixty seconds — writing a line of
performance telemetry into the log of every install, for ever. A countdown timer does not need to
file a report about itself once a minute. - The round-trip probe, which sent a message to Stream Deck every minute purely to time the reply.
- Per-gesture logging. A line was written for every press, release, turn and tap.
- The
pressed || downoverride on a rotation. It was borrowed from another plugin on the theory
that the flag might lag the button, never measured, and a reviewer pointed out it trades a
self-correcting reading for a latch that stays wrong until the next complete press. No evidence for
it ever appeared — and the actual cause was three feet of USB away. The rotation's own flag decides
the step again.
Changed
- Copy diagnostics stays, and is leaner. It costs nothing until it is pressed, and it is what
makes the next hardware problem ten minutes rather than a day. It now carries warnings and
errors rather than every gesture and a per-minute performance line, and gathers what it needs at
the moment you press it rather than from a reporter running in the background.
Kept
For the record, since this release removes a great deal: the ten fixes from the last two days all
stay. The paused clock that threw away its count, the no-detent rotation that ate a press, the
duration ratchet, the floor that added time when you turned it down, the repeat tally that ran a
timer six times for a setting of four, the key's press-then-hold firing twice, the stray release
after a page flip, the orphaned long-press timer, the inspector undoing a gesture, and a release gate
that can now actually fail. Every one was reproduced before it was written, and every one is still
caught by deliberately breaking it and watching a test go red.
3.10.0 — copy diagnostics now names the Stream Deck application version and the connected device
Added
-
Copy diagnostics now names the Stream Deck application version and the connected device. Both
arrive when the plugin starts, in a handshake no user could go and look up — and they are exactly
what the two most commonly reported causes of an unresponsive Stream Deck turn on.Stream Deck 7.1.0.0 on mac 14.0.0 devices: Stream Deck + (type 7)When the plugin has not been told, the line is left out entirely rather than printed with question
marks in it: a line readingStream Deck ? on ? ?looks like an answer.
Internal
-
Researched what is actually reported when a Stream Deck stops responding, prompted by keys from
other plugins failing too. The two recurring answers are insufficient USB power — the device
browns out, restarts without initialising and is left in a bad state, which is why it is usually
cured by a powered hub or a direct port rather than by any software change — and an out-of-date
application. Neither is a plugin fault, and neither could be advised on without the two facts now
in the report. -
What the research did not support is recorded too: a page offering to fix Stream Deck lag gave
tidy percentages for each cause, which is the shape of a number written to be quotable rather than
measured. It is not used here. The one figure that is cited comes from a plugin vendor describing
their own support queue, and is attributed as that rather than as a fact about anyone's hardware.
3.9.1 — copy diagnostics now carries Stream Deck's own log as well as this plugin's
Fixed
-
Copy diagnostics now carries Stream Deck's own log as well as this plugin's. The application
keeps a separate log, and it is the component every plugin talks through — so when the complaint is
that the whole machine is slow and other applications are lagging too, its side of the story was in
a file the report was not reading.Its tail is included unfiltered, unlike this plugin's own lines. The format is Elgato's, and picking
lines out of it would mean guessing which ones matter; twenty-five lines of everything is more
honest than a filtered view built on an assumption.
Internal
-
The two logs are known with different confidence, and the report is careful about it. This
plugin's log location is asked of the running process and cannot be wrong. Stream Deck's is
derived from Elgato's logging guide and therefore can be — so a miss there is reported as an
absence rather than an error, and on a platform Stream Deck does not run on it says so plainly. -
Both platform branches are tested from whichever platform the suite runs on. Otherwise the
Windows path is never executed on a Mac and the Mac path never on Windows, and the one that is wrong
is precisely the one nobody ran. -
Two things turned up while reading the documentation, recorded rather than acted on: the docs say a
plugin's log files "never exceed 10 MiB", while the SDK that actually ships is configured for 50 MB
— the code is what runs. And the property inspector is Chromium with DOM access, which is why a copy
button inside it can reach the clipboard at all.
3.9.0 — a "copy diagnostics" button in the property inspector
Added
-
A "Copy diagnostics" button in the property inspector. One press puts everything needed to
investigate a problem on your clipboard, ready to paste into a message or an issue.It replaces an instruction that ran: find your Stream Deck plugins folder, which is in a different
place on each platform and depends how you installed it; open the.sdPlugindirectory; find
logs; open the newest file; scroll to the bottom; find the lines beginninghealth:; copy some of
them. Seven steps, each one a place to give up — and none of it is the job of somebody who has
reported that their device is slow. The plugin is the one thing that knows where its own log is, so
it fetches it.Dial Countdown 3.9.0.0 linux 6.8.0-139-generic x64 · 12 cores · 31GB · node v24.21.0 log: <the plugin's own folder>/logs last 6 health, warning and gesture lines: 2026-09-17T12:26:00.904Z INFO dialDown 2026-09-17T12:26:00.955Z INFO dialUp turnedWhileDown=false down=true (and so on)It carries the health lines and the gesture lines, because those are the two kinds of
trouble this plugin has actually had — is it slow and is it this plugin, and what did the
hardware really send. A report that answered only one would send you back for the other. Everything
else the plugin has ever logged is left out: a whole log is unreadable in a chat window.Find it under Diagnostics, at the bottom of the settings for any countdown.
Internal
-
Driven end to end through the real socket rather than read, and both runs found something reading
it had not.os.version()is the kernel's version, not Node's — the report printednode #139-Ubuntu SMP PREEMPT_DYNAMIC, which is precisely the shape of thing that reads as a
checked fact when it lands in a bug report. And the first version of the filter kept only health
lines, so a gesture problem would have produced a report with nothing about gestures in it. -
The empty case is tested as carefully as the full one: a button that hands back an empty box reads
as broken, so it says the first health line is about a minute away instead. Six mutations, all
caught, including one that puts the kernel version back.