Repository navigation
Integrate OpenCodex v2.78.0 with Haly features and bundled RTK - #3
Draft
WanxTitanx wants to merge 1012 commits into
Draft
WanxTitanx wants to merge 1012 commits into
WanxTitanx wants to merge 1012 commits into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Comment |
|
⏳ DRAFT
What to do
Review readiness checklist
1/4 boxes ticked. This pull request was already a draft. Its draft status will be preserved after every issue above is resolved. |
Carry legacy fallback and refresh skew from lidge-jun#6378 at 3db2ab4. Verify fully rotated Claude pairs against bearer-bound account identity and capture ownership from one coherent store snapshot. Preserve unresolved history and refresh intent without guessing account ownership. Co-authored-by: Epinephrine <luvs01@hanmail.net>
fix(responses): stabilize large native HTTP uploads (carry lidge-jun#6508)
…-c-ollama fix(ollama-native): retain tool batches across assistant commentary
Retain standalone pairing carry and its unique real-HTTP regression after shared registry normalization and upload integration.
…-a-messages fix(claude): keep native context failures terminal in Messages
fix(antigravity): group Claude 5.5 usage and derive reference prices
fix(codex): classify revoked native sessions without stale attribution
Carry the credential-provenance and refresh work from lidge-jun#6507 (6108244 and 7ffd1a8). Bind native refusal to the physical profile and grant, preserve caller-owned credentials across preview and retry, and retain only fixed refresh diagnostics. Keep terminal-probe attribution from the parent lidge-jun#6515 correction. Co-authored-by: Vadym O <bolein95@gmail.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…-e-identity fix(oauth): preserve Claude identity across token rotation (carry lidge-jun#6378)
…i-parity-foundation # Conflicts: # scripts/test-layout/layout.json # tests/fixtures/test-layout-expected.json
…ounts-settings feat(cli): complete account policy and runtime settings workflows
…egrations-maintenance feat(cli): complete integration recovery and maintenance workflows
…ervation-api feat(cli): complete observation and explicit-key API workflows
…to Windows (lidge-jun#6599) cli-access-audio: /dev/null does not exist on Windows, so the stat fails as a read error (exit 1) instead of a usage refusal (exit 2). Keep the directory case strict everywhere, use NUL on Windows, and assert the device is refused with no request sent on every platform. cli-account-login-options: new URL(..., import.meta.url).pathname is /D:/... on Windows and cannot be imported by the --eval child. Use pathToFileURL(repoPath(...)).href.
…ge-jun#6596) * docs(devlog): plan Claude settings single page and Desktop model roles * feat(gui): lay Claude Code settings out as one page with a sticky save bar * fix(gui): make a successful Claude Code save the baseline before its refresh * feat(gui): lead Claude Desktop with default and quick task models, tiers under Advanced * fix(gui): keep Claude Desktop import and export reachable with no models * docs: describe the one-page Claude settings and Desktop model roles * perf(gui): single pass for Desktop role defaults, toSorted for the list order * fix(gui): show the normalized interception rows once a Claude Code save succeeds * refactor(gui): build the Claude Code save body from the submitted draft * fix(gui): drop Claude Code reads that a successful write has superseded * fix(gui): keep reads that overlap a Claude Code save out of the session cache * fix(gui): publish the Claude Code save cache from the latest confirmed switches * fix(gui): show a committed Claude switch even when its reread fails * fix(gui): share the Claude Code write epoch across mounts * fix(gui): build the Claude Code save cache from the shared session copy * fix(gui): fold shared Claude Code reads into the draft of the page on screen * fix(gui): deliver Claude switch acknowledgements to the page on screen * fix(gui): deliver Claude Code save confirmations to the page on screen * fix(gui): keep edits made while a Claude Code save is out * docs(devlog): record the Claude Code save hardening from review
…ge-jun#6600) * test(oauth): remove proxy keys case-insensitively in startup-proxy children The startup-proxy refresh cases failed on Windows (dev dadc232, CI run 37227252582, shard 6/9): after the child deleted the six fixed proxy key spellings, outboundProxyConfigured() still returned true. Windows environment names are case-insensitive, so an inherited spelling outside that fixed list survives. Both the parent env handed to the child and the child's own cleanup now remove every key whose upper-cased name is HTTPS_PROXY, HTTP_PROXY or ALL_PROXY, and the precondition assertion names any proxy key still visible. The production startup-proxy guard is unchanged. * test(oauth): only require an observably proxy-free env where deletion is observable Windows CI run 37229867142 showed the real cause of the shard 6/9 failure: on win32 Bun 1.4.0, deleting a process.env variable removes it from enumeration (no proxy key remains in Object.keys(process.env)), but property reads still return its value, so outboundProxyConfigured() stays true. The "deleted" child therefore keeps its strict current-env precondition on every other platform, and the "empty" child keeps it everywhere. The startup snapshot and intent retention assertions run on all platforms. Production behavior is unchanged; on Windows a runtime deletion simply leaves the guard closed.
…; state unhealthy in-place shim status (lidge-jun#6602) * test: make catalog audit and provider proxy fixture robust on Windows runners Compare the audit opencodexHome with redactUserPath of the same path, so long, 8.3 and non-home temp roots all hold. Fail only the audit file ACL in the Windows audit privacy cases; the catalog writer legitimately hardens its own backup on real Windows. Bound the provider proxy fixture child at 45s on Windows (12s elsewhere) under a deadline 3s above it, and report signal, elapsed time and bound when it is killed. * fix(codex): state the unhealthy verdict in in-place shim status diagnoseCodexShim computed healthy:false for a damaged Windows in-place wrapper, but its summary only said "shim present", so ocx codex-shim status read a broken wrapper as fine. Append the unhealthy verdict and repair command when the diagnosis is unhealthy, matching the overlay summary. A host-independent regression records a legacy win32 in-place state; it fails without the fix.
…come (lidge-jun#6595) * docs(devlog): close the CLI update restart unit with its delivery outcome lidge-jun#6556 merged as 7cf1b76, so its devlog unit moves from _plan to _fin with the recorded outcome: the final-head unmocked POSIX acceptance and its limits, the runtime-readiness gate and lidge-jun#6548 message carry, the test isolation fix, and the lidge-jun#6548 disposition. Co-authored-by: agentHits <140916359+agentHits@users.noreply.github.com> * docs(devlog): record lidge-jun#6548 closure in the restart unit delivery outcome --------- Co-authored-by: agentHits <140916359+agentHits@users.noreply.github.com>
…idge-jun#6597) * fix(integrations): write DSH routes to the Desktop profile patch it reads DSH 0.1.7+ imports $DSH_HOME/settings.yaml once into the first profile that boots and renames it to settings.yaml.imported. From then on it reads provider routes from the llm-pi-ai row of a profile patch (a top-level YAML list of loader rows) and hot reloads that file. The integration kept writing settings.yaml, so after that first import a catalog refresh, a model change or a disable reached nobody, and status read the renamed file as absent. Declare the Desktop profile's cordis.patch.yml as DSH's currentStore (the seam from lidge-jun#5348), addressed through a leading [id=llm-pi-ai] selector. The home patch is not an alternative: a home row replaces the profile row's whole config, the user's own routes with it. - merge.ts keeps a sequence root, and prunes an element it seeded once only its selector fields remain. - The source-preserving YAML patcher edits one top-level list entry as the block map it holds and restores its "- " and two-space indent byte for byte. DSH's empty `[]` is the only flow form adopted, and a disable that empties the list writes it back. - IntegrationTarget carries its own sourcePreservingYaml, so the legacy file and the store are patched along their own paths, and a coordinated write also holds DSH's config-editor lock (the profile's package.json.lock) whenever the profile directory exists. - Without a Desktop profile the legacy settings.yaml stays the target. - The dashboard accepts the new plan path; GUI text, docs and the integrations structure doc describe the new location. * test(gui): pin the DSH ownership copy to the Desktop profile path The locale-parity fixture still held the settings.yaml sentence in every locale, and the DSH surface test asserted the old llm-pi-ai.providers spelling. Both now follow the copy: the llm-pi-ai row, the Desktop profile patch, and the settings.yaml fallback. * fix(integrations): keep DSH profile refresh order and lock late profiles Refreshing a Desktop profile row that OpenCodex created no longer deletes and re-appends it in the expected merge, so a row DSH appended afterwards no longer turns a routine catalog refresh into an "unsafe" refusal. The created-row provenance is kept so disable still removes it. The profile manifest lock is now chosen after the settings lock is held and re-checked after every revalidation await, so a profile that appears mid-write is locked and revalidated before it is read or written. Removing the last managed row also keeps the file's original final-newline and CRLF convention. * fix(integrations): refuse restoring into a missing DSH profile directory A confirmed restore of a journaled Desktop profile write used to recreate a removed profiles/desktop directory and write it without the profile's package.json.lock. Preview and restore now refuse as unsafe when the declared locked store's directory is missing, and the structure doc records the lock re-probe, row-order, and restore contracts. * docs(structure): fit the DSH store paragraph inside the integrations budget Merging lidge-jun#6577 put structure/clients/integrations.md four lines over its 600-line budget. Tighten the DSH paragraph without dropping any contract. * fix(integrations): report a booted DSH profile without a patch instead of writing settings.yaml With profiles/desktop/package.json present and cordis.patch.yml missing, the target fell back to $DSH_HOME/settings.yaml with no ineffective marker. DSH imported that file when it booted the profile and never reads it again, so the write was lost without a word. A store declaration can now name a missing store the client still reads; DSH's does, and the write is refused as an ineffective one with the remedy (create the patch as `[]`). * docs(integrations): state why a DSH profile without a patch is refused The comments, structure doc, and refusal message said DSH imports settings.yaml once and never reads it again. Upstream DSH's importLegacyDocument renames settings.yaml to settings.yaml.imported and imports it on every startup where it exists. The refusal stays: a block written there would be moved out from under opencodex's ownership record. Only wording changes; behavior and tests' assertions are unchanged. * feat(integrations): show the missing-store remedy in the dashboard A DSH Desktop profile whose cordis.patch.yml is missing is refused as superseded_store, and the CLI names the fix: create the patch containing `[]`. The dashboard only had the generic superseded-store copy, which says the client reads a file opencodex does not write and offers no way out. - The missingStore declaration publishes its empty document (`[]` for DSH) beside the remedy text, and IneffectiveWrite carries it. - Status rows carry supersededReason beside supersededBy, plus missingStoreDocument for a missing store. - A superseded_store plan carries the same two fields. The plan still names no file (the path stays on the status row), and the fingerprint does not change: the bound ineffective-write token already covers this finding. - The GUI accepts the fields only on a superseded_store refusal, the document only for missing-store and only as one short line, and renders copy that names the file and the document in all eleven locales. * fix(integrations): name the missing store in the dialog and decode it in the CLI - The apply dialog covers the page's status notice, so a refused DSH preview now names the patch path as well as `[]`. The path comes from the status row; the plan still names no file. Bulk dialogs, which have no single status row, keep the pathless copy. - The Turkish copy names the legacy settings file explicitly instead of "that file". - The CLI plan decoder from lidge-jun#6542 accepts supersededReason and missingStoreDocument under the same contract as the GUI, and `ocx integration client preview` prints the remedy. Both decoders now reject a non-string reason and a document that is not one short printable-ASCII line, since the CLI echoes it to a terminal. * fix(gui): wrap long missing-store paths in the DSH notice and plan dialog --------- Co-authored-by: JUN <jun@lidgeai.com>
…-list next steps (lidge-jun#6611) * fix(cli): show account health actions, paid-credit consent, and empty-list next steps * fix(cli): never echo an id that fails the selector allowlist in account recovery lines
… in leaf help (lidge-jun#6609) * fix(cli): correct help and CLI reference text and show declared flags in leaf help * test(cli): follow the corrected restart help summary
…te-failed, and ZCode guide text (lidge-jun#6619)
…ss (lidge-jun#6601) * fix(management): keep inference ports independent of management ingress * fix(management): keep Cursor gateway on the bound inference port; cover ingress export Cursor status now prefers the lifecycle-bound public port, then the PID-matched runtime record, then config, so a management-only ingress port can never become the advertised gateway. Adds a real-server regression that exports a client config through hub management ingress and asserts the public bound port, plus Cursor precedence cases, and records resolver ownership and known limitations in ADR-6598. * fix(management): use the live bound port for Desktop provider-change auto-apply autoApplyDesktopBestEffort wrote the Desktop 3P config from config.port, so a CLI override or ephemeral bind could leave Desktop pointing at a port nothing serves. It now uses managementInferencePort like the other management writers; the roster-update fixture asserts the live port reaches the writer. --------- Co-authored-by: Ingwannu <ingwannu@users.noreply.github.com> Co-authored-by: JUN <jun@lidgeai.com>
…6588) * fix(responses): normalize native upstream session aliases * test(responses): expect normalized session_id for caller aliases; state alias precedence Canonical ChatGPT egress now fills session_id from session-id/thread-id, so the Claude affinity and Chat affinity wire expectations follow it. Adds a two-alias precedence case and documents exact precedence, the bridges' empty-value filtering, and that aliases are forwarded raw like an explicit session_id. * fix(responses): treat empty session headers as absent when normalizing aliases Upstream auth header selection already drops empty values, so the alias helper now does the same. First attempts and retries rebuilt from raw caller headers pick the same upstream session_id. Docs state the precedence for non-empty headers. * test(responses): cover caller session identity across auth replay --------- Co-authored-by: JUN <jun@lidgeai.com>
… #debug after the GUI regroup (lidge-jun#6612) * fix(gui): keep short sidebars, Claude sidecar rows and Save errors usable; open legacy #debug on Debug Audit follow-up for the GUI merged since v2.77.0 (lidge-jun#6579, lidge-jun#6593, lidge-jun#6596): - A short or zoomed desktop window no longer collapses the sidebar menu to its padding: the menu keeps about three rows and the whole rail scrolls only when it cannot fit, with the language menu kept on screen. - The Claude web search and vision sidecar rows wrap their controls under the copy instead of covering the title (French at 768px) or clipping the model input (390px). - A failed Save on the one-page Claude settings reports in the Save bar, where it was clicked; the bar status wraps instead of sliding under Revert. - Cold-loading a legacy #debug bookmark selects the Debug tab, reading the canonical hash like Connect and Providers do. Findings and plan: devlog/_plan/261005_r4_gui_audit/. * fix(gui): keep the short-window language menu on screen in every engine Review on lidge-jun#6612: the rail backdrop-filter makes the sidebar the containing block of the fixed language menu, so an engine that treats it like an absolute child would scroll and clip it with the rail. In windows 480px tall or less the rail is now opaque, as in the existing no-backdrop-filter fallback, which anchors the menu to the window; the menu is opaque too.
… the dashboard (lidge-jun#6613) * docs: sync Connect, Claude settings and DSH profile-patch guides with the dashboard The integration guides still sent readers to an Integrations tab that is called Connect since lidge-jun#6593, the DSH sections named the legacy settings.yaml mapping as the only owned path after lidge-jun#6522 moved it to the Desktop profile patch, and the Claude GUI sections listed the pre-lidge-jun#6596 order without the Save bar contract. English and the seven translations now match the shipped dashboard. * docs: name the DSH missing-patch refusal and finish the Connect → API Keys rename Review on lidge-jun#6613: a Desktop profile without cordis.patch.yml makes Apply refuse with the create-[] remedy rather than write the patch or fall back to settings.yaml, and the remote-hub, CLI lifecycle and Codex integration pages still pointed at Integrations → API Keys or the Integrations overview.
…e-jun#6591) * fix(test): keep armed test processes out of the real Codex home A local suite run rewrote the real ~/.codex catalog twice (lidge-jun#6529): a convergence ran with OPENCODEX_HOME in the test temp tree and CODEX_HOME unset, so it resolved os.homedir()/.codex, which ignores the preload's HOME on macOS. The real-home guard covered the OpenCodex home and native auth.json, not the catalog, models cache, journal or config.toml. atomicWriteFile now refuses any write whose directory is the real Codex home in an armed test process, and K refuses it before the owner precheck, so a test never gets a catalog permit for it. Refs lidge-jun#6529 * test: probe the unset-CODEX_HOME fallback against the real-home guard Run the probe child with CODEX_HOME absent and HOME/USERPROFILE at the sentinel home, check getCodexHome() resolves there, and check every Codex-home write and K are refused. This is the path the incident took. --------- Co-authored-by: JUN <jun@lidgeai.com>
…ot starve claude.ai (lidge-jun#6511) (lidge-jun#6610) * fix(claude): serve the Desktop picker over HTTP/2 so SSE streams cannot starve claude.ai (lidge-jun#6511) The picker listener terminated claude.ai with an HTTP/1.1-only TLS server. Claude Desktop keeps several messages/stream SSE subscriptions open, each holding one of Chromium's six per-origin HTTP/1.1 connections, so later claude.ai requests queued in the client and timed out before reaching OpenCodex. Blind tunnels negotiate HTTP/2 with Anthropic and multiplex. The listener port is now a TCP front that reads the TLS ClientHello ALPN offer (bounded multi-record reassembly) and splices the untouched connection to an HTTP/2 server when the client offers h2, or to the existing native HTTP/1.1 relay otherwise (WebSockets included). HTTP/2 requests are translated for the HTTP/1.1 upstream (:authority -> Host, cookie crumbs joined) and cancellation follows the underlying stream. Shutdown force-closes every front, bridge, h2 and HTTP/1.1 socket. * fix(claude): bound picker h2 fan-out and refuse unrelayable h2 targets Security review of lidge-jun#6610: an HTTP/2 :method or :path that the HTTP/1.1 client cannot express threw before cleanup was installed, and one connection could open unbounded streams, each dialing upstream. Validate h2 targets and guard request construction (empty 400, fixed log line), advertise maxConcurrentStreams 100 per session and cap in-flight upstream requests at 256 listener-wide (empty 503 without dialing). * fix(claude): refuse picker targets the URL parser rejects Security re-review of lidge-jun#6610: an origin-form h2 path such as //[ passed the target check but threw in new URL() before the refusal boundary. Parse the pathname inside it and answer an empty 400. * fix(claude): do not log a client-cancelled picker request as 502 Hosted CI on lidge-jun#6610: cancelling an h2 HEAD before upstream headers closed upstream as intended, but the teardown error then wrote a 502 log line for a client that had already gone. Ignore upstream errors once the client side closed first. The ALPN test now asserts only that HTTP/1.1 clients never get h2: Bun's native HTTP/1.1 server does not report its ALPN choice.
…lidge-jun#6618) * fix(cli): stop echoing values in claude desktop apply argument errors parseDesktopApplyArgs printed unknown arguments verbatim, so an inline --token=<value> or a stray credential operand reached the terminal. Show options by name only and bare operands as <redacted>. * fix(cli): never echo rejected claude desktop arguments Security review of lidge-jun#6618: option names can still carry values (-tVALUE, dash-prefixed operands) and control characters. Apply errors now count unknown arguments and list the valid options; move/default show a route operand only when it is a plain provider/model id. * fix(cli): keep desktop bind and profile file errors free of operands Security re-review of lidge-jun#6618: bind errors echoed a rejected picker id and an unavailable route, and import/export printed filesystem errors that carry the user-supplied path. Binding errors now omit the id and show a route only as a plain provider/model id; profile file failures report the operation and error code. * fix(cli): drop rejected route operands from desktop errors Security re-review of lidge-jun#6618: a route that only looks like provider/model is still a rejected operand. move/default and bind now say the route is unavailable and point to ocx claude desktop show, without echoing it.
…dge-jun#6625) * fix(gui): keep Claude Desktop role selects inside the Models card A long unavailable stored model plus its status overflowed the role select at 390px (chevron and status clipped) and squeezed the label column to nothing at 768px. Bound the controls column, let the route truncate inside the trigger while the translated status and chevron stay whole, and put the full text in the trigger tooltip. * test(gui): cover the unavailable role choice label and tooltip The route sits in its own truncating span, the translated status in a separate element, and the trigger's tooltip carries the full text.
…ffers Retry (lidge-jun#6623) * fix(gui): start the integration dialog on Close and offer Retry when client status fails Found by the R4 audit of lidge-jun#6597: showModal() focused the invisible backdrop dismiss button, so the dialog opened with no visible focus and Space dismissed it unseen; and a cold status-load failure on a client page had no way to retry. * docs(devlog): record the lidge-jun#6597 GUI audit and the R4 CI plan * test(gui): cover the dialog's initial focus and the client-status Retry
…oxy (lidge-jun#6622) * fix(cli): name ocx start when integration preview finds no running proxy * test(cli): pass preview stopped-proxy cases as object rows
…in argument errors (lidge-jun#6608) * fix(cli): reject arguments to uninstall and redact credential values in argument errors * fix(cli): keep adjacent credential options and option-shaped positionals redacted; cover models leftovers * fix(cli): redact bare leftovers whenever argv carried a credential option * fix(cli): scrub argv credential operands from console diagnostics as a last-line guard * fix(cli): scrub only diagnostics streams and always collect inline credential operands * fix(cli): redact credential-shaped unknown provider subcommands at the output site
…th, update; validate provider add before saving (lidge-jun#6614) * fix(cli): honest exit codes and JSON receipts for config, alias, health, update; validate provider add before saving * fix(cli): name the recovery path when provider changes are refused by config validation
… management refusals (lidge-jun#6615) * fix(cli): name the real cause and next action in restart, update, and management refusals * fix(cli): stop the owning proxy before reinstall advice; scope integration writer detail to the normalized route * fix(cli): render fixed integration recovery guidance instead of writer prose * test(cli): expect the no-request stopped-proxy guidance on Codex login routing
….78.0 [WRONG BRANCH] release: 2.78.0
Preserve upstream grouped navigation, Haly API-key quotas and model scopes, Headroom, and bundled RTK. Reconcile credential continuity and typed recovery; translate extension controls into Portuguese and align the development version at 2.79.0.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
93cdffd6ac7f125d4b932a6d45af5c3ab1de5156). The new merge head is5f1052c00a39d8154a438768c45acfbee3af3783, preserving both the old Haly/RTK candidate and the new release as ancestors.ocx rtk.7d_oipolicy.devpolicy; this is a candidate based on the stable 2.78.0 release, not an official 2.79.0 release.Haly's
devwas reconfirmed atdac1d25f48fad18420aa856631ff9ee9c1775b0f; no newer Haly release was listed. The historical branch name is retained to keep this existing proposal and discussion together.Verification
Current candidate, pinned Bun 1.4.0:
bun run typecheckbun run buildbun run lintandbun run lint:i18nbun run buildbun run structure:checkbun scripts/file-size-ratchet.tsbun run skill:surface:checkbun run privacy:scanbun run prepare:packageandnpm pack --ignore-scriptsThe npm candidate contains all five pinned RTK executables with executable modes, LICENSE/NOTICE, built GUI and compatibility metadata. Artifact:
bitkyc08-opencodex-2.79.0.tgz, 37,033,376 bytes, SHA2567341208399185b44bb3bcaa2078fd422000c8ef0995cecf2bc28cdfbea48cc0c.Automated unit/integration test suites were not run in this session. Compilation, static checks and screenshot rendering do not replace them. Historical tests of the previous candidate are not claimed for this head. Focused/full tests required by repository policy, exact-head CI, independent security review, Windows/macOS runtime execution and live provider inference remain pending. No release, live installation, provider reconfiguration or service restart was performed.
GUI evidence
Built candidate, isolated local fixture, synthetic providers/key. Headroom and API-key detail controls rendered in Portuguese with no captured browser error/warning entries. The fixture logged an Anthropic model-discovery HTTP 401. This proves the displayed UI only, not successful provider discovery or real inference.
Review evidence and limitations. Images are on the separate
pr-assetsbranch, not in the feature branch.Checklist
The PR remains draft. The contributor has read-only access to this repository and cannot apply its maintainer sponsorship or merge decision. The existing
unsponsored_surfacehygiene gate requires a maintainer-appliedmaintainer-sponsoredlabel following review. That label does not replace independent security review, required tests or exact-head CI. CodeRabbit's success status on a draft is not independent-review evidence.Co-authored-by: halysondev halysoncesar2020@gmail.com
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
Required local validation passed; commands, results, and any full-suite exception are documented.
I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.