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
14 changes: 11 additions & 3 deletions docs/conventions/hook-observability/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ text and for a genuine user message that arrives beside it.

This section moves no hook to a different event. The guard mods' context and rate-limit lines are a
[recorded exception](#recorded-exception-the-guard-mods-lines-and-telemetry-owner-approved-2026-10-03)
to the Frequency rule.
to the Frequency rule, and `rate-limit-guard`'s threshold line to the Phrasing rule.

- **Pointer**: for each channel's reader and phrasing, see
<https://code.claude.com/docs/en/hooks#add-context-for-claude>,
Expand Down Expand Up @@ -410,7 +410,8 @@ quiet skip needs a sanctioned helper call or an explicit `# silent-skip-ok:` ann
`context-guard`'s and `rate-limit-guard`'s mods add lines to tool results and prompts about the
session's context and rate-limit windows, which the Frequency rule's "no countdown or budget line
after tool results" would otherwise bar. They are admitted on this shape, and only on it (the owner
amended the What bullet on 2026-10-04, dropping the standing-rule sentence):
amended the What bullet twice on 2026-10-04: dropping the standing-rule sentence, then admitting
`rate-limit-guard`'s one directive):

- **When.** One line per boundary crossing, one per approach margin (a set number of points before
a boundary), and one restatement after a compaction, a resume, a `/branch`, a reload of the mod
Expand All @@ -419,7 +420,14 @@ amended the What bullet on 2026-10-04, dropping the standing-rule sentence):
- **What.** Each line names its plugin and a verdict worded as a fact. The verdict names no action,
claims no authority and gives no order. `context-guard`'s boundary lines add that continuing is
the user's call, and may be followed by the dumb-zone save note or an operator-configured
`zones.json` action; `rate-limit-guard`'s lines carry the verdict only. By default a line carries
`zones.json` action. `rate-limit-guard`'s lines carry the verdict only, except that the line at
the threshold ends with one directive, `Keep working.`, the only order this exception admits on a
context channel. The owner decided this on 2026-10-04: they rotate accounts by hand on the alerts,
and an interactive session waits out a usage limit on its own
(<https://code.claude.com/docs/en/interactive-mode#wait-for-a-usage-limit-to-reset>), so a line
read as a cue to stop would end work the session can finish. The observed stumble: on
2026-10-04 the owner saw sessions treat the earlier fact-only line, `at the 90% pause edge`, as a
reason to stop. By default a line carries
no raw count; the operator can add figures through the plugin's line-data option. The reading
behind the verdict stays on the plugin's status tools.
- **Telemetry.** The guard mods emit an envelope only on a fire that acts: lines sent, an operator
Expand Down
2 changes: 1 addition & 1 deletion plugins/rate-limit-guard/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rate-limit-guard",
"version": "0.14.2",
"version": "0.15.0",
"description": "Shared rate-limit guard for loop lanes and Claude: a hooks module writes the subscription rate-limit windows to a fixed machine-scope file and tells Claude where they stand at boundaries, a StopFailure hook records rate-limit stops reactively, and a reader contract fixes how consuming sessions pause and resume.",
"author": {
"name": "Melodic Software",
Expand Down
6 changes: 6 additions & 0 deletions plugins/rate-limit-guard/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
All notable changes to the `rate-limit-guard` plugin are documented here. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning.

## [0.15.0] - 2026-10-04

### Changed

- **Lines to Claude state facts and say to keep working; none implies a pause.** An interactive session waits out a usage limit and continues on its own, so the lines drop "pause edge" and name the threshold: `rate-limit-guard: 5-hour window at or above 95%, resets at 2026-10-03 21:00 UTC. Keep working.`, `nearing 95%`, and `5-hour window reset, now below 95%.`. Only the last threshold line of a batch ends "Keep working.". The operator-mode suggestion and the `/rate-limit-guard` status reply (`7% used, below 95%`) follow the same wording. The toast, the notice row and the transcript line keep "pause edge", and the loop lanes' 95% pause floor is unchanged.

## [0.14.2] - 2026-10-04

### Changed
Expand Down
11 changes: 7 additions & 4 deletions plugins/rate-limit-guard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,19 @@ of a prompt; a crossing seen when a turn ends reaches Claude with the next promp

| When | Line |
|---|---|
| The window reaches the approach mark (90%) | once per window, "nearing the 95% pause edge" |
| The window reaches the line threshold (95%) | once per window, "at the 95% pause edge", with the reset time |
| The window reaches the approach mark (90%) | once per window, "nearing 95%" |
| The window reaches the line threshold (95%) | once per window, "at or above 95%", with the reset time and "Keep working." |
| The window resets (its reset time passes, or it leaves the reading) after reaching the threshold | once; the approach and threshold lines can then fire again |
| After a compaction (not the precompute kind), and after `/resume` or `/branch` | the verdict for each window at or above the approach mark, once; nothing when none is |
| After `/clear`, and when the module loads into a session that already has turns (a `--resume` launch, a reload after an options change, a hooks-worker restart) | the verdict for each window at or above the threshold, once; nothing when none is |

Use only rises within a window, so a reading that dips below a mark sends nothing and does not
re-arm that mark's line. No other tool call or prompt carries a line. Each window gets its own
line, its verdict only, for example `rate-limit-guard: 5-hour window at the 95% pause edge, resets
at 2026-10-03 21:00 UTC.`. Every line carries its verdict; `rate_limit_line_data` chooses what
line, for example `rate-limit-guard: 5-hour window at or above 95%, resets at 2026-10-03 21:00 UTC. Keep
working.`; when several windows reach the threshold together, only the last line ends "Keep
working.". No line tells Claude to pause: an interactive session
[waits out a usage limit](https://code.claude.com/docs/en/interactive-mode#wait-for-a-usage-limit-to-reset)
and continues on its own. Every line carries its verdict; `rate_limit_line_data` chooses what
goes with it: the window's name (`window`), its use (`percent`) and its reset time (`reset`). Without `window` the line says "a
rate-limit window". A line never carries the account email or the session name. Subagents get no
line. Each line sent to Claude is also written as sent to the debug log (`claude --debug`). The
Expand Down
Loading
Loading