Repository navigation
Releases: promptityourself/mwk-dial-countdown
Release list
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.
3.8.0 — the health line now reports the machine's own load, not just this plugin's
Added
-
The health line now reports the machine's own load, not just this plugin's. Because the next
thing reported was that other applications were lagging too — and every number in this report so
far was about this plugin, all of which read perfectly healthy on a machine that is on its knees. A
starved process uses little CPU precisely because it is not being scheduled, so the line would
have saidcpu 0.2%and looked like an exoneration when it was a symptom.health: cpu 0.4% rss 71MB controls 12 frames 9.3/s lag 2ms slowest-render 0.8ms rtt 92ms | machine: cpu 1% free-mem 23.4/31GBEverything before the bar is this plugin. Everything after it is the computer. If the machine's
CPU is high or its free memory is nearly gone while this plugin's own numbers are small, the plugin
is a victim rather than a cause — and the same line proves it, out of a log you are already
collecting. -
A Diagnostics section in the property inspector, showing the latest reading and where the log
lives. Open the inspector for any countdown and it is at the bottom: the most recent health line,
the full path to the log folder, and a button to copy that path.It exists because the honest answer to "where do I read this?" was several lines long and began with
"it depends on your platform and how Stream Deck was installed". The plugin does not have to guess —
Stream Deck launches it from inside its own folder, so it simply reports where it is.
Internal
-
The machine's CPU is derived from per-core times rather than a load average, because
os.loadavg()returns zeroes on Windows and this number has to mean the same thing on both
platforms. -
The test for it had to be written twice, and the first version is worth recording: it asserted
the line matchedmachine: cpu \d+%, whichcpu 0%satisfies — so a reading stubbed out to zero
passed it. It pegs a core now and asserts the number is above zero. That is the third check today
written against a format rather than a value that went green against a broken build.
3.7.0 — the health line now times the round trip to stream deck, which is how a busy application is told from a busy plugin
Added
-
The health line now times the round trip to Stream Deck, which is how a busy application is told
from a busy plugin. Asked the obvious question — what if something else on the machine is blocking
it — and the honest answer needed a number that did not exist yet.Nothing another plugin does can block this one directly. Every Stream Deck plugin runs in its
own process, so another plugin misbehaving cannot stall this one's event loop;lagwould stay
clean straight through it. What is shared is the Stream Deck application and the one USB device
behind it — and a plugin flooding that would leave every number in this report looking healthy while
the hardware crawled. No measurement taken inside this process could see it.rttcan, because it is the application's own answering time:health: cpu 0.4% rss 71MB controls 12 frames 9.3/s lag 2ms slowest-render 0.8ms rtt 92mswhat the line says what it means cpuhighthis plugin, and this plugin's to fix laghigh,cpulowthis process is blocked or starved — something else is taking the machine rtthigh,cpuandlaglowthe Stream Deck application or the device, not this plugin all low, device still slow not the software at either end of this link
Internal
- The probe asks for the global settings, which this plugin does not use and has no handler for.
Asking for an action's settings would have worked equally well and would have fired this plugin's
owndidReceiveSettingsonce a minute, re-applying settings nobody had touched — a measurement that
alters what it measures. It is raced against a five second timeout, and a probe that fails or never
returns is reported in the line rather than thrown, because a round trip that cannot complete is the
most interesting thing the line could say.
3.6.0 — the plugin now reports what it is costing your machine, once a minute, into its own log
Added
-
The plugin now reports what it is costing your machine, once a minute, into its own log. Because
"the device feels slow" is the one question that cannot be answered from a developer's desk — and
every performance number this plugin has produced so far came from a mock host on a Linux box with
one control on it, which says nothing about a Stream Deck + on Windows with a dozen other plugins
running beside it.health: cpu 0.4% rss 71MB controls 12 frames 9.4/s lag 2ms slowest-render 0.8msFour numbers, because between them they separate the three possible causes.
cpuand
framesare this plugin's to fix if they are high.lagis the one that matters for an
unresponsive device: a plugin at 1% CPU and 400 ms of lag is blocked, not busy, and nothing else
tells those two apart.slowest-rendernames this plugin as the cause of that lag, if it is.A warning is written the moment lag crosses 250 ms, rather than waiting for the next summary, so
a freeze leaves a timestamp you can point at. That number is the touchscreen's own double-tap
window: once the plugin is running that late it can no longer tell a single tap from half of a
double one, because the delay is as long as the thing it is measuring. That is the point where
slowness stops being cosmetic and starts changing what a gesture means — which would explain
presses that do not register and a clock that seems to tick unevenly, from one cause.The log is
logs/com.matewishkey.dial-countdown-v2.0.log, inside the plugin's own folder.
Internal
-
For the record, measured on a Linux desktop, and offered as a baseline rather than as a verdict:
one dial frame — the ring and the glyph, rendered and encoded as they are sent — costs 4 µs,
which is 0.01% of one core for four dials at the full render rate. Twelve controls idle at 0.3%
CPU; spinning a dial hard reaches 1.2%. Nothing in that supports the plugin being the cause of
a slow device, and nothing in it rules the possibility out on other hardware either. -
The control count was wrong the first time it ran end to end, and only running it showed that.
The dial and the key are separate actions with separate instance maps, so a single shared total was
written twice per change and whichever ran last won — four dials and eight keys reportedcontrols 8. It is counted per action and summed now. An undercount makes every per-control figure beside it
read better than the truth, which is the one direction a health report must never be wrong in.
3.5.1 — a change made on the hardware could be undone by the next thing you touched in the property inspector
Fixed
-
A change made on the hardware could be undone by the next thing you touched in the property
inspector. Reported as the clicks going wrong once auto-reset and fade to the end were switched
on. Neither setting is itself at fault — what they have in common is that you switch them on in the
inspector, and the inspector is the other half of this.A gesture that changes the preset is written to disk a fraction of a second later, because that write
is held back so that spinning the dial does not go to disk on every click. The inspector is brought
up to date by that write — so until it lands, the inspector is both the authority on your settings
and out of date about them. Tick any checkbox in that gap and its idea of the selected preset came
back over the top: the clock reloaded the old preset, and the pending write then put the old
selection on disk too, so the preset you had just chosen was gone from the screen and from the
settings both.Measured against the built plugin, holding the screen to move 5m → 20m and then ticking a box: at
80 ms and 250 ms the advance was undone; at 800 ms, past the write, it survived. All three keep it
now. Only the selected preset is held back, and only while a write is outstanding — everything you
actually opened the inspector to change is taken exactly as sent, including edits to the preset
lengths themselves.
Internal
- Two new tests tear down in a
finally, and the mutation harness now knows a hang from a
failure. Written without one, a deliberately broken build hung the suite rather than failing it:
the render loop is an interval, and an assertion that throws before the teardown line leaks it and
holds the process open. By exit code alone a hang and a pass are the same answer, which is the same
shape of blind spot as the release gate that could not fail.