Skip to content

Claude/cpu guard script dn d8u - #129

Merged
gamblecodezcom merged 4 commits into
mainfrom
claude/cpu-guard-script-DnD8u
Mar 4, 2026
Merged

Claude/cpu guard script dn d8u#129
gamblecodezcom merged 4 commits into
mainfrom
claude/cpu-guard-script-DnD8u

Conversation

@gamblecodezcom

@gamblecodezcom gamblecodezcom commented Mar 4, 2026

Copy link
Copy Markdown
Owner

User description

Summary by Sourcery

Guard Telegram API rate limiting around callApi and make QA telemetry file writes non-fatal to avoid impacting core service operation.

Enhancements:

  • Unify and centralize the list of Telegram methods that bypass global callApi rate limiting, including long-polling, lifecycle, and individually patched methods.
  • Export the bypass method sets from telegramSafe for easier testing of rate-limiting behavior.
  • Wrap QA directory creation and artifact/state file writes in try/catch so missing permissions do not break the main service, logging a warning when QA artifacts cannot be written.

CodeAnt-AI Description

Prevent Telegram long-poll timeout and make QA file writes non-fatal

What Changed

  • Long-polling and Telegraf lifecycle API calls (e.g., getUpdates, getMe, setWebhook) now bypass the global 15s timeout so polling no longer times out or causes bot launch to fail.
  • QA directory creation and all QA artifact/state file writes are now non-fatal: permission errors are caught, startup continues, and a warning is logged when QA artifacts can't be written.
  • Sets of bypassed Telegram methods are exported so tests can assert which methods skip global rate-limiting.

Impact

✅ Prevents bot restart loops caused by long-poll timeouts
✅ Fewer startup crashes when QA files are unwritable
✅ Easier testing of Telegram rate-limit bypasses

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced application resilience by making QA operations non-fatal. Directory creation, state persistence, and artifact generation failures no longer cause crashes and are handled gracefully.
  • Refactor

    • Reorganized API rate-limiting logic for clarity. Method-specific rate-limiting is now centrally managed with improved documentation and testability.

claude added 2 commits March 4, 2026 13:00
…eout

Telegraf's long-polling uses getUpdates with timeout=50 (Telegram holds
the connection for up to 50 seconds waiting for new updates). The callApi
patch was wrapping ALL methods — including getUpdates — with globalThrottle,
which has a hard 15-second race. This fired on every poll cycle, throwing
'rateLimiter: API call timed out after 15000ms', causing bot.launch() to
reject and systemd to enter an infinite restart loop.

Fix: add getUpdates (and Telegraf startup/lifecycle calls: getMe,
deleteWebhook, setWebhook, getWebhookInfo, close, logOut) to the _MANAGED
bypass set so they call the original callApi directly without the timeout
wrapper.

All 60 unit tests pass. Bot loads cleanly in CI mode.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
…hod sets

Two fixes:

1. index.js — ensureQaArtifacts(), persistQaProviderState(), ensureQaDirs():
   All QA file writes are now wrapped in try/catch and treated as non-fatal.
   The bot service runs as the 'runewager' system user but qa/ is owned by
   root, so writeFileSync was throwing EACCES on every startup, which was
   caught by startBot()'s outer try/catch and called process.exit(1).

2. telegramSafe.js — callApi bypass list refactored (code review feedback):
   The inline _MANAGED set is replaced with three named, exported constants:
   - LONG_POLL_METHODS    : getUpdates (must bypass 15 s timeout)
   - LIFECYCLE_METHODS    : getMe, deleteWebhook, setWebhook, etc.
   - INDIVIDUALLY_PATCHED_METHODS : sendMessage, sendPhoto, etc.
   Combined into CALLAPI_BYPASS_METHODS used by the callApi patch.
   All sets are exported so test suites can assert bypass membership without
   requiring a live Telegraf instance.

All 60 unit tests pass. Module loads cleanly in CI mode.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
@codeant-ai

codeant-ai Bot commented Mar 4, 2026

Copy link
Copy Markdown

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@sourcery-ai

sourcery-ai Bot commented Mar 4, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refines Telegram callApi rate-limiting bypass logic using categorized method sets and exposes them for testing, and hardens QA artifact directory/file handling so permission issues never crash the process and are logged as warnings instead.

Sequence diagram for updated Telegram callApi rate-limiting and bypass logic

sequenceDiagram
    actor User
    participant Bot
    participant tg
    participant globalThrottle
    participant TelegramAPI

    User->>Bot: triggerTelegramAction
    Bot->>tg: callApi sendMessage, data, signal
    Note over tg: sendMessage is in CALLAPI_BYPASS_METHODS
    tg->>TelegramAPI: callApi sendMessage, data, signal
    TelegramAPI-->>tg: response
    tg-->>Bot: response
    Bot-->>User: success

    User->>Bot: triggerOtherAction
    Bot->>tg: callApi unknownMethod, data, signal
    Note over tg: unknownMethod not in CALLAPI_BYPASS_METHODS
    tg->>globalThrottle: schedule _callApi unknownMethod, data, signal
    globalThrottle->>TelegramAPI: callApi unknownMethod, data, signal
    TelegramAPI-->>globalThrottle: response or error
    globalThrottle-->>tg: response
    tg-->>Bot: response
    Bot-->>User: success or failure
Loading

Flow diagram for QA artifacts creation with non-fatal error handling

flowchart TD
    A[start ensureQaArtifacts] --> B[try ensureQaDirs]
    B --> C[try write qaRepoInfoFile]
    C --> D[try write qaCapabilitiesFile]
    D --> E[call persistQaProviderState]
    E --> F{persistQaProviderState success?}
    F -->|yes| G[ensureQaArtifacts complete]
    F -->|no - exception| G

    B -.on error.-> H[catch error in ensureQaArtifacts]
    C -.on error.-> H
    D -.on error.-> H
    E -.on error.-> I[catch error in persistQaProviderState]

    I --> G

    H --> J[logEvent warn
      ensureQaArtifacts skipping QA artifact write]
    J --> G

    subgraph persistQaProviderState
      K[start persistQaProviderState] --> L[try ensureQaDirs]
      L --> M[try write qaProviderStateFile]
      M --> N[persistQaProviderState return]
      L -.on error.-> O[catch and ignore error]
      M -.on error.-> O
      O --> N
    end
Loading

File-Level Changes

Change Details Files
Generalize and document callApi rate-limiter bypass behavior using categorized method sets and reuse in the init() patch while exposing them for tests.
  • Introduce LONG_POLL_METHODS, LIFECYCLE_METHODS, and INDIVIDUALLY_PATCHED_METHODS sets along with a combined CALLAPI_BYPASS_METHODS set to control which Telegram methods bypass globalThrottle.
  • Update the tg.callApi wrapper in init() to consult CALLAPI_BYPASS_METHODS instead of a local _MANAGED set and keep long-poll, lifecycle, and already-wrapped methods out of the rate limiter.
  • Export the method sets from the module to allow tests to assert bypass behavior without a live Telegraf instance.
  • Add clarifying comments explaining the rationale for bypassing long-poll and lifecycle methods and avoiding double-wrapping of individually-patched methods.
telegramSafe.js
Make QA directory and artifact writes non-fatal and log failures instead of throwing.
  • Wrap qa directory creation in ensureQaDirs() with try/catch to ignore mkdir failures that may occur under restricted permissions.
  • Guard persistQaProviderState() with try/catch so inability to write qa provider state does not crash the service.
  • Wrap ensureQaArtifacts() body in try/catch, treating QA artifacts as best-effort observability outputs and logging a warning via logEvent when writes fail.
  • Ensure QA-related errors are safely swallowed or logged while keeping cooldown refresh scheduling unchanged.
index.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Mar 4, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

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

⌛ 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.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e19aa2c0-6e0f-432e-9557-623248aba014

📥 Commits

Reviewing files that changed from the base of the PR and between b9be6f9 and 3faf7e8.

📒 Files selected for processing (2)
  • index.js
  • telegramSafe.js
📝 Walkthrough

Walkthrough

Changes enhance resilience by wrapping QA directory creation, state persistence, and artifact generation in try-catch blocks, and refactor the API rate-limiter bypass logic in telegramSafe.js by centralizing bypass method definitions into exported constant sets.

Changes

Cohort / File(s) Summary
QA Resilience
index.js
Wrapped QA directory creation, provider state persistence, and artifact generation in try-catch blocks to prevent crashes from file system errors; logs warnings instead of throwing exceptions.
API Bypass Centralization
telegramSafe.js
Introduced three method sets (LONG_POLL_METHODS, LIFECYCLE_METHODS, INDIVIDUALLY_PATCHED_METHODS) and consolidated them into CALLAPI_BYPASS_METHODS; refactored callApi wrapper to check against the centralized bypass set instead of inline logic; exported all four constants for testing and inspection.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

size:M

Poem

🐰 Errors, be gentle, don't crash my QA,
With try-catch shields, we'll go far!
And callApi's paths now clearly defined,
In sets we trust, all neatly aligned. ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The pull request title 'Claude/cpu guard script dn d8u' is vague and does not clearly convey the actual changes, which involve making QA operations non-fatal and refactoring rate-limiting bypass logic. Replace the title with a clear, descriptive summary of the main changes, such as 'Make QA operations non-fatal and refactor callApi rate-limiter bypass logic' or similar.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/cpu-guard-script-DnD8u

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codeant-ai codeant-ai Bot added the size:M This PR changes 30-99 lines, ignoring generated files label Mar 4, 2026

@sourcery-ai sourcery-ai 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.

Hey - I've found 1 issue, and left some high level feedback:

  • The empty catch blocks around fs.mkdirSync in ensureQaDirs and persistQaProviderState fully swallow any filesystem issues; consider at least logging at a debug level or restricting the catch to expected error codes (e.g. EEXIST, EACCES) so that unexpected failures don't go unnoticed.
  • In ensureQaArtifacts, the catch block assumes a permission issue; it might be more robust to branch on error.code (e.g. only suppress EACCES/EPERM) and rethrow or log differently for other error types to avoid masking genuine bugs like invalid paths.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The empty catch blocks around `fs.mkdirSync` in `ensureQaDirs` and `persistQaProviderState` fully swallow any filesystem issues; consider at least logging at a debug level or restricting the catch to expected error codes (e.g. EEXIST, EACCES) so that unexpected failures don't go unnoticed.
- In `ensureQaArtifacts`, the catch block assumes a permission issue; it might be more robust to branch on `error.code` (e.g. only suppress EACCES/EPERM) and rethrow or log differently for other error types to avoid masking genuine bugs like invalid paths.

## Individual Comments

### Comment 1
<location path="index.js" line_range="4884-4888" />
<code_context>
 }

 function persistQaProviderState() {
-  ensureQaDirs();
-  fs.writeFileSync(qaProviderStateFile, JSON.stringify(qaRuntime.providerStatus, null, 2));
+  try {
+    ensureQaDirs();
+    fs.writeFileSync(qaProviderStateFile, JSON.stringify(qaRuntime.providerStatus, null, 2));
+  } catch (_) { /* non-fatal — qa/ dir may not be writable by the service user */ }
 }

</code_context>
<issue_to_address>
**suggestion (bug_risk):** Swallowing all errors in persistQaProviderState makes diagnosing real issues difficult.

Making this non‑fatal is reasonable, but the empty catch masks all failures (including unexpected ones like JSON serialization issues). Please either log the error (even at debug/info) or restrict the catch to the expected cases (e.g., permission errors) so unexpected issues remain visible.

Suggested implementation:

```javascript
function persistQaProviderState() {
  try {
    ensureQaDirs();
    fs.writeFileSync(qaProviderStateFile, JSON.stringify(qaRuntime.providerStatus, null, 2));
  } catch (err) {
    // Non-fatal — qa/ dir may not be writable by the service user.
    // Only swallow expected filesystem permission issues; rethrow unexpected errors
    // (including JSON serialization issues) so they remain visible.
    if (err && (err.code === 'EACCES' || err.code === 'EROFS' || err.code === 'EPERM')) {
      // eslint-disable-next-line no-console
      console.warn('Unable to persist QA provider state; qa/ directory not writable for service user.', err);
      return;
    }

    throw err;
  }
}

```

If the codebase has a centralized logger (e.g., `logger.warn` or similar), replace `console.warn` with that to be consistent with existing logging practices.
You may also want to audit the other empty `catch` blocks around `fs.mkdirSync` and apply a similar pattern (log and/or narrow to expected error codes) for better diagnosability.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread index.js Outdated
@codeant-ai

codeant-ai Bot commented Mar 4, 2026

Copy link
Copy Markdown

Nitpicks 🔍

🔒 No security issues identified
⚡ Recommended areas for review

  • Mutable exports
    The PR exports internal Sets (LONG_POLL_METHODS, LIFECYCLE_METHODS, INDIVIDUALLY_PATCHED_METHODS, CALLAPI_BYPASS_METHODS) directly. Because Sets are mutable, external code or tests could accidentally modify these collections at runtime which changes module behavior. Consider exposing immutable copies or arrays for testing instead of the live Sets.

@codeant-ai

codeant-ai Bot commented Mar 4, 2026

Copy link
Copy Markdown

CodeAnt AI finished reviewing your PR.

…e conflict

Addresses code review feedback:

index.js:
- Added QA_FS_SUPPRESS constant (EACCES, EPERM, EROFS, EEXIST) — the set of
  expected error codes when qa/ is owned by root but the service runs as the
  runewager user. Defined once, shared by all three QA helpers.
- ensureQaDirs: replace silent catch-all with per-directory loop; unexpected
  error codes (e.g. ENOENT, ENOMEM) are logged as warnings so they remain
  visible; permission codes are silently skipped.
- persistQaProviderState: catch checks err.code — returns silently for
  permission errors, logs a warning for any other code (e.g. JSON failure).
- ensureQaArtifacts: same pattern — unexpected errors are logged at warn level;
  permission errors (EACCES/EPERM/EROFS) are intentionally silent.

telegramSafe.js:
- Resolved merge conflict: kept the CALLAPI_BYPASS_METHODS module-level
  constants introduced in the previous commit; dropped the inline _MANAGED
  block that arrived from main during the merge.

All 60 unit tests pass.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (2)
index.js (1)

4885-4888: Avoid fully silent QA provider-state write failures.

Catching-and-ignoring here can mask persistent write problems during runtime. Consider at least a throttled logEvent('warn', ...) so ops can detect broken QA persistence.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@index.js` around lines 4885 - 4888, The try/catch around ensureQaDirs() and
fs.writeFileSync(qaProviderStateFile, JSON.stringify(qaRuntime.providerStatus,
null, 2)) swallows all errors; change the catch to capture the error (e) and
emit a throttled warning via the existing log mechanism (e.g., call
logEvent('warn', ... ) or a rate-limited logger) that includes the
qaProviderStateFile path and error message so ops can detect persistent write
failures while preserving the non-fatal behavior.
telegramSafe.js (1)

329-334: Consider exporting immutable snapshots instead of live Set references.

Line 329 through Line 334 currently exports mutable Set objects by reference; external mutation can silently alter runtime bypass behavior.

Optional hardening diff
 module.exports = {
     init,
     sendMessage,
     editMessageText,
     answerCallbackQuery,
     sendPhoto,
     sendDocument,
     // Exported for testing — allows test suites to assert which methods bypass
     // rate-limiting without requiring a live Telegraf instance.
-    LONG_POLL_METHODS,
-    LIFECYCLE_METHODS,
-    INDIVIDUALLY_PATCHED_METHODS,
-    CALLAPI_BYPASS_METHODS,
+    LONG_POLL_METHODS: Object.freeze([...LONG_POLL_METHODS]),
+    LIFECYCLE_METHODS: Object.freeze([...LIFECYCLE_METHODS]),
+    INDIVIDUALLY_PATCHED_METHODS: Object.freeze([...INDIVIDUALLY_PATCHED_METHODS]),
+    CALLAPI_BYPASS_METHODS: Object.freeze([...CALLAPI_BYPASS_METHODS]),
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@telegramSafe.js` around lines 329 - 334, The export currently exposes live
mutable Set instances (LONG_POLL_METHODS, LIFECYCLE_METHODS,
INDIVIDUALLY_PATCHED_METHODS, CALLAPI_BYPASS_METHODS) which allows external code
to mutate runtime behavior; replace those exports with immutable snapshots by
exporting frozen copies (e.g., Object.freeze([...theSet]) or a new Set created
from the original and frozen) so callers receive an immutable array/collection
instead of the original Set reference, and update any internal usage to continue
working with the original Sets where mutation is required while keeping exported
symbols read-only.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@index.js`:
- Around line 4885-4888: The try/catch around ensureQaDirs() and
fs.writeFileSync(qaProviderStateFile, JSON.stringify(qaRuntime.providerStatus,
null, 2)) swallows all errors; change the catch to capture the error (e) and
emit a throttled warning via the existing log mechanism (e.g., call
logEvent('warn', ... ) or a rate-limited logger) that includes the
qaProviderStateFile path and error message so ops can detect persistent write
failures while preserving the non-fatal behavior.

In `@telegramSafe.js`:
- Around line 329-334: The export currently exposes live mutable Set instances
(LONG_POLL_METHODS, LIFECYCLE_METHODS, INDIVIDUALLY_PATCHED_METHODS,
CALLAPI_BYPASS_METHODS) which allows external code to mutate runtime behavior;
replace those exports with immutable snapshots by exporting frozen copies (e.g.,
Object.freeze([...theSet]) or a new Set created from the original and frozen) so
callers receive an immutable array/collection instead of the original Set
reference, and update any internal usage to continue working with the original
Sets where mutation is required while keeping exported symbols read-only.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 57f258e1-c0a9-4a1c-9c1b-c8874f53a941

📥 Commits

Reviewing files that changed from the base of the PR and between f72e96d and b9be6f9.

📒 Files selected for processing (2)
  • index.js
  • telegramSafe.js

External code or tests could accidentally mutate the exported Sets
(LONG_POLL_METHODS, LIFECYCLE_METHODS, etc.) which would silently
alter runtime bypass behavior in callApi.

Export frozen array snapshots instead — callers can still iterate and
use .includes() for membership checks; the internal module-level Sets
remain mutable for runtime use by the callApi patch.

All 60 unit tests pass.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
@gamblecodezcom
gamblecodezcom merged commit b1cb5d7 into main Mar 4, 2026
6 checks passed
@gamblecodezcom
gamblecodezcom deleted the claude/cpu-guard-script-DnD8u branch March 4, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants