Skip to content

chore(dev→main): routine PR cadence for CodeRabbit review#5

Merged
Snider merged 11 commits into
mainfrom
dev
Apr 27, 2026
Merged

chore(dev→main): routine PR cadence for CodeRabbit review#5
Snider merged 11 commits into
mainfrom
dev

Conversation

@Snider

@Snider Snider commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Routine dev→main PR opened by Hephaestus PR-cadence task.

This PR exists to:

  1. Trigger CodeRabbit auto-review of accumulated dev work
  2. Surface any blocking review feedback before merge
  3. Keep main current with dev once approved

ahead_by: 11 commit(s) (per gh api compare)

If CodeRabbit clears with no blocking comments, this PR is eligible for gh pr merge --merge (real merge commit, no force-push). Conflicts and review feedback should be addressed on the dev branch before merge.

Co-authored-by: Hephaestus hephaestus@cladius

Snider and others added 11 commits April 14, 2026 17:22
Co-Authored-By: Virgil <virgil@lethean.io>
Removes testify + davecgh/go-spew + pmezard/go-difflib from go.mod;
rewrites assert/require calls in *_test.go to stdlib t.Fatalf patterns.
Adds assertions_test.go with local helpers for contains/len/eventually/
delta/panic checks. go mod tidy + go vet + go test all clean.

Closes tasks.lthn.sh/view.php?id=672

Co-authored-by: Codex <noreply@openai.com>
Via-codex-lane: Cladius-solo dispatch (Mac codex CLI)
Added `// Note:` intrinsic annotations on stdlib imports in ratelimit.go
and sqlite.go — documenting why each stdlib dependency has no core
primitive replacement (net/url URL semantics, slices operations,
sync.RWMutex, time sliding-window math, database/sql transaction API).

Verification: GOCACHE=/tmp/... go vet ./... passes.

Closes tasks.lthn.sh/view.php?id=673

Co-authored-by: Codex <noreply@openai.com>
Added `// Note:` annotations to go.mod external direct dependencies
documenting why they have no core primitive replacement:
- gopkg.in/yaml.v3: YAML parse for rate limit rules config
- modernc.org/sqlite: pure-Go SQLite for state persistence

Verification: GOWORK=off go vet ./... passes.

Closes tasks.lthn.sh/view.php?id=797

Co-authored-by: Codex <noreply@openai.com>
Dropped the doubly-stale path `dappco.re/go/core/go-ratelimit` (both
"core" segment AND "go-" prefix redundant) to align with graduated
repos: dappco.re/go/{name}. No *.go self-imports existed — single-line
change. `go build ./...` passes.

Closes tasks.lthn.sh/view.php?id=796

Co-authored-by: Codex <noreply@openai.com>
Add tests/cli/ratelimit/Taskfile.yaml + main.go AX-10 driver per
RFC-CORE-008-AGENT-EXPERIENCE.md §10.

Driver constructs a YAML-backed RateLimiter in a temp dir with the
ProviderGemini default profile, calls CanSend + Decide for the
gemini-2.5-flash model with 100 estimated tokens, prints the
resulting Decision as JSON, then Persist()s. Exits 0 on success.

go.mod was already at v0.8.0-alpha.1; no dep bumps in this commit.

Closes tasks.lthn.sh/view.php?id=391

Co-Authored-By: Athena <athena@lthn.ai>
First slot of the AX-10 triad completion sweep (Mantis #920). Adds
TestRatelimit_CanSend_Bad demonstrating that CanSend returns false when
RecordUsage has filled the RPM quota.

Codex (xhigh) made it through Step 1+3 of the milestone-shaped brief but
budget-exhausted before the remaining 16 missing _Bad/_Ugly siblings.
Filed as scope-disciplined progress; remaining slots tracked as separate
follow-up ticket per the don't-merge-unfinished rule.

Test verified by inspection (uses existing newTestLimiter helper, follows
the same idiom as TestRatelimit_CanSend_Good). Local 'go test' blocked
by the pre-existing task #28 workspace forge dep break (404 on
dappco.re/go/forge@v0.8.0-alpha.1); CI will validate at next dev push.

Found-by: Cerberus (mechanism-tier audit, AX-10 triad gap)
Audit-by: codex (gpt-5.5 xhigh, Bash-direct dispatch via Cerberus session)
Closes-partial tasks.lthn.sh/view.php?id=920

Co-Authored-By: Codex <noreply@openai.com>
Co-Authored-By: Cerberus <cerberus@lthn.ai>
Co-Authored-By: Virgil <virgil@lethean.io>
- Persisted/future timestamp normalization under clock skew
- Injectable internal clock for deterministic tests
- retryAfterForTokens overflow guard
- DayCount increment saturation (no silent wrap-around)
- Added clock-skew, overflow, and lock-discipline test coverage

Note: design-level Decide/RecordUsage gap residual (medium) — documented in threats.md, requires reservation API to fully close.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=922
Audit of ratelimit_test.go confirmed every Test*_Good has matching
_Bad (failure mode) and _Ugly (edge case) siblings. 852 lines of test
coverage added. Race suite passes.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=925
…ngs (#925)

Filled all 16 missing _Bad/_Ugly siblings enumerated in #925:
- ratelimit_test.go: CanSend_Ugly, RecordUsage_{Bad,Ugly}, Reset_{Bad,Ugly},
  WaitForCapacity_{Bad,Ugly}, Stats_{Bad,Ugly}, AllStats_{Bad,Ugly},
  DefaultQuotas_{Bad,Ugly}, TokenTotals_{Bad,Ugly}
- iter_test.go: Iterators_Bad, Iterators_Ugly

Coverage: concurrent races, negative tokens, unknown models, context
cancellation, capacity boundary, type-mismatch fallbacks, mutate-while-
iterating. Race detector passes.

Closes tasks.lthn.sh/view.php?id=925

Co-authored-by: Codex <noreply@openai.com>
- Removed net/url; URL parsing/escape replaced with core.URLNormalize +
  core.URLPathEscape + local authority validation
- Removed http.StatusOK constant dependency

net/http remains because CountTokens is a public API using *http.Client.
Full net/http removal would require changing/removing the public
CountTokens contract — outside this batch's bounded scope.

Verification: go test ./... passed via temp modfile.

Co-authored-by: Codex <noreply@openai.com>
Refs tasks.lthn.sh/view.php?id=389
@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@Snider has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 19 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5a625059-b33c-443a-abfb-56b93ac98d00

📥 Commits

Reviewing files that changed from the base of the PR and between a35d0f7 and b4cfaf7.

📒 Files selected for processing (11)
  • assertions_test.go
  • error_test.go
  • go.mod
  • iter_test.go
  • ratelimit.go
  • ratelimit_test.go
  • sqlite.go
  • sqlite_test.go
  • tests/cli/ratelimit/Taskfile.yaml
  • tests/cli/ratelimit/main.go
  • threats.md

Comment @coderabbitai help to get the list of available commands and usage tips.

@Snider

Snider commented Apr 27, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 27, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copilot AI 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.

Pull request overview

This dev→main cadence PR brings in recent go-ratelimit hardening work: threat-analysis notes, a small CLI driver, core limiter fixes (clock-skew + overflow handling), and a broad test refactor away from stretchr/testify.

Changes:

  • Harden RateLimiter time handling by injecting a clock (rl.now), normalizing future-dated persisted usage before pruning, and saturating counters to avoid overflows.
  • Refactor tests to remove stretchr/testify, adding local assertion/message helpers and expanding coverage (including new threat-focused tests).
  • Update module metadata (module path rename, dependency cleanup) and add an AX-10 style CLI driver + Taskfile for black-box exercising the public API.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
threats.md Documents identified threats (clock skew, integer overflow, race semantics) and mitigations/risks.
ratelimit.go Adds injectable clock + future normalization; fixes overflow in token retry logic; adds safe day-count increment; tweaks CountTokens URL validation/escape and status constant.
sqlite.go Adds explanatory comments on intrinsic stdlib imports.
assertions_test.go Introduces local assertion/message helpers used across tests (replacing testify).
ratelimit_test.go Large rewrite to use local assertions and add many additional cases, including threat regressions.
sqlite_test.go Rewrites SQLite tests to use local assertions and expands coverage.
iter_test.go Updates iterator tests to use local assertions; adds additional cases.
error_test.go Updates error-path tests to use local assertions.
tests/cli/ratelimit/main.go Adds a small CLI driver to exercise the public API without importing package test files.
tests/cli/ratelimit/Taskfile.yaml Adds Taskfile tasks to build/run the CLI driver in an isolated cache/workspace setup.
go.mod Renames module path and removes testify dependency; adds comments on retained deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ratelimit_test.go
Comment on lines +2356 to +2361
if err :=

// Persist and reload
require.NoError(t, rl.Persist())
// Persist and reload
rl.Persist(); err != nil {
t.Fatal(testUnexpectedErrorMessage(err))
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

This if err := is split across lines, which is invalid Go syntax and will prevent the test from compiling. Rewrite it as if err := rl.Persist(); err != nil { ... } (or assign err separately).

Copilot uses AI. Check for mistakes.
Comment thread ratelimit_test.go
Comment on lines +911 to +916
}); recovered !=

// --- Phase 0: Stats ---
nil {
t.Fatal(testUnexpectedPanicMessage(recovered))
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

This testRecoverPanic result check is syntactically broken (}); recovered != followed by a comment and then nil {), which will not compile. It should be }); recovered != nil { ... } with the phase header comment moved outside the if condition.

Copilot uses AI. Check for mistakes.
Comment thread sqlite_test.go
Comment on lines +544 to +549
if err :=

// Verify the final persisted state survives a reload.
require.NoError(t, rl.Persist())
require.NoError(t, rl.Close())
// Verify the final persisted state survives a reload.
rl.Persist(); err != nil {
t.Fatal(testUnexpectedErrorMessage(err))
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

This if err := statement is split across multiple lines (if err := on its own line), which is invalid Go syntax and will prevent the test from compiling. Combine it into a single if err := rl.Persist(); err != nil { ... } form.

Copilot uses AI. Check for mistakes.
Comment thread ratelimit_test.go
Comment on lines +773 to +774
if // should not panic
!testIsEmpty(rl.State) {

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

This if statement is broken by an inline comment (if // should not panic), which is invalid Go syntax. Move the comment above the if line so the condition immediately follows if.

Suggested change
if // should not panic
!testIsEmpty(rl.State) {
// should not panic
if !testIsEmpty(rl.State) {

Copilot uses AI. Check for mistakes.
Comment thread ratelimit_test.go
Comment on lines +206 to +210
rl.RecordUsage(model, 50, 40)
if // 90 tokens
rl.CanSend(model, 20) {
t.Fatal(testExpectedFalseMessage("should reject when 90+20=110 > 100"))
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

This if condition is malformed (if // 90 tokens on one line and the expression on the next), which will not compile. Move the comment outside the if header so the boolean expression is on the same line as if.

Copilot uses AI. Check for mistakes.
Comment thread error_test.go
Comment on lines +106 to +111
if err :=

// Save some quotas so loadQuotas succeeds, then corrupt the state tables.
require.NoError(t, rl.Persist())
// Save some quotas so loadQuotas succeeds, then corrupt the state tables.
rl.Persist(); err != nil {
t.Fatal(testUnexpectedErrorMessage(err))
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

This if err := is broken across multiple lines, which is invalid Go syntax and will stop the test suite from compiling. Rewrite it as a single-line short variable declaration in the if statement.

Copilot uses AI. Check for mistakes.
Comment thread error_test.go
Comment on lines +571 to +578
if err :=

// Save valid quotas first.
require.NoError(t, store.saveQuotas(map[string]ModelQuota{
"test": {MaxRPM: 10},
}))
// Save valid quotas first.
store.saveQuotas(map[string]ModelQuota{
"test": {MaxRPM: 10},
}); err != nil {
t.Fatal(testUnexpectedErrorMessage(err))
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

This if err := block is split across lines (with the assignment on its own line), which is invalid Go syntax and breaks compilation. Combine the assignment and condition into a standard if err := ...; err != nil { ... } statement.

Copilot uses AI. Check for mistakes.
Comment thread ratelimit_test.go
Comment on lines +191 to +195
rl.RecordUsage(model, 50, 40)
if // 90 tokens
!rl.CanSend(model, 10) {
t.Fatal(testExpectedTrueMessage("should allow at exact TPM limit (90+10=100)"))
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

This if statement is split by an inline comment (if // 90 tokens), producing invalid Go syntax. Move the comment above the if (or after the condition) so the if keyword is immediately followed by a boolean expression.

Copilot uses AI. Check for mistakes.
Comment thread go.mod
// SPDX-License-Identifier: EUPL-1.2

module dappco.re/go/core/go-ratelimit
module dappco.re/go/ratelimit

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

The module path is changed here, which is a breaking change for downstream importers. If this rename is intentional, please update repository documentation/examples (README/docs badges/import snippets) and any external references accordingly; if not, revert the module path change.

Copilot uses AI. Check for mistakes.
Comment thread sqlite_test.go
Comment on lines +211 to +234
if err :=

// Save initial state.
require.NoError(t, store.saveState(map[string]*UsageStats{
"model-a": {
Requests: []time.Time{now, now, now},
DayStart: now,
DayCount: 3,
},
}))

// Save new state (should replace).
require.NoError(t, store.saveState(map[string]*UsageStats{
"model-b": {
Requests: []time.Time{now},
DayStart: now,
DayCount: 1,
},
}))
// Save initial state.
store.saveState(map[string]*UsageStats{
"model-a": {
Requests: []time.Time{now, now, now},
DayStart: now,
DayCount: 3,
},
}); err != nil {
t.Fatal(testUnexpectedErrorMessage(err))
}
if err :=

// Save new state (should replace).
store.saveState(map[string]*UsageStats{
"model-b": {
Requests: []time.Time{now},
DayStart: now,
DayCount: 1,
},
}); err != nil {
t.Fatal(testUnexpectedErrorMessage(err))
}

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

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

These if err := statements are split across lines (the if err := appears by itself), which is invalid Go syntax and breaks compilation. Rewrite each as if err := store.saveState(...); err != nil { ... } without a newline between := and the call.

Copilot uses AI. Check for mistakes.
@Snider Snider merged commit 2f2577b into main Apr 27, 2026
9 of 11 checks passed
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.

2 participants