Skip to content

perf(startpos): rewrite slots with 88% less allocation and 8% smaller files - #145

Merged
Microck merged 10 commits into
Microck:mainfrom
theblazehen:autoresearch/aight-lets-get-autoresearch-working-we-want-a-re-20260827
Aug 28, 2026
Merged

perf(startpos): rewrite slots with 88% less allocation and 8% smaller files#145
Microck merged 10 commits into
Microck:mainfrom
theblazehen:autoresearch/aight-lets-get-autoresearch-working-we-want-a-re-20260827

Conversation

@theblazehen

@theblazehen theblazehen commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • rewrite the fixed real-map StartPos corpus with 88.3% less managed allocation
  • reduce deterministic capture/save allocation by 62.0%
  • write the same v10 snapshots 8.3% smaller
  • keep the existing saved-state format, slot compatibility, reader ceilings, and fail-before-commit behavior

This is the memory/size follow-up to the v10 work in #138. It changes how Akron builds, validates, and compresses reconstruction documents; it does not move akron-reconstruction-v10 or require players to reset slots.

Why

A restart copy walked and serialized one reconstruction document, then proved the staged file by deserializing a second complete document that was immediately discarded. Large documents also paid for empty model collections, repeated JsonReader.Path strings, eager diagnostic paths, fresh validation dictionaries/sets/stacks, repeated property-name strings, and oversized JSON buffers.

That work is transient, but it drives cumulative allocation and GC pressure on the persistence worker. The released v10 format made snapshots much smaller on disk; this PR makes reading and rewriting that same format substantially cheaper.

Method

The branch adds a fixed, manifest-verified benchmark over 23 real StartPos snapshots:

  • 11 vanilla snapshots
  • 12 modded snapshots across Spring Collab Cookie, Strawberry Jam Hyperlife, and Monika's D-Sides
  • deterministic synthetic capture/save/restore coverage alongside the corpus

The search reward is:

overall_cost = 0.75 * (0.9 * corpus_allocation_ratio
                     + 0.1 * synthetic_allocation_ratio)
             + 0.25 * compressed_size_ratio

Working time, CPU time, and peak RSS are reported but are not reward terms.

Every candidate hard-fails unless:

  • all 23 corpus inputs match their SHA-256 manifest
  • the source corpus identity and exact 1,151,644,947-byte decompressed total match the calibrated baseline
  • rewritten documents retain their header and graph shape
  • synthetic state saves, reads, and restores exactly
  • bounded JSON readability succeeds
  • no workload cohort or synthetic allocation regresses by more than 5%
  • compressed size does not regress by more than 1%

The retained stack came from 40 measured candidate segments; discarded candidates are not part of this PR.

The checked-in collector and grader Kubernetes manifests make their public images, PVC, resource limits, and isolation requirements reviewable. They contain no corpus payloads, credentials, secrets, or host paths.

Results

Cumulative results for the exact final tree against the calibrated baseline:

Metric Baseline Final Change
Overall cost 1.0000 0.3367 -66.3%
Weighted allocation ratio 1.0000 0.1431 -85.7%
Corpus allocated bytes 110,513,612,600 12,909,322,744 -88.3%
Synthetic allocated bytes 28,478,472 10,808,272 -62.0%
Compressed corpus bytes 40,304,236 36,976,510 -8.3%
Working time 220.10 s 123.22 s -44.0%
CPU time 223.66 s 124.57 s -44.3%
Peak RSS 3,313,205,248 2,955,034,624 -10.8%

The benchmark also emits workload and invariant metrics that are not all represented by the headline table:

Reported metric Baseline Final Delta
Worst cohort allocation ratio 1.0000 0.1707 -82.9%
Vanilla allocation ratio 1.0000 0.1320 -86.8%
Spring Collab Cookie allocation ratio 1.0000 0.1565 -84.4%
Strawberry Jam Hyperlife allocation ratio 1.0000 0.1707 -82.9%
Monika's D-Sides allocation ratio 1.0000 0.1097 -89.0%
Source compressed bytes 40,304,236 40,304,236 0 (0.0%)
Decompressed bytes 1,151,644,947 1,151,644,947 0 (0.0%)
Snapshot count 23 23 0 (0.0%)

Hyperlife is the worst allocation cohort at 0.1707x baseline; every cohort remains far below its non-regression gate. Source size, decompressed identity, and snapshot count are invariants rather than optimization targets, so their correct delta is zero.

What changed

No second reconstruction graph during staged readback

SaveSnapshot validates the exact indexed in-memory document before writing, streams the staged JSON through every bounded-reader structural ceiling, and requires the exact uncompressed SHA-256 to match every byte handed to gzip. It catches truncation, corruption, malformed JSON, and structural-limit failures before commit without materializing a discarded second graph.

Less per-record and per-pass allocation

  • optional reconstruction-node collections and metadata stay null until used
  • production traversal uses allocation-free *OrNull backings while public mutable list getters retain their existing behavior
  • bounded-reader record classification tracks token/depth state instead of materializing JsonReader.Path
  • diagnostic path lengths and parent links validate eagerly; strings materialize only when observed
  • field, array, and delegate paths avoid intermediate strings
  • reachability walks fields/items/delegates directly instead of composing LINQ iterators
  • header, edge, reachability, path, and type-index passes reuse pre-sized node indexes and per-graph scratch
  • canonical type-name tables are reused when already valid
  • known Json.NET property names are interned per graph
  • Json.NET character buffers use ArrayPool<char>.Shared
  • JSON stream buffers use the measured 8-KiB midpoint

Smaller stored snapshots

The single gzip member uses CompressionLevel.SmallestSize. This is the only change that alters stored bytes: decompressed v10 JSON and its contract remain unchanged. It saves 3,327,726 bytes across the fixed corpus while the complete rewrite remains about 45% faster than baseline.

Exact-state and safety boundaries

The save path still refuses a slot before commit if a later load would reject it.

Streaming JSON validation cannot infer derived diagnostic paths by itself, so serialization resets only [JsonIgnore] path caches and rebuilds them from the serialized parent edges through the loader's existing RestoreDiagnosticPaths validator. Path-size, aggregate-size, unresolved-parent-depth, and cycle limits are therefore enforced on both trusted serialization and hostile deserialization.

The tests cover both directions. The path caches are not serialized, so rebuilding them changes no wire state.

Review map

The eight commits are intentionally grouped by idea. The harness commit records the calibrated baseline, the buffer-size commit records its measured A/B deltas, and every other body records its measured autoresearch checkpoint; the final commit and tables below record the exact rebased tree:

  1. fixed 23-snapshot benchmark and corpus collector
  2. lazy model collections + allocation-free bounded-reader classification
  3. hash-certified streaming staged readback
  4. validation/path/type-table allocation removal
  5. per-graph scratch reuse + property interning + pooled char buffers
  6. measured 64-KiB to 8-KiB JSON stream-buffer reduction
  7. denser gzip + capture metadata cleanup + final tuning
  8. save-time diagnostic-path correctness closure

The measured checkpoints are preserved for review, but commit 3 intentionally relies on commit 8 to close derived diagnostic-path preflight. Merge the stack as one unit; squash-merging is also safe.

Suggested review order:

  • SaveSnapshot, ValidateSerializedDocument, and hash handling: no second graph, same fail-before-commit boundary
  • PrepareForSerialization, ResetDiagnosticPaths, and RestoreDiagnosticPaths: derived path limits remain symmetric between save and load
  • AkronBoundedJsonTextReader: same ceilings without JsonReader.Path
  • lazy public getters versus internal *OrNull accessors: API compatibility
  • CompressionLevel.SmallestSize: the only stored-byte change

Verification

Checklist

  • The diff is scoped to one goal.
  • Public docs are unchanged because no public format, setting, command, or file contract changes.
  • CHANGELOG.md records the notable memory and size improvement.
  • Feature policy docs and registry tests are unchanged because feature classification does not change.
  • Tests cover the changed persistence, exact-state, and validation behavior.
  • Unit tests plus the fixed real-snapshot corpus prove the changed persistence boundaries; no behavior here requires a live game process to exercise.
  • Screenshots/video are not applicable: this has no visible, input, rendering, timing, or capture-UI change.
  • No local captures, corpus payloads, tokens, secrets, personal config, or machine-specific paths are committed.
  • I have the right to submit this contribution and agree to the contribution license in CONTRIBUTING.md.

Checks run

git diff --check origin/main...HEAD
dotnet build Source/Akron.csproj --configuration Release --nologo --no-restore
dotnet test tests/akron-tests.csproj --configuration Release --nologo --no-restore --filter 'FullyQualifiedName!~AFailedSnapshotInstallKeepsTheSnapshotTheSlotAlreadyHad&FullyQualifiedName!~ASecondInstallAttemptIsRefusedRatherThanRunOnTheFirstOnesRecord'
runuser -u nobody -- env HOME=/tmp dotnet test tests/akron-tests.csproj --configuration Release --nologo --no-restore --no-build --filter 'FullyQualifiedName~AFailedSnapshotInstallKeepsTheSnapshotTheSlotAlreadyHad|FullyQualifiedName~ASecondInstallAttemptIsRefusedRatherThanRunOnTheFirstOnesRecord'
bash scripts/akron-corpus/autoresearch.sh

Results:

  • source build: 0 warnings, 0 errors
  • applicable test suite: 1811/1811 passed
  • filesystem-permission install tests: 2/2 passed as nobody
  • canonical corpus: 23/23 snapshots passed, exact decompressed total retained

The template's dotnet format command is not listed as a passing gate: this checkout has no formatter configuration, so the SDK default proposes a whole-file brace-style rewrite that conflicts with the repository's existing K&R style. git diff --check is clean.

Live verification

  • Map SID: Not applicable; this benchmark replays a fixed manifest-verified snapshot corpus.
  • Akron setup or ruleset state: Existing v10 StartPos persistence contract.
  • Steps: No live Celeste/Everest session was run; the corpus rewrite, exact synthetic restore, hostile-input tests, and full unit suite exercise the changed boundaries.
  • Evidence: Metrics and exact-byte totals are recorded above; all automated checks passed.

AI assistance disclosure

  • agent_name: Oh My Pi coding agent
  • agent_version: model/version metadata not exposed by the harness
  • model_used: llmproxy/codex/gpt-5.6-sol
  • human_testing: No human-run live Celeste testing was performed for this PR. Automated verification run through the coding harness is listed above; the contributor should add any manual review or live testing they perform before marking the PR ready.
  • contribution_summary: Built a measured StartPos persistence optimization, reviewed the correctness boundary, consolidated the retained changes into a metric-backed commit series, and drafted the PR explanation.

@Microck
Microck marked this pull request as ready for review August 28, 2026 07:46
@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9d8d1e0f-fbf2-4f6a-965b-ee86d9f4fb30

📥 Commits

Reviewing files that changed from the base of the PR and between cdbb285 and 5ecfff1.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • Source/SaveLoad/akron-reconstruction-graph.cs
  • tests/startpos-reconstruction-tests.cs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


Akron now reconstructs fixed real-map StartPos slots with lower allocation, snapshot size, working time, and peak RSS while preserving v10 format and slot compatibility.

  • The workflow avoids a second reconstruction graph and uses lazy collections, scratch reuse, pooled buffers, optimized paths and property names, and denser gzip compression.
  • The workflow preserves reader ceilings and fail-before-commit behavior; 23/23 corpus snapshots retain identical decompressed totals.
  • Tests cover malformed parent chains, diagnostic paths, required properties, streaming limits, filesystem permissions, and deterministic capture/save/restore scenarios.

Walkthrough

The reconstruction tests now verify that serialization and deserialization reject excessive parent-chain depth and diagnostic-path size. They also verify deserialization errors for missing field values and delegate-call targets. The changelog records reduced StartPos memory use and output size while preserving saved-state and slot compatibility.

Merge Risk: ⚪ Minimal · up to 5ecff

This localized persistence optimization preserves the existing saved-state format, compatibility, validation limits, and fail-before-commit behavior while reducing allocation and snapshot size. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Documentation Impact ✅ Passed No undocumented public contract change is introduced. The diff keeps akron-reconstruction-v10, the v10-*.json.gz snapshot naming, and the existing reader limits. The only stored-byte change is `Co…
Full details: Documentation Impact

Explanation

No undocumented public contract change is introduced. The diff keeps akron-reconstruction-v10, the v10-*.json.gz snapshot naming, and the existing reader limits. The only stored-byte change is CompressionLevel.Optimal to CompressionLevel.SmallestSize; the .akr archive and snapshot contracts remain unchanged. CHANGELOG.md documents the lower memory use and smaller writes, and the existing StartPos and .akr reference pages remain accurate.


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.

@Microck

Microck commented Aug 28, 2026

Copy link
Copy Markdown
Owner

@codex review

theblazehen and others added 9 commits August 28, 2026 09:12
Add a manifest-verified corpus collector and a resource-isolated benchmark for 11 vanilla and 12 modded StartPos snapshots. The modded cohorts cover Spring Collab Cookie, Strawberry Jam Hyperlife, and Monika's D-Sides.

The companion Kubernetes manifests define long-lived collection and guaranteed-resource grading pods backed by the corpus PVC. They contain no corpus payloads, credentials, secrets, or host paths.

The reward is 75% weighted allocation and 25% compressed size; allocation weights corpus rewrites 9:1 over deterministic synthetic capture. Working time, CPU time, and peak RSS remain diagnostic metrics rather than optimization targets.

Every run hard-fails unless all 23 inputs retain their manifest identity, exact 1,151,644,947-byte decompressed total, bounded readability, document shape, and synthetic exact restore. Per-cohort allocation, synthetic allocation, and compressed size have independent regression gates, so the scalar reward cannot buy a localized regression.

The benchmark is opt-in: ordinary CI returns a passing no-op when neither corpus variable is configured; partial configuration fails loudly; scripts/akron-corpus/autoresearch.sh supplies both and also refuses a missing result.

Calibrated baseline: 110,513,612,600 corpus-allocated bytes, 28,478,472 synthetic-allocated bytes, 40,304,236 compressed bytes, 220.103 seconds working time, 223.660 seconds CPU time, and 3,313,205,248 bytes peak RSS. No production behavior changes.
Make optional reconstruction-node collections lazy and traverse absent collections without allocating. Preserve the model's mutable public list behavior with lazy getters while routing production traversal through allocation-free *OrNull backings.

Replace bounded-reader JsonReader.Path construction with ordinal array-element matching and depth-tracked recognition of the few record arrays that affect structural ceilings.

The reader still enforces the same token, container, record, node, and expensive-record limits; it derives record context from token/depth state instead of materializing full JSON paths. Snapshot bytes and the v10 contract are unchanged.

Canonical reader checkpoint versus baseline:
- overall cost: 0.473838 (-52.6%)
- corpus allocation: 25,832,071,112 bytes (-76.6%)
- synthetic allocation: 25,083,800 bytes (-11.9%)
- working time: 136.83 seconds (-37.8%)
- compressed corpus: unchanged at 40,304,236 bytes

The lazy mutable getters measured corpus allocation flat with exact bytes unchanged. Peak RSS was 1.066x baseline at the reader checkpoint; later pooling and scratch reuse lower it. All 23 snapshots passed.
Stop proving a staged snapshot by deserializing a second complete reconstruction graph that is immediately discarded. Validate the indexed in-memory document before write, stream the staged JSON through the bounded reader, and require its exact uncompressed SHA-256 to match the bytes handed to gzip.

The stream still enforces format, type, token, string, container, record, node, and expensive-record ceilings. Header and graph invariants are checked against the exact document before serialization, while truncation, corruption, malformed JSON, and structural-limit failures still abort before commit.

Keep optional delegate parameter metadata and non-array path indices nullable, copying them only when present.

The final correctness commit restores derived diagnostic-path preflight, which a token stream cannot infer by itself; this stack should be merged as a unit.

Canonical group-tip change versus the preceding reader checkpoint:
- overall cost: 0.410675 (-13.3%)
- corpus allocation: 20,375,773,616 bytes (-21.1%; -81.6% from baseline)
- synthetic allocation: 13,754,232 bytes (-45.2%; -51.7% from baseline)
- working time: 112.34 seconds (-17.9%; -49.0% from baseline)
- compressed corpus: unchanged at 40,304,236 bytes

All 23 snapshots and the focused size/structural guards passed.
Walk field, item, and delegate reachability directly instead of composing per-node LINQ iterators. Build one pre-sized node index during header validation and reuse it for parent edges, reachability, and diagnostic-path restoration; pre-size the remaining scratch collections from known graph counts.

Validate serialized type-name indexes directly after the one full graph validation and reuse an already canonical type table. Keep nested default values, delegate targets, and gameplay payloads nullable rather than constructing throwaway objects.

Make diagnostic paths cheap without weakening their limits: share exact child/field paths, reuse unresolved-node scratch, build field/array/delegate paths without intermediate strings, and validate path lengths and parent links eagerly while materializing strings only when observed.

Canonical group-tip change versus streaming readback:
- overall cost: 0.384396 (-6.4%)
- corpus allocation: 16,732,912,096 bytes (-17.9%; -84.9% from baseline)
- synthetic allocation: 12,224,312 bytes (-11.1%; -57.1% from baseline)
- working time: 97.43 seconds (-13.3%; -55.7% from baseline)
- peak RSS: 0.924x baseline

Snapshot bytes and diagnostic-path accounting are unchanged. All 23 snapshots and the focused graph, path, header, action-state, delegate, and weak-reference guards passed.
Reuse per-graph parent-edge, reachability, serialization-index, and root-node validation scratch across sequential passes. Clear every reusable collection on exit and keep returned deserialize indexes independent so scratch lifetime does not leak into loaded documents.

Prepopulate one per-graph Json.NET property-name table with the known v10 and auxiliary keys, interning repeated property tokens without retaining unknown names. Back Json.NET reader and writer character buffers with ArrayPool<char>.Shared through a stateless adapter.

Canonical group-tip change versus the validation checkpoint:
- overall cost: 0.358750 (-6.7%)
- corpus allocation: 12,902,315,064 bytes (-22.9%; -88.3% from baseline)
- synthetic allocation: 11,370,512 bytes (-7.0%; -60.1% from baseline)
- peak RSS: 0.853x baseline (-7.7% versus the preceding checkpoint)
- compressed corpus: unchanged at 40,304,236 bytes

Exact decompressed bytes, bounded-reader behavior, and all 23 snapshot rewrites are unchanged.
Use one 8-KiB constant for JSON stream reader and writer buffers instead of 64-KiB backing arrays. UTF-8 output and bounded-reader behavior remain unchanged.

Measured checkpoints on the canonical stack:
- 16 KiB versus 64 KiB reduced synthetic allocation 3.45%, corpus allocation 0.36%, and peak RSS 6.1%
- the final 8-KiB midpoint versus 16 KiB reduced synthetic allocation another 0.60% without hurting corpus balance or throughput

All round-trip, exact-byte, and workload guards passed.
Write the existing single gzip member with CompressionLevel.SmallestSize. Pass capture parent-edge metadata as scalars, copy array indices only for newly created nodes, and keep the parent-edge validator static so the denser output does not carry avoidable capture overhead.

SmallestSize is the only stored-byte change. At its isolated checkpoint it increased working time 22.3% over the preceding 16-KiB pre-compression candidate, trading some throughput for 3,327,726 fewer compressed bytes; the complete stack remains substantially faster than baseline.

Canonical group-tip versus baseline:
- overall cost: 0.336458 (-66.4%)
- compressed corpus: 36,976,510 bytes (-8.3%)
- synthetic allocation: 10,777,360 bytes (-62.2%)
- corpus allocation: 12,887,797,520 bytes (-88.3%)
- working time: 120.58 seconds (-45.2%)
- CPU time: 121.73 seconds (-45.6%)
- peak RSS: 0.872x baseline

All 23 snapshots retained exactly 1,151,644,947 decompressed bytes.
Streaming staged readback proves byte integrity and enforces every JSON-level ceiling without allocating a second reconstruction graph. Derived diagnostic paths are not serialized, however, so a token stream cannot infer their parent-link, depth, cycle, or aggregate-size constraints.

Before serialization, reset only the [JsonIgnore] diagnostic-path caches and rebuild them from the serialized parent edges through RestoreDiagnosticPaths. This restores the loader's exact path preflight on trusted SaveSnapshot input while retaining the same hostile-deserialization checks. Cached paths do not affect wire bytes.

Cover both boundaries: trusted Serialize input now refuses oversized derived paths before commit, and hostile Deserialize input still refuses the same document shape.

Exact rebased final-tree canonical result versus baseline:
- overall cost: 0.336671 (-66.3%)
- weighted allocation ratio: 0.143083 (-85.7%)
- corpus allocation: 12,909,322,744 bytes (-88.3%)
- synthetic allocation: 10,808,272 bytes (-62.0%)
- compressed corpus: 36,976,510 bytes (-8.3%)
- working time: 123.22 seconds (-44.0%)
- CPU time: 124.57 seconds (-44.3%)
- peak RSS: 2,955,034,624 bytes (-10.8%)
- worst cohort allocation ratio: 0.170689 (-82.9%)
- vanilla allocation ratio: 0.131987 (-86.8%)
- Spring Collab Cookie allocation ratio: 0.156470 (-84.4%)
- Strawberry Jam Hyperlife allocation ratio: 0.170689 (-82.9%)
- Monika's D-Sides allocation ratio: 0.109662 (-89.0%)
- source compressed bytes: 40,304,236 (unchanged)
- decompressed bytes: 1,151,644,947 (unchanged)
- snapshot count: 23 (unchanged)

All 23 snapshots passed with the exact 1,151,644,947-byte decompressed total.
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 20077bfdd4

ℹ️ 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".

Require serialized field values and delegate targets so malformed v10 documents cannot turn omitted members into nulls. Cover both properties and keep streaming-ceiling fixtures valid under the stricter contract.
@Microck
Microck force-pushed the autoresearch/aight-lets-get-autoresearch-working-we-want-a-re-20260827 branch from 20077bf to 5ecfff1 Compare August 28, 2026 09:21
@Microck

Microck commented Aug 28, 2026

Copy link
Copy Markdown
Owner

@coderabbitai review

@codex review

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

@Microck: Review requested for #145.

⚠️ Action not completed

Review rate limited.

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.

@Microck

Microck commented Aug 28, 2026

Copy link
Copy Markdown
Owner

@codex review

@Microck

Microck commented Aug 28, 2026

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

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.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 5ecfff15f4

ℹ️ 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".

@Microck

Microck commented Aug 28, 2026

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

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.

@Microck

Microck commented Aug 28, 2026

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

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.

@Microck
Microck merged commit 645b1b7 into Microck:main Aug 28, 2026
1 check failed
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