Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/desktop-notification/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "desktop-notification",
"version": "0.5.2",
"version": "0.5.3",
"description": "Alert you when Claude Code needs input — an audible terminal bell, an OSC 9 terminal notification, and an OS-native toast (macOS/Linux) on permission and idle prompts.",
"author": {
"name": "Melodic Software",
Expand Down
23 changes: 23 additions & 0 deletions plugins/desktop-notification/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,29 @@
All notable changes to the `desktop-notification` plugin are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning.

## [0.5.3]

### Fixed

- C1 fd1-leak detector in `desktop-notification.test.sh`: the threshold that was
supposed to widen the slow-sink margin (`#751`, closing `#448`) could not actually
widen it — `THRESHOLD_MS` was derived as `SINK_SLEEP * 1000 / 2`, so widening
`SINK_SLEEP` widened the threshold by the same ratio and left the margin unchanged
by construction. `#448` was reopened after this reproduced on clean `main`
(delta=3697ms false-fail, no leak present). `THRESHOLD_MS` now asserts the real
invariant directly — sink-sleep-minus-a-safety-margin, not half the sleep — and
`SINK_SLEEP` is widened from 6s to 8s (still comfortably under the 10s ceiling
documented against EXIT-cleanup file-locking on Windows) for more absolute
separation between ambient noise and the leak signal. The safety margin is sized so
BOTH sides of the threshold clear the 2150ms of worst observed no-leak noise, not
just the noise side: a threshold too close to the leak signal lets a load shift that
inflates every baseline sample and then subsides before the slow run subtract real
leak signal out of the delta, and the detector reports no leak. At `SINK_SLEEP`=8s
and a 3000ms margin the threshold sits at 5000ms — 2850ms of noise-side margin,
3000ms of leak-side margin. Verified on Windows Git Bash: 10 consecutive clean runs,
40 runs under heavy concurrent load (worst observed no-leak delta ~1590ms), and a
deliberately reintroduced fd1 leak still fails the case (observed delta ~8065ms).

## [0.5.2]

### Fixed
Expand Down
33 changes: 29 additions & 4 deletions plugins/desktop-notification/hooks/desktop-notification.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,32 @@ rm -f "$TEL"
# locks its stub file on Windows. A baseline run (fast sink, no sleep) captures
# the SAME ambient overhead as the slow run under the SAME capture; subtracting
# it cancels the overhead and isolates the leak signal. Under a leak the delta
# is ~SINK_SLEEP; with no leak it is ~0 (± scheduling jitter). Threshold is half
# the sleep: comfortably above jitter, comfortably below the leak signal.
# is ~SINK_SLEEP; with no leak it is ~0 (± scheduling jitter).
#
# THRESHOLD_MS asserts the actual invariant — "did not wait for the sink" —
# as sleep-minus-a-safety-margin, NOT half the sleep. Halving discarded margin
# for no gain and was proven too tight empirically (#448 reopen): a clean-main
# false-fail measured delta=3697ms against the old 3000ms/half-sleep threshold,
# and load-generated measurements up to ~2150ms (30 concurrent suite runs on
# Windows Git Bash) confirm noise alone can approach that old threshold.
#
# The threshold has TWO margins and both must clear that 2150ms worst observed
# noise, because the detector can fail in either direction:
#
# noise side threshold - max_noise a no-leak run must stay BELOW it
# leak side leak_signal - threshold a leaking run must stay ABOVE it
#
# The leak side is the one a too-HIGH threshold breaks, and it is not covered by
# the min-of-N baseline below: that protects against ONE unlucky baseline sample,
# not against a load shift that inflates ALL of them and then subsides before the
# slow run. Baselines 2s+ slower than the slow run's own overhead subtract real
# leak signal out of the delta, so a leak whose delta lands between the threshold
# and SINK_SLEEP passes silently. SINK_SLEEP=8s with SAFETY_MARGIN_MS=3000 puts
# the threshold at 5000ms, roughly midway between the signal and the noise:
# 2850ms of noise-side margin and 3000ms of leak-side margin, both above the
# 2150ms worst case measured. Recorded measurements bracket it — a deliberately
# reintroduced leak measured delta=8065ms (detected), while 40 runs under 30x
# concurrent load peaked at ~1590ms with no leak (passed).
#
# The baseline is the MINIMUM of several fast runs, not a single sample. A lone
# baseline that happened to be descheduled longer than the slow run would shrink
Expand All @@ -238,7 +262,8 @@ rm -f "$TEL"
# unlucky sample. The opposite error — an inflated slow sample with no leak —
# only re-fails a green run (fail-safe, re-runnable), so just the baseline needs
# min-of-N; the slow run stays single (each slow sample costs SINK_SLEEP).
SINK_SLEEP=6
SINK_SLEEP=8
SAFETY_MARGIN_MS=3000
BASE_SAMPLES=3
BASE_SINK="$(make_sink "cat >/dev/null")"
SLOW_SINK="$(make_sink "cat >/dev/null; sleep $SINK_SLEEP")"
Expand All @@ -261,7 +286,7 @@ _TS1=$EPOCHREALTIME
SLOW_MS=$(epoch_delta_ms "$_TS0" "$_TS1")

DELTA_MS=$((SLOW_MS - BASE_MS))
THRESHOLD_MS=$((SINK_SLEEP * 1000 / 2))
THRESHOLD_MS=$((SINK_SLEEP * 1000 - SAFETY_MARGIN_MS))
Comment thread
kyle-sexton marked this conversation as resolved.
echo " (C1 fd1-leak: base=${BASE_MS}ms (min of ${BASE_SAMPLES}) slow=${SLOW_MS}ms delta=${DELTA_MS}ms, threshold <${THRESHOLD_MS}ms, sink sleeps ${SINK_SLEEP}s)"
if [[ $RC_SLOW -eq 0 ]]; then ok "telemetry/slow-sink: hook exit 0"; else fail "telemetry/slow-sink: hook exit $RC_SLOW"; fi
if [[ $DELTA_MS -lt $THRESHOLD_MS ]]; then
Expand Down
2 changes: 1 addition & 1 deletion plugins/markdown-format/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "markdown-format",
"version": "0.6.4",
"version": "0.6.5",
"description": "Auto-format and lint Markdown on edit via markdownlint-cli2, using the consuming repo's own markdownlint config.",
"author": {
"name": "Melodic Software",
Expand Down
22 changes: 22 additions & 0 deletions plugins/markdown-format/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,28 @@
All notable changes to the `markdown-format` plugin are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning.

## [0.6.5]

### Fixed

- C1 fd1-leak detector in the hook contract test: the differential threshold
introduced in `0.6.2` (ported from `desktop-notification` `#751`) carried the same
latent defect — `THRESHOLD_MS` was derived as `SINK_SLEEP * 1000 / 2`, so widening
`SINK_SLEEP` widened the threshold proportionally and left the margin unchanged by
construction (`#448`, reopened after reproducing on clean `main`: delta=3697ms
false-fail with no leak present, in the `desktop-notification` copy this test was
ported from). `THRESHOLD_MS` now asserts the real invariant directly —
sink-sleep-minus-a-safety-margin, not half the sleep — and `SINK_SLEEP` widens from
6s to 8s (still under the 10s ceiling documented against EXIT-cleanup file-locking
on Windows) for more absolute separation between ambient noise and the leak signal.
The safety margin is sized so BOTH sides of the threshold clear the 2150ms of worst
observed no-leak noise, not just the noise side: a threshold too close to the leak
signal lets a load shift that inflates every baseline sample and then subsides
before the slow run subtract real leak signal out of the delta, and the detector
reports no leak. At `SINK_SLEEP`=8s and a 3000ms margin the threshold sits at
5000ms — 2850ms of noise-side margin, 3000ms of leak-side margin.
No behavior change for this plugin — the hook is untouched; test-only.

## [0.6.4]

### Fixed
Expand Down
33 changes: 29 additions & 4 deletions plugins/markdown-format/hooks/markdown-format.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -789,8 +789,32 @@ rm -f "$FAIL_SINK_FILE"
# file on Windows. A baseline run (fast sink, no sleep) captures the SAME ambient
# overhead as the slow run under the SAME capture; subtracting it cancels the
# overhead and isolates the leak signal. Under a leak the delta is ~SINK_SLEEP;
# with no leak it is ~0 (± scheduling jitter). Threshold is half the sleep:
# comfortably above jitter, comfortably below the leak signal.
# with no leak it is ~0 (± scheduling jitter).
#
# THRESHOLD_MS asserts the actual invariant — "did not wait for the sink" —
# as sleep-minus-a-safety-margin, NOT half the sleep. Halving discarded margin
# for no gain and was proven too tight empirically (#448 reopen): a clean-main
# false-fail measured delta=3697ms against the old 3000ms/half-sleep threshold,
# and load-generated measurements up to ~2150ms (30 concurrent suite runs on
# Windows Git Bash) confirm noise alone can approach that old threshold.
#
# The threshold has TWO margins and both must clear that 2150ms worst observed
# noise, because the detector can fail in either direction:
#
# noise side threshold - max_noise a no-leak run must stay BELOW it
# leak side leak_signal - threshold a leaking run must stay ABOVE it
#
# The leak side is the one a too-HIGH threshold breaks, and it is not covered by
# the min-of-N baseline below: that protects against ONE unlucky baseline sample,
# not against a load shift that inflates ALL of them and then subsides before the
# slow run. Baselines 2s+ slower than the slow run's own overhead subtract real
# leak signal out of the delta, so a leak whose delta lands between the threshold
# and SINK_SLEEP passes silently. SINK_SLEEP=8s with SAFETY_MARGIN_MS=3000 puts
# the threshold at 5000ms, roughly midway between the signal and the noise:
# 2850ms of noise-side margin and 3000ms of leak-side margin, both above the
# 2150ms worst case measured. Recorded measurements bracket it — a deliberately
# reintroduced leak measured delta=8065ms (detected), while 40 runs under 30x
# concurrent load peaked at ~1555ms with no leak (passed).
#
# The baseline is the MINIMUM of several fast runs, not a single sample. A lone
# baseline that happened to be descheduled longer than the slow run would shrink
Expand All @@ -801,7 +825,8 @@ rm -f "$FAIL_SINK_FILE"
# sample with no leak — only re-fails a green run (fail-safe, re-runnable), so
# just the baseline needs min-of-N; the slow run stays single (each slow sample
# costs SINK_SLEEP).
SINK_SLEEP=6
SINK_SLEEP=8
SAFETY_MARGIN_MS=3000
BASE_SAMPLES=3
BASE_SINK="$(make_sink "cat >/dev/null")"
SLOW_SINK="$(make_sink "cat >/dev/null; sleep $SINK_SLEEP")"
Expand Down Expand Up @@ -832,7 +857,7 @@ _TS1=$EPOCHREALTIME
SLOW_MS=$(epoch_delta_ms "$_TS0" "$_TS1")

DELTA_MS=$((SLOW_MS - BASE_MS))
THRESHOLD_MS=$((SINK_SLEEP * 1000 / 2))
THRESHOLD_MS=$((SINK_SLEEP * 1000 - SAFETY_MARGIN_MS))
echo " (C1 fd1-leak: base=${BASE_MS}ms (min of ${BASE_SAMPLES}) slow=${SLOW_MS}ms delta=${DELTA_MS}ms, threshold <${THRESHOLD_MS}ms, sink sleeps ${SINK_SLEEP}s)"
if [[ $RC_SLOW -eq 0 ]]; then ok "telemetry/slow-sink: hook exit 0"; else fail "telemetry/slow-sink: hook exit $RC_SLOW"; fi
if [[ $DELTA_MS -lt $THRESHOLD_MS ]]; then
Expand Down