Skip to content

fix(paging): stop calendar and Gmail listing on a repeated page token - #1004

Merged
steipete merged 2 commits into
openclaw:mainfrom
SebTardif:fix/repeated-page-tokens
Aug 25, 2026
Merged

fix(paging): stop calendar and Gmail listing on a repeated page token#1004
steipete merged 2 commits into
openclaw:mainfrom
SebTardif:fix/repeated-page-tokens

Conversation

@SebTardif

Copy link
Copy Markdown
Contributor

What Problem This Solves

gog calendar events --all (and any other path that lists every calendar) walks CalendarList.List with no memory of page tokens it has already seen. Gmail backup ID listing does the same on users.messages.list. If Google repeats nextPageToken, both loops never finish.

Why

The repo already has this guard. collectAllPages errors with pagination loop: repeated page token. Photos Picker and Drive changes do the same with a local seen-token map. listCalendarList is in package cmd, so it now calls collectAllPages instead of growing a second helper. Gmail backup lives under internal/backup/gmail and cannot import cmd, so it adds the same local seenTokens map Photos Picker already uses.

User Impact

A stuck Google page token now fails with repeated page token instead of hanging gog calendar events --all or a Gmail backup list until the process is killed.

Evidence

terminal output from the unpatched loops versus this patch, using a Calendar httptest server and a Gmail source that always return nextPageToken=stuck.

Unpatched (300ms context; the HTTP peer answers immediately, so the deadline is the only stop):

$ go test ./internal/cmd/ -count=1 -timeout 5s -v -run TestListCalendarListRejectsRepeatedPageToken
=== RUN   TestListCalendarListRejectsRepeatedPageToken
    calendar_list_test.go:115: err = context deadline exceeded
--- FAIL: TestListCalendarListRejectsRepeatedPageToken (0.30s)
FAIL

$ go test ./internal/backup/gmail/ -count=1 -timeout 5s -v -run TestListMessageIDsRejectsRepeatedPageToken
=== RUN   TestListMessageIDsRejectsRepeatedPageToken
    fetch_test.go:146: err = list Gmail backup messages: context deadline exceeded
--- FAIL: TestListMessageIDsRejectsRepeatedPageToken (0.30s)
FAIL

Patched (same commands, same stuck token, returns immediately):

$ go test ./internal/cmd/ -count=1 -timeout 10s -v -run TestListCalendarListRejectsRepeatedPageToken
=== RUN   TestListCalendarListRejectsRepeatedPageToken
    calendar_list_test.go:117: err = pagination loop: repeated page token "stuck"
--- PASS: TestListCalendarListRejectsRepeatedPageToken (0.00s)
PASS

$ go test ./internal/backup/gmail/ -count=1 -timeout 10s -v -run TestListMessageIDsRejectsRepeatedPageToken
=== RUN   TestListMessageIDsRejectsRepeatedPageToken
    fetch_test.go:148: err = list Gmail backup messages: repeated page token "stuck"
--- PASS: TestListMessageIDsRejectsRepeatedPageToken (0.00s)
PASS

$ go run proof_gmail_pages.go
elapsed=0s ids=[] err=list Gmail backup messages: repeated page token "stuck"

go test ./internal/cmd/ ./internal/backup/gmail/ -count=1 also completed on this tree.

Real behavior proof

  • Behavior or issue addressed: Repeated Google nextPageToken values could hang calendar listing (--all) and Gmail backup ID listing.
  • Real environment tested: macOS Darwin 25.6.0 arm64, Go go1.26.6, full clone at /tmp/pr-gogcli-pages on fix/repeated-page-tokens from upstream/main.
  • Exact steps or command run after this patch: From /tmp/pr-gogcli-pages, ran the same go test commands shown above against a Calendar httptest that always returns nextPageToken=stuck, then ran go run proof_gmail_pages.go which calls exported ListMessageIDs with a source that always returns NextPageToken "stuck".
  • Evidence after fix: terminal output above. Calendar listing now returns pagination loop: repeated page token "stuck" in 0.00s. Gmail ListMessageIDs returns list Gmail backup messages: repeated page token "stuck" with elapsed=0s.
  • Observed result after fix: The stuck token no longer runs until a context deadline. The process returns the repeated-token error on the next page instead of hanging.
  • What was not tested: A live Google CalendarList or Gmail messages.list response that actually repeats a token. That requires a faulty Google page, which we cannot force from a healthy account.

Related

  • Same-repo guard already used by collectAllPages in internal/cmd/paging.go, Photos Picker (errPhotosPickerRepeatedPage), and Drive changes.
  • Calendar listing without a seen-set dates to #131 (9977c0be, 2026-02-15, 184 days ago).
  • Gmail backup ID paging dates to 12461f5d (2026-06-13, 66 days ago).

listCalendarList now uses collectAllPages. Gmail backup ID listing
rejects a repeated NextPageToken the same way Photos Picker already
does, so a stuck Google token cannot hang --all or backup.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@clawsweeper

clawsweeper Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Aug 18, 2026
@clawsweeper

clawsweeper Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed August 24, 2026, 9:16 PM ET / August 25, 2026, 01:16 UTC.

ClawSweeper review

What this changes

The PR detects repeated continuation tokens in calendar-list and Gmail backup message-ID pagination, with regression coverage for both paths.

Regression provenance

Possible regression — probable (reviewed change; reproduction). No predecessor PR is attributed.

Merge readiness

Blocked until stronger real behavior proof is added - 3 items remain

This focused reliability fix is still needed: current main retains both unguarded loops, and the patch has no code-level or security finding. Before merge, the Gmail half needs production-transport proof rather than only a fake Source implementation.

Priority: P2
Reviewed head: f68fe084483d7d3ece9efc01e62e73ee2772cc5c

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The implementation is strong and focused, but the incomplete Gmail production-path proof remains a merge gate.
Proof confidence 🦐 gold shrimp (3/6) Needs stronger real behavior proof before merge: The Calendar harness uses the real Calendar client, but the Gmail evidence uses a fake Source rather than the production ServiceSource and Google API transport; add redacted after-fix terminal proof for that path before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs stronger real behavior proof before merge: The Calendar harness uses the real Calendar client, but the Gmail evidence uses a fake Source rather than the production ServiceSource and Google API transport; add redacted after-fix terminal proof for that path before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 5 items Current-main gap: Current main still advances CalendarList pagination directly to the returned token without a seen-token check.
Current-main Gmail gap: Current main likewise advances Gmail backup message-ID pagination directly to the returned page token.
Existing guard reuse: The PR routes calendar listing through the repository’s existing collector, which trims and rejects a previously seen token before another fetch.
Findings None None.
Security None None.

Live Verification

Command: go test ./internal/cmd ./internal/backup/gmail -count=1 -run 'Test(ListCalendarList|ListMessageIDs)RejectsRepeatedPageToken'

Result: FAIL (failed) — execution before step 1 run: sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.23.0.tgz

sh -lc pnpm install --ignore-scripts --frozen-lockfile failed: ! Corepack is about to download https://registry.npmjs.org/pnpm/-/pnpm-11.23.0.tgz

Assertions:

  • FAIL expect_output: PASS

How this fits together

Calendar commands enumerate calendars before selecting and listing events, while Gmail backup enumerates message IDs before fetching messages. Both paths consume Google API continuation tokens to request subsequent pages.

flowchart LR
A[Google list response] --> B[Calendar or Gmail paginator]
B --> C[Read continuation token]
C --> D{Previously seen?}
D -->|No| E[Request next page]
E --> A
D -->|Yes| F[Return pagination error]
F --> G[CLI command or backup workflow]
Loading

Before merge

  • Add real behavior proof - Needs stronger real behavior proof before merge: The Calendar harness uses the real Calendar client, but the Gmail evidence uses a fake Source rather than the production ServiceSource and Google API transport; add redacted after-fix terminal proof for that path before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Resolve merge risk (P1) - The supplied Gmail after-fix output drives a fake Source, so it does not prove the production ServiceSource and Google API transport path returns the new error correctly.
  • Complete next step (P2) - The remaining blocker is contributor-supplied production-path proof, not an automated code repair.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Focused pagination change 4 files affected; production +12/-15, tests +62/-0 The small patch reuses an existing Calendar guard and adds bounded Gmail logic plus focused tests.

Merge-risk options

Maintainer options:

  1. Decide the mitigation before merge
    Keep the narrow guards and tests, then add redacted terminal proof using Gmail ServiceSource with a controlled repeated-token HTTP response before merging.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best possible solution:

Keep the narrow guards and tests, then add redacted terminal proof using Gmail ServiceSource with a controlled repeated-token HTTP response before merging.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main directly reuses returned continuation tokens in both paths, and the branch provides deterministic repeated-token harnesses that exercise the resulting error path.

Is this the best way to solve the issue?

Yes. Reusing the existing guarded collector for Calendar and keeping a small package-local seen-token set for Gmail is the narrowest maintainable repair.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against c4952a2241c4.

Labels

Label changes:

  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦞 diamond lobster.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The Calendar harness uses the real Calendar client, but the Gmail evidence uses a fake Source rather than the production ServiceSource and Google API transport; add redacted after-fix terminal proof for that path before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • remove proof: sufficient: Current real behavior proof status is insufficient, not sufficient.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦐 gold shrimp, so this older rating label is no longer current.
  • remove status: 👀 ready for maintainer look: Current PR status label is status: 📣 needs proof.

Label justifications:

  • P2: A repeated upstream token can otherwise leave calendar enumeration or Gmail backup ID discovery running until cancellation.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦞 diamond lobster.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The Calendar harness uses the real Calendar client, but the Gmail evidence uses a fake Source rather than the production ServiceSource and Google API transport; add redacted after-fix terminal proof for that path before merge. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

Likely related people:

  • Peter Steinberger: Introduced the Gmail backup fetch engine and is attributed in current history for the shared pagination guard. (role: recent pagination and Gmail backup contributor; confidence: high; commits: 12461f5df6f5, 45b5d766e137; files: internal/backup/gmail/fetch.go, internal/cmd/paging.go)
  • salmonumbrella: Merged calendar-selection work provides the historical origin for the calendar-list path cited by this PR. (role: calendar selection-path contributor; confidence: medium; commits: 9977c0bedbc5; files: internal/cmd/calendar_list.go)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Post redacted terminal output that drives Gmail ServiceSource through a controlled repeated-token HTTP response and shows the returned repeated-token error.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (1 earlier review cycle)
  • reviewed 2026-08-18T23:22:30.262Z sha f68fe08 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Aug 25, 2026
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
@clawsweeper

clawsweeper Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix(paging): stop calendar and Gmail listing on a repeated page token This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@steipete
steipete merged commit 0996b6a into openclaw:main Aug 25, 2026
7 checks passed
@steipete

Copy link
Copy Markdown
Collaborator

Landed in 0996b6a after strengthening the original fix and independently verifying the real Google client path.

  • Focused regressions: go test ./internal/backup/gmail ./internal/cmd -run 'Test(ListMessageIDsRejectsRepeated(PageTokenFromServiceSource|ResumeTokenBeforeCacheWrite|PageToken)|ListCalendarListRejectsRepeatedPageToken)$' -count=1.
  • Production transport proof constructs the real Google Gmail service, wraps it in the production ServiceSource, returns a repeated page token from an actual HTTP test server, and proves exactly two requests before failure.
  • Resumed-token coverage proves failure happens before cache writes, preserving the original cursor and cached message IDs.
  • Live provider integration: GOG_IT_ACCOUNT=ACCOUNT go test -tags=integration ./internal/integration -run '^(TestCalendarSmoke|TestGmailSmoke)$' -count=1 -v; both real Google services passed.
  • Complete local make ci passed, and exact-head hosted Linux, Windows, macOS, worker, and Docker checks passed: https://github.com/openclaw/gogcli/actions/runs/32822529669 and https://github.com/openclaw/gogcli/actions/runs/32822529696.

Thanks @SebTardif!

chrischall added a commit to chrischall/gogcli-mcp that referenced this pull request Aug 25, 2026
… and calendar reminders (#286)

Wraps the new surface in [gogcli
0.38.0](https://github.com/openclaw/gogcli/releases/tag/v0.38.0). Two
commits, so the PR title is what release-please parses.

## What

| Area | Tools | Notes |
|---|---|---|
| **Sheets** — Connected Sheets writes | `datasource_add` / `_update` /
`_refresh` / `_delete` | Completes the read-only half wrapped for 0.37.0
|
| **Slides** — visibility | `skip_slide` / `unskip_slide` | Keeps the
slide in the deck; omits it when presenting |
| **Calendar** — reminders | params on `create` + `update` |
`--reminder` was never wrapped either; `--no-reminders` is the 0.38.0
addition |
| **Chat** (new service) | 12 tools | spaces, threads, messages, DMs,
reactions, `run` |
| **Apps Script** (new service) | 8 tools | metadata, source, pull,
deployments, versions, function execution, `run` |

Chat and Apps Script land as **base service modules with no
sub-package**, following the `tasks` precedent. Base is now 112 tools
across 13 services.

### Decisions worth reviewing

- **`datasource_delete` carries `--force`.** gog gates it and the runner
always injects `--no-input`. Confirmed live rather than assumed —
without it gog answers `refusing to delete Connected Sheets data source
… without --force (non-interactive)`. The mocked suite cannot catch
this, per the Gotchas section in CLAUDE.md.
- **`datasource_add/update/refresh` say they cost money.** Each starts a
BigQuery execution billed to `billingProject`, and returns once the
execution is *requested*, not finished — the descriptions tell the
caller to poll `datasource_describe` for `SUCCEEDED`/`FAILED`.
- **Calendar reminders are three states in one param pair.** A list sets
overrides; `noReminders` disables them; an **empty list** is gog's
"restore the calendar's defaults" (an empty `--reminder`), which differs
from omitting the flag. All three verified with `--dry-run`.
- **`appscript_run_function` is annotated destructive** and says so
loudly: it executes someone's script under this account's authority, and
the wrapper cannot tell a read from a write.
- **Naming:** `gog_appscript_run` stays the escape hatch
(fleet-consistent across 13 services); function execution is
`gog_appscript_run_function`. Both descriptions point at each other.

### Version pins

`MIN_GOG_VERSION` → **0.38.0**, with `fly-gog-runner/Dockerfile` and the
nine `mint.yaml` pins from #284 moved alongside it. The second commit
also extends `check-runner-gog-version.mjs` to cover `mint.yaml`, since
an mcp-host `--npm` registration installs gog from that pin — a third
path nothing was checking. Verified the guard *fails* on a stale pin,
not merely that it passes.

## Test plan

- `npm test` — 878 base + sub-package suites, 100% coverage gate held
(three branches the first pass missed are now covered).
- `npm run typecheck` and `npm run build` clean. (A green vitest run is
not a green `tsc`.)
- **Live against a real gog 0.38.0**, beyond the mocked suite: every new
argv shape dry-run; the delete gate refused without `--force` and
proceeded with it; all three reminder states produced the expected
`reminders` patch.

## Known limits, deliberately shipped

Neither new service is reachable on a consumer account, so both facts
are in the **tool descriptions** where a model reads them, not just in
comments:

- **Chat is Workspace-only.** gog refuses every call on `@gmail.com`
regardless of scopes — re-authorizing cannot fix it, and a model that
reads "permission error" as "missing scope" would otherwise waste a
re-auth round trip.
- **The Apps Script API is off by default** on a Cloud project; gog's
error names the exact console URL. Also a project setting, not a scope.

`docs/auth-scopes.md` now says both, since it previously claimed these
scopes had no tools here.

## Follow-ups (not in this PR)

- **The Fly runner still runs 0.37.0** — the Dockerfile pin is bumped,
but the hosted connector needs a redeploy before it actually has the
binary.
- **`fetchGmailPages` has no repeated-page-token guard**
(`gmail-results.ts:190`). gog 0.38.0 fixed this on its own side
(openclaw/gogcli#1004), but our wrapper does its own multi-page walk
over single-page gog calls: if Google repeats a token we re-fetch and
merge duplicates until `maxPages`. Wrong results rather than an error.
- Whether Chat belongs in the kitchen-sink base package at all, given it
can never work for a consumer user, and given base is now 112 tools.

Also corrects the base README/SKILL service tables, which advertised "52
tools across 8 services" while the package shipped 112 across 13 —
Slides, Classroom and the API escape hatch were missing entirely,
predating this change.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01119smk3joNhptNrSQfLK1e

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
chrischall added a commit to chrischall/gogcli-mcp that referenced this pull request Aug 25, 2026
#288)

Found while reviewing the gog 0.38.0 surface for #286; independent of
that PR and branched off `main`, so the two can land in either order.

## The bug

`fetchGmailPages` (`packages/gogcli-mcp/src/gmail-results.ts`) walks up
to `maxPages` by making **N separate single-page gog calls**, following
whatever `nextPageToken` each returns. Google can hand back a cursor it
has already issued. Following it re-fetches a page that was already
merged, so every remaining iteration appends the same threads again.

Two harms, the first much worse than the second:

1. **Duplicates presented as more results.** The payload looks perfectly
well-formed — nothing about it says "these twelve threads are the same
three, four times over". A caller counting or de-duplicating downstream
gets a wrong answer with no error to notice.
2. **A wasted gog spawn per duplicate**, up to the full `maxPages`
budget.

gog 0.38.0 fixed this class on its own side (openclaw/gogcli#1004 —
"stop safely when Google repeats a pagination token"), but that fix
covers gog's `--all`. This walk is ours: separate `--page=<token>`
invocations, so the repeated cursor arrives here untouched. Reachable
today through `gog_gmail_search` and the gmail sub-package's search
whenever `maxPages > 1`.

## The fix

The walk remembers every cursor it has fetched with and stops on a
repeat, **before** requesting the duplicate page — so the duplicate is
never fetched and never merged.

- **Seeded with the caller's own cursor**, since a response echoing that
straight back would re-fetch the page just merged.
- **Detects any earlier cursor**, not just the immediately-previous one
— a `T1 → T2 → T1` cycle stalls exactly the same way.
- **Keeps the cursor in the result** rather than dropping it. The walk
never established an end, so the set stays truncated; dropping it would
claim a completeness we never had, and a set that reads complete is
precisely how mail that exists gets reported as missing. Handing the
cursor back also lets a caller retry later.

`fetchGmailPages` is the only multi-page walk in the repo — I checked
the rest of `nextPageToken`'s uses, and they are single-page
pass-through or descriptive text, so there is no second instance of this
class to fix.

## Test plan

- Four new cases in `tests/gmail-results.test.ts`, written first and
confirmed failing against the old code — the first failed by running off
the end of the mocked responses, which is the stall itself.
- stops rather than re-fetching, and does not burn the remaining page
budget
  - the result still reads as truncated afterwards
  - a cursor repeating the *caller-supplied* one is caught
  - a cursor repeating an *earlier* token in the walk is caught
- `npm test` green (834 base + sub-package suites) with the 100%
coverage gate held; `npm run typecheck` and `npm run build` clean.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01119smk3joNhptNrSQfLK1e

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants