Repository navigation
Commit b214bbd
fix(skills): coalesce a watcher's debounce window into one reconcile (#215)
## What
`SkillWatcher` cleared its wake flag *before* waiting out the debounce.
A notification that arrived inside the window set the flag again, so a
second reconcile followed right after the first: a burst of changes
spread across one window ran two reconciles, not one. The TypeScript
watcher restarts its timer on every notification and runs one.
The debounce now trails. After each window the watcher checks whether
another change arrived and, if one did, waits a fresh window. It
reconciles only after delivery has been quiet for a whole window. The
reconcile reads the store after that last window, so it sees every
change in the burst. Nothing is lost.
The flag is still cleared before each window, not after the reconcile. A
change that lands while a reconcile is running still schedules exactly
one more pass.
## Behavior change
A steady stream of notifications closer together than `debounce` now
**postpones** the reconcile until the stream pauses. Before, the watcher
reconciled about once per window throughout the stream. A revocation now
takes effect `debounce` seconds after delivery goes quiet, not within
`debounce` of its arrival. The README, the module docstring and the
`debounce` argument docs say so now.
## Tests
- `test_a_burst_of_changes_coalesces_into_a_debounce_window` now pins
**one** reconcile for six notifications spread 100 ms apart across a 600
ms window, where it pinned two. It keeps the anti-vacuity setup: the
puts come after the listener is attached and are spread out, and the
count is an equality check after settling past two windows. It also
checks that the single reconcile wrote all six skills.
- New: `test_a_change_during_a_reconcile_schedules_one_more`. A store
double delivers a new skill just after an armed reconcile has taken its
snapshot. The test asserts exactly two reconciles and checks that the
late skill reached disk.
- Mutation checks, each run against the two tests above:
- debounce removed (reconcile straight after the wake): the coalescing
test fails
- the previous single-window code: the coalescing test fails (2 ≠ 1)
- trailing window with the flag cleared after the reconcile: the
mid-reconcile test fails
`make lint format-check typecheck` and `uv run pytest packages/client
tests` pass: 1924 passed, 18 skipped.
## Follow-up for #211
#211 (`SkillSource` / `config_skills`) has not merged. Its
`test_the_debounce_spans_both_trigger_kinds` in
`tests/test_skills_source.py` pins the old behavior: `reconciles == 2`
and `source.reads == 1 + 2`. Once this lands, that test needs the same
edit: `reconciles == 1`, `source.reads == 1 + 1`, and the docstring
reworded to drop "schedules exactly one further pass".
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Overview**
> **`SkillWatcher`** debounce is now **trailing**: each delivery
notification restarts the quiet window, and reconcile runs only after
**`debounce`** seconds with no further changes. Bursts that used to
trigger about one reconcile per window (e.g. six spaced puts → two
passes) collapse to **one** pass that reads the store after the last
window.
>
> The worker loop clears the wake flag **before** each wait (unchanged
intent): a change **during** an in-flight reconcile still schedules
exactly one follow-up reconcile. Docs in **`README`**,
**`skills_watch`**, and **`watch_skills`** now describe “quiet for
`debounce`” instead of “within `debounce` of arrival,” including
revocation timing.
>
> Tests expect **one** reconcile for the spread burst, assert all six
skills on disk, and add
**`test_a_change_during_a_reconcile_schedules_one_more`** for the
mid-reconcile case.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
224f1ab. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>1 parent 715815f commit b214bbd
3 files changed
Lines changed: 67 additions & 19 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
848 | 848 | | |
849 | 849 | | |
850 | 850 | | |
851 | | - | |
| 851 | + | |
852 | 852 | | |
853 | 853 | | |
854 | 854 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
34 | | - | |
35 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
36 | 38 | | |
37 | 39 | | |
38 | 40 | | |
| |||
105 | 107 | | |
106 | 108 | | |
107 | 109 | | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
113 | 122 | | |
114 | 123 | | |
115 | 124 | | |
| |||
206 | 215 | | |
207 | 216 | | |
208 | 217 | | |
209 | | - | |
210 | | - | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
211 | 221 | | |
212 | 222 | | |
213 | 223 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
70 | | - | |
| 70 | + | |
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
78 | | - | |
| 77 | + | |
| 78 | + | |
79 | 79 | | |
80 | 80 | | |
81 | 81 | | |
| |||
85 | 85 | | |
86 | 86 | | |
87 | 87 | | |
88 | | - | |
89 | | - | |
| 88 | + | |
| 89 | + | |
90 | 90 | | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
91 | 128 | | |
| 129 | + | |
92 | 130 | | |
93 | 131 | | |
94 | 132 | | |
| |||
0 commit comments