Skip to content

fix(rate-limit-guard): tell Claude to keep working at the threshold - #6326

Merged
kyle-sexton merged 5 commits into
mainfrom
fix/rate-limit-guard-keep-working
Oct 4, 2026
Merged

kyle-sexton merged 5 commits into
mainfrom
fix/rate-limit-guard-keep-working

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

No related issue: owner decision 2026-10-04 that guard lines must not tell Claude to stop

Summary

rate-limit-guard's lines to Claude no longer say "pause edge", which read as a cue to stop. They name the threshold as a fact, and the line at the threshold ends Keep working. (once per batch). The owner rotates accounts by hand on the alerts, and interactive Claude Code waits out a usage limit on its own (docs). Loop lanes keep their fixed 95% pause floor: -p and --bg sessions do not auto-wait.

Fix

  • plugins/rate-limit-guard/hooks/register.tsx: model-facing lines and the /rate-limit-guard status reply use threshold wording (at 95%, nearing 95%, reset, now below 95%); the last threshold line of a batch ends Keep working.. The toast, notice row and transcript line keep "pause edge". The status tool's JSON keeps lanes_pause_edge.
  • docs/conventions/hook-observability/README.md: the recorded guard-mods exception admits exactly one directive, Keep working., on rate-limit-guard's threshold line, citing the 2026-10-04 owner decision. The general rule (context channels carry facts, not orders) is unchanged.
  • Version 0.15.0 with a CHANGELOG entry; README updated.

Verification

  • claude plugin test plugins/rate-limit-guard (fresh config dir): 129 pass, 0 fail.
  • scripts/check-changelog-parity.sh --check-bump origin/main: pass.
  • scripts/check-loop-lane-floor-drift.sh: 7 consumers match the floor, no unregistered copy.
  • scripts/sync-shared-copies.sh --check: all 335 registered copies match.

Related

🤖 Generated with Claude Code

kyle-sexton and others added 2 commits October 4, 2026 14:23
An interactive session waits out a usage limit and continues on its
own, so the lines sent to Claude no longer say "pause edge". They name
the threshold and, at it, end "Keep working." (once per batch). The
operator-mode suggestion and the /rate-limit-guard status reply use the
same wording, and the status tool's JSON drops lanes_pause_edge. The
toast, notice row and transcript line keep their wording, and the loop
lanes' 95% pause floor is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The recorded guard-mods exception now admits one directive on a
context channel: rate-limit-guard's threshold line ends "Keep working.",
per the owner decision of 2026-10-04 (accounts are rotated by hand on
the alerts, and an interactive session waits out a usage limit itself).
The general facts-not-orders rule is unchanged.

The status tool's JSON keeps lanes_pause_edge: it is a fact consumers
may read, so the earlier removal and its CHANGELOG clause are reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton marked this pull request as ready for review October 4, 2026 18:25
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-04T18:29:11.643274Z e8d718c Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 43s —— View job


Code review complete

  • Gather context (PR body, diff, CLAUDE.md/AGENTS.md, REVIEW.md)
  • Review changed files for correctness and alignment with guidelines
  • Verify candidate findings adversarially
  • Post inline comments for findings / summary

No findings. This is a clean, well-scoped wording change.

What I checked:

  • plugins/rate-limit-guard/hooks/register.tsx: the new modelVerdict helper and the dueLines "last edge event in the batch gets Keep working." logic (lastEdge = events.map(([, event]) => event).lastIndexOf('edge')). Traced every call site (clause, toastBody, statusText) to confirm the human-facing paths (toast/notice/transcript) still use verdictText ("pause edge") while the model-facing paths (lines to Claude, FYI/operator suggestion, /rate-limit-guard status reply) use modelVerdict (threshold wording). The directive is correctly scoped to event === 'edge' only, never to approach/quiet/reset.
  • plugins/rate-limit-guard/hooks/rate-limit-guard.test.ts: test coverage is thorough and specifically exercises the multi-window-at-edge case (only the last line by window order gets "Keep working."), the mixed edge+approach batch (only the edge line gets it), and the restate-after-compaction case (no edge events → no directive on any line).
  • docs/conventions/hook-observability/README.md: the updated recorded-exception section is internally consistent — it now admits exactly one directive (Keep working.) on rate-limit-guard's threshold line, with rationale (owner rotates accounts by hand; interactive sessions already wait out usage limits on their own), and the general Phrasing rule (context channels state facts, not orders) is otherwise unchanged.
  • README.md, CHANGELOG.md, plugin.json: version bump (0.14.0 → 0.15.0), CHANGELOG entry, and README table/prose all match the actual line output in the tests.
  • No security, atomicity, or audit-log concerns apply (text-only change, no multi-record writes, no auth paths). This repo runs a separate security lane (pr-review-security-hosted.yml), so security scope is excluded here regardless.

Author-claimed, not independently re-run by me: claude plugin test (129 pass), check-changelog-parity.sh, check-loop-lane-floor-drift.sh, sync-shared-copies.sh results stated in the PR body.
· branch fix/rate-limit-guard-keep-working

@claude

claude Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 47s —— View job


Security review complete

  • Gather context (PR diff, changed files)
  • Run skip-gate check
  • Review changed files for security-relevant surface
  • Check instruction-surface deletions against protected classes
  • Report findings

No security issues found.

This PR only changes wording in rate-limit-guard's context/status lines, a doc update, tests, and a version/CHANGELOG bump — no new injection surface, no secret handling, no auth/access-control code.

Two things I checked specifically given this PR's shape, both clear:

  • Hardcoded directive, not data-derived. The new Keep working. suffix in plugins/rate-limit-guard/hooks/register.tsx#L461-L465 is a fixed string appended by position (i === lastEdge), not built from rate-limit API data, so there's no way for attacker-influenced input to shape the directive text.
  • Instruction-surface check. docs/conventions/hook-observability/README.md narrows the "gives no order" clause of the recorded guard-mods exception to admit this one directive. I checked it against the Gate 0 protected classes in docs/conventions/instruction-exception-register/README.md: the actual enforcement mechanism for automated/loop lanes (lanes_pause_edge, register.tsx#L475) is untouched by this PR — the text change only affects what interactive sessions are told, not the hard pause floor loop lanes read independently. So this isn't a deletion of an agent-authority-class guardrail, just a documented, owner-approved phrasing exception.

GitHub Actions hardening is out of scope for this lane (zizmor's advisory lane covers it), and no workflow files are touched here anyway.

@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

claude-security-review has reviewed this pull request through 6777d1e; a later push is reviewed from there.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e8d718c777

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/conventions/hook-observability/README.md Outdated
Comment thread plugins/rate-limit-guard/hooks/register.tsx Outdated
@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

claude-review has reviewed this pull request through 6777d1e; a later push is reviewed from there.

Lines to Claude read 'at 95% (97% used)' and the status reply '97% used,
at 95%' once usage passed the threshold. The edge verdict now reads 'at or
above'. The hook-observability exception names the observed stumble behind
its 'Keep working.' directive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 4m 22s —— View job


Code review complete (incremental: e8d718c → 5f26b56)

  • Gather context (PR body, incremental diff, AGENTS.md/CLAUDE.md, instruction-economy rule)
  • Review changed files for correctness and alignment with guidelines
  • Verify candidate findings adversarially
  • Post findings

This commit fixes both things Codex flagged on the prior revision: modelVerdict's edge case now reads at or above ${threshold}% instead of at ${threshold}% (register.tsx#L147), and docs/conventions/hook-observability/README.md now names a dated, owner-observed stumble (sessions treating the pre-#6316 fact-only line, at the 90% pause edge, as a reason to stop) to satisfy the instruction-economy evidence requirement. I traced both call sites of modelVerdict (clause for the lines to Claude, and statusText for the /rate-limit-guard status reply) and confirmed both now render the non-contradictory wording. The historical "90% pause edge" quote checks out against d70ea53, where PAUSE_EDGE was still 90 before #6316 raised it to 95.

One finding, cross-file, not on a line this commit touched:

plugins/rate-limit-guard/README.md:53 — the "Lines to Claude" table still reads once per window, "at 95%", with the reset time and "Keep working.". That was accurate as of e8d718c (when modelVerdict's edge case still said at 95%), but this commit's fix to register.tsx (#L147) changed the actual line to at or above 95% without updating this table row, three lines above the prose example in the same file that was updated to at or above 95% in this commit (README.md#L58). The table and the prose now disagree within the same document — the exact "internally contradictory" shape Codex's P2 comment flagged, just reintroduced here in docs instead of code. Suggest: once per window, "at or above 95%", with the reset time and "Keep working.".

No other findings. The test file's expectation updates match modelVerdict's new output exactly (spot-checked several, including the multi-window and operator-mode cases), and the CHANGELOG entry's wording is consistent with the code.
· branch fix/rate-limit-guard-keep-working

@claude

claude Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 25s —— View job


Security review complete

  • Gather context (PR body, incremental diff since e8d718c, custom instructions)
  • Run /review:security-review (incremental scope)
  • Run skip-gate check
  • Report findings

No security issues found.

Skip-gate reasoning: this increment (diff since e8d718c, in .claude-lane/incremental.diff) has no security-relevant surface. It is two cosmetic changes, both addressing the prior Codex review round:

  • plugins/rate-limit-guard/hooks/register.tsx L147: modelVerdict's edge wording changed from 'at' to 'at or above', still a hardcoded string keyed by event, not derived from any external/attacker-influenced input. rate-limit-guard.test.ts updates its expected strings to match; no logic or control flow changed.
  • docs/conventions/hook-observability/README.md L428-L430: adds the observed-stumble evidence sentence for the Keep working. exception. This adds grounding to an existing documented exception — it does not delete, narrow, or soften a standing instruction, so the instruction-surface/protected-class check doesn't apply here. The enforcement mechanism (lanes_pause_edge, the loop-lane pause floor) is untouched.
  • plugins/rate-limit-guard/README.md and CHANGELOG.md: prose-only, same wording update, no behavior change.

No injection surface, no secret handling, no auth/access-control code in this increment. GitHub Actions hardening is out of scope for this lane (zizmor's advisory lane covers it); no workflow files are touched.
· branch fix/rate-limit-guard-keep-working

@claude

claude Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 3m 45s —— View job


Code review complete (incremental: 5f26b56 → 2d2b5f0)

  • Gather context (PR body, incremental diff, AGENTS.md/REVIEW.md, prior review rounds)
  • Review the one changed file (plugins/rate-limit-guard/README.md) against register.tsx's actual output
  • Verify candidate findings adversarially
  • Report findings

No findings.

This increment is the one-line fix for the exact issue flagged in the previous review round on this PR: plugins/rate-limit-guard/README.md#L53 now reads "at or above 95%" instead of "at 95%".

I checked this against:

  • modelVerdict's actual edge output ('at or above' + ' ' + threshold + '%', per register.tsx, unchanged in this increment) — the table row now matches what the code actually emits.
  • Internal consistency within the same file — the row now agrees with the prose example three lines below it (L60-61), "5-hour window at or above 95%...", which this PR's prior commit already updated. The table/prose contradiction a prior Claude review round flagged is resolved.
  • The adjacent approach-mark row (L52), "nearing 95%" — still matches modelVerdict's approach case, untouched and correct.

No other lines in this file changed in this increment. All other files in this PR were reviewed in the prior round at 5f26b56 and are unchanged since.
· branch fix/rate-limit-guard-keep-working

@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 4, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 4, 2026
…keep-working

# Conflicts:
#	plugins/rate-limit-guard/.claude-plugin/plugin.json
#	plugins/rate-limit-guard/CHANGELOG.md
#	plugins/rate-limit-guard/hooks/rate-limit-guard.test.ts
@claude

claude Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 6s —— View job


Security review complete

  • Gather context (PR body, diff, custom instructions)
  • Invoke /review:security-review for this PR
  • Report findings

Skip gate: no new security-relevant surface.

HEAD (6777d1e) is a merge of origin/main (c08e178) into this branch. git diff origin/main...HEAD --stat shows the PR's effective diff is unchanged from what was already reviewed at 2d2b5f0 — still the same 6 files, +79/-54 across docs/conventions/hook-observability/README.md, plugins/rate-limit-guard/{.claude-plugin/plugin.json,CHANGELOG.md,README.md,hooks/register.tsx,hooks/rate-limit-guard.test.ts}. The merge pulled in main's independent history (including #6267) without touching or conflicting with any line this PR added, so no new content entered the PR's scope.

Per the skip gate in /review:security-review ("this head already has a successful security review that still applies"), I'm not re-running the full hunt. The prior rounds on this PR (through 2d2b5f0) already covered:

  • The hardcoded Keep working. directive in register.tsx is positionally appended (i === lastEdge), not derived from any rate-limit API data or other attacker-influenced input — no injection surface.
  • The docs/conventions/hook-observability/README.md exception narrows the "gives no order" clause but doesn't touch the enforcement mechanism (lanes_pause_edge, the loop-lane pause floor), which loop lanes read independently of the model-facing text — so this isn't a deletion of an agent-authority-class guardrail per the instruction exception register, just a documented, owner-approved phrasing exception with observed-stumble evidence now recorded.
  • No secrets, auth, or access-control code touched; no GitHub Actions workflow files touched (zizmor's lane covers that surface regardless).

No security issues found.
· branch fix/rate-limit-guard-keep-working

@claude

claude Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 5m 4s —— View job


Code review complete (skip gate: no new content on this head)

  • Gather context (PR body, diff, custom instructions)
  • Invoke /review:code-review skill per custom instructions
  • Compare current head against last-reviewed commit
  • Report

No new findings — skip gate applies.

Head 6777d1e is fix/rate-limit-guard-keep-working merged with origin/main (bringing in unrelated c08e178, #6267). I confirmed this merge introduces no new content to this PR:

  • git diff origin/main...HEAD (the PR's net contribution) has the exact same per-file +/- counts as the changed_files list in this PR's own description, and is byte-identical to git diff c08e178...2d2b5f0 — i.e. the PR's own diff is unchanged since commit 2d2b5f0.
  • git merge-base origin/main HEAD == c08e178 == origin/main HEAD, so the merge was a clean fast-forward-style incorporation with no conflict resolution to review.
  • 2d2b5f0 already received a clean code review in this thread (no findings) after two prior rounds (e8d718c, 5f26b56) fixed Codex's two P1/P2 findings — the internally-contradictory "at 95%" wording in register.tsx's modelVerdict and the missing repeated-stumble evidence in docs/conventions/hook-observability/README.md.

I independently re-verified the fixed state is still intact at the current head, not just trusting the prior rounds' claims:

No inline comments to post; nothing on this head is new relative to what two prior Claude rounds and Codex already reviewed and verified fixed.
· branch fix/rate-limit-guard-keep-working

@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 4, 2026
Merged via the queue into main with commit 9f2041c Oct 4, 2026
16 checks passed
@kyle-sexton
kyle-sexton deleted the fix/rate-limit-guard-keep-working branch October 4, 2026 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant