Skip to content

fix(combo): force defaults over declared reasoning sentinels - #5990

Closed
RHODIZSECURITY wants to merge 3 commits into
lidge-jun:devfrom
RHODIZSECURITY:fix/combo-force-none-sentinels-20260926
Closed

RHODIZSECURITY wants to merge 3 commits into
lidge-jun:devfrom
RHODIZSECURITY:fix/combo-force-none-sentinels-20260926

Conversation

@RHODIZSECURITY

@RHODIZSECURITY RHODIZSECURITY commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Addresses #5989; the issue was auto-closed before the reproduction was expanded, and the full reproduction is now documented there.

defaultEffortMode: force currently overrides only ranked low..ultra caller efforts because concreteComboRequestBody() gates the override with isCodexReasoningEffort().

none and minimal are valid declared request sentinels, so they must also be overridden when the combo explicitly forces a default. Otherwise a forced-high combo can leak none to a downstream model that rejects it.

This patch uses isDeclaredReasoningEffort() for the caller-side force check while continuing to require the configured combo default itself to be a ranked isCodexReasoningEffort() value.

Validation on current dev:

  • combo + reasoning focused suites: 122 pass / 0 fail / 490 assertions
  • bun x tsc --noEmit: PASS
  • live RHODIZ validation: forced-high combo + caller reasoning.effort=none changed from HTTP 400 to HTTP 200; concrete Muse child wire effort is high

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.

Summary by CodeRabbit

  • Bug Fixes
    • Force mode now applies configured reasoning defaults when a caller specifies none or minimal. When the target’s reasoning capability is unknown, a caller’s none setting is preserved. This makes reasoning selection consistent across declared caller settings while retaining conservative behavior when target capabilities cannot be determined.

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: b179cc33-19da-4e20-9d36-22ff231e64cc

📥 Commits

Reviewing files that changed from the base of the PR and between 8a09f1e and 6e92953.

📒 Files selected for processing (1)
  • src/combos/request.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

Force mode now recognizes all declared caller reasoning efforts, including none and minimal. Tests expect the configured high default for those values and verify that strict mode preserves none when target capabilities are unknown.

Changes

Reasoning effort override

Layer / File(s) Summary
Recognize and test declared caller efforts
src/combos/request.ts, tests/codex-integration/combos.test.ts
The force-mode check now recognizes all declared caller efforts. Tests expect the configured high default for none and minimal, and verify that strict mode preserves none when target capabilities are unknown.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 6e929

Force mode overrides declared caller sentinels with a ranked configured effort when target capabilities permit it. When capabilities are unknown, the request follows the existing conservative behavior; no material merge risk is established.

Architecture Summary

Architecture risk: 🔵 Low · up to 6e929

The change affects 2 systems.

Changed systems: src, tests

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — src (service) was modified; 1 changed file maps to changed impact.
  • observed — tests (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in tests/codex-integration/combos.test.ts: The force-mode test now covers caller efforts none and minimal, expecting the configured high default; it also updates the test name to state that every valid declared caller effort is overridden. Existing per-target default resolution expectations remain.
  • observed — Modified behavior in tests/codex-integration/combos.test.ts: Adds a strict force-mode expectation that, with unknown target capabilities, a caller’s none effort is preserved rather than replaced by the configured high default.
  • observed — Modified behavior in src/combos/request.ts: The import adds isDeclaredReasoningEffort for checking declared caller effort values.
  • observed — Modified behavior in src/combos/request.ts: Adds documentation describing the request-cloning policy, including force-mode overrides for valid declared efforts and conservative handling when target capabilities are unknown.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: force mode now overrides declared reasoning sentinels such as none and minimal.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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.

@github-actions github-actions Bot added the bug Something isn't working label Sep 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions

github-actions Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

✅ READY

  • all PR quality gates passed; the review readiness checklist is complete.

Review readiness checklist

  • ✅ 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.

✅ 4/4 boxes ticked.

This pull request is already Ready for Review.
The review-ready label marks this PR as ready; review automation runs independently.
Maintainers: @lidge-jun @Ingwannu

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 66 / 80

콤보는 여러 모델을 하나의 이름으로 묶어 두는 길입니다. defaultEffort: high와 defaultEffortMode: force를 적으면, 요청에 적힌 추론 강도보다 콤보에 적어 둔 high를 써야 합니다. 지금은 low에서 ultra까지만 그렇게 바꿉니다. none과 minimal은 올바른 값이지만 그 목록 밖이라서, force여도 다음 모델로 그대로 나갑니다.

Meta Muse는 none을 받지 않습니다. 거절하면 HTTP 400이 납니다. Claude Code의 Auto 분류기가 이 값을 보내면, 분류기가 없다고 보고 Bash를 막습니다. 이 PR은 요청이 none이나 minimal이어도 force가 콤보 기본값으로 바꾸게 합니다. 콤보에 적어 둔 기본값 자체는 low에서 ultra 사이여야 합니다. none을 기본값으로 적으면 요청이 거절됩니다. minimal만 오고 summary가 없으면, 기존처럼 summary에 auto를 채웁니다. 요청 원본은 복사본만 고치고 그대로 둡니다. 이슈 #5989를 닫는다고 적혀 있습니다. 바탕은 dev입니다. types.ts와 config.ts를 나누는 변경은 아닙니다.

라인 - src/combos/request.ts 99줄. 대상 모델이 받을 수 있는 강도 목록을 아직 모르면 100줄에서 바꿀 값이 비고, 113줄이 요청을 그대로 돌려줍니다. force가 none을 덮으러 들어왔어도 목록이 없으면 none이 남습니다. tests/codex-integration/combos.test.ts 424줄은 목록이 없을 때 medium이 남는지만 확인합니다. none이 같은 길로 나가는 테스트는 없습니다.

메인테이너의 판단이 필요한 지점

강도 목록을 모를 때도 none을 뺄지, 지금처럼 남겨 둘지 정하면 됩니다. 목록을 아는 Muse 경우는 이 PR로 고칩니다. 이슈 #5989는 재현 절차 칸이 비어서 품질 봇이 not_planned로 이미 닫았습니다. 머지할 때 Closes #5989는 이미 닫힌 이슈를 다시 열지 않습니다. 고침으로 묶으려면 이슈를 다시 열면 됩니다. 이 PR은 아직 초안이고 준비 체크는 0/4입니다. 같은 수정의 다른 열린 PR은 없습니다. 바탕은 이미 dev라서 옮길 이유가 없습니다. types.ts/config.ts 분할 때문에 닫을 이유도 없습니다.

너의 추천

none과 minimal까지 force가 덮는 방향은 맞습니다. 목록이 있을 때 high로 바꾸는 테스트도 맞습니다. 목록이 없을 때 none이 남는 경우를 테스트 한 줄로 적어 두면, 일부러 남기는 것인지 나중에 헷갈리지 않습니다. 그 한 줄과 준비 체크를 채운 뒤 머지하면 됩니다.

이 댓글은 grok-bot이 작성했습니다

@RHODIZSECURITY
RHODIZSECURITY force-pushed the fix/combo-force-none-sentinels-20260926 branch from fcde467 to 6a5ecca Compare September 26, 2026 18:42

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Pull request base or head changed.

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.

@RHODIZSECURITY
RHODIZSECURITY force-pushed the fix/combo-force-none-sentinels-20260926 branch from 8a09f1e to 6e92953 Compare September 26, 2026 19:26
@RHODIZSECURITY
RHODIZSECURITY marked this pull request as ready for review September 26, 2026 19:26
@Ingwannu Ingwannu added the maintainer-sponsored Maintainer sponsors this change to an auth, workflow, release, or dependency surface label Sep 26, 2026
@Ingwannu

Copy link
Copy Markdown
Owner

Maintainer sponsorship added after exact-head source review found the combo reasoning-sentinel override narrow and internally consistent. This starts executable CI; it is not merge approval. I will make the final review decision from the resulting exact-head checks.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Approved on exact head 6e929536 after source review. The change is confined to valid declared none/minimal sentinels, while the concrete target ladder, malformed input, fallback mode, and unknown capability remain conservative. React Doctor is green; merge remains conditional on queued exact-head Cross-platform CI.

@Ingwannu

Copy link
Copy Markdown
Owner

Exact approved head 6e929536b1 now has a fully successful Cross-platform CI run, including all four test shards, gates, desktop shell and aggregate ci. Existing approval remains valid; merge can proceed through the normal maintainer gate.

lidge-jun added a commit that referenced this pull request Sep 27, 2026
…ch 9E) (#5998)

Carry the owner's Remote Link, restart, desktop supervision and Codex routing fixes onto dev in their original order, then carry RHODIZSECURITY's combo reasoning fix as one attributed commit.

| PR | Change | Author |
| --- | --- | --- |
| #5970 | Turn a standalone computer into a Child from its dashboard; keep Codex on its local loopback URL and protect the linked data plane. | lidge-jun |
| #5973 | Reconnect the Child's SSH tunnel after sleep, outages and crashes. | lidge-jun |
| #5972 | Heal opencodex-owned Codex routing left on a dead loopback endpoint, with ownership and race gates. | lidge-jun |
| #5971 | Keep a proxy on the configured port through a Child restart. | lidge-jun |
| #5974 | Let the desktop app supervise runtime restarts and unexpected exits. | lidge-jun |
| #5990 | Apply forced combo defaults over declared none/minimal reasoning sentinels. | RHODIZSECURITY |

The carry keeps the 9D one-use sibling handoff and passes link status, cached key and tunnel gate through the Child listener. Separate integration commits bound the port-conflict regression test and keep carried files below the file-size guard, including newer dev's layout entries. The five owner commits retain JUN's authorship; the #5990 squash retains RHODIZSECURITY's commit identity and noreply co-author trailer.

An independent review found four integration defects. Each repair is a separate Codex-authored commit:

| Finding | Commit | Repair |
| --- | --- | --- |
| Linked requests could fetch without a connected tunnel. | 6a29f7b | Require a positive supervisor connected verdict before every fetch; missing, failed and stopped supervision return 503 without forwarding key or body. |
| IPv4 and IPv6 destinations on one port shared one probe/streak key. | 8903998 | Probe and track each hostname and port separately; a live endpoint blocks healing and an address change starts a fresh dead-probe streak. |
| A same-port route change could pass the locked write guard. | f62e43b | Abort when admitted config bytes or the complete destination set changes under the lock, then require fresh probes. |
| Orphan reaping could KILL a reused PID. | e0ef426 | Record the process start identity and revalidate argv, start time and orphan status before TERM and before KILL; legacy records lacking start identity never authorize a signal. |

A second review confirmed those four repairs and found two remaining blockers:

| Finding | Commit | Repair |
| --- | --- | --- |
| A competing local listener received the readiness key and private relay traffic before SSH bound the tunnel port. | 39f246a | Require an exclusive local LISTEN socket owner PID matching the SSH child before every keyed probe and relay admission; adopted processes also need matching pidfile argv and start time. Unknown scans fail closed. |
| Newer dev mappings made the merge result exceed the layout file-size guard. | 3bb2ab6, 46ee24f | Merge origin/dev at a91568e, then compact formatting while retaining every explicit mapping. |

A third review confirmed the competing-listener and layout repairs, then found three lookup defects:

| Finding | Commit | Repair |
| --- | --- | --- |
| Minimal Linux lacks lsof/netstat and never proves the SSH listener. | 9c66251 | Use tool-independent async /proc/net/tcp{,6} inode lookup, checking the expected SSH PID's fd symlinks first. |
| A foreign ::1 listener shares the numeric port with the owned IPv4 forward. | 9c66251 | Match only the exact 127.0.0.1 address and port on Linux, macOS and Windows. |
| Synchronous owner scans block Bun on every relayed fetch. | b5e565d | Use bounded async lookups and a one-second positive proof keyed by port, SSH PID, start identity and tunnel generation; re-prove after restart. |

The branch also merged current dev at 35f267d in 51747c9. The merged test registries retain both lanes' mappings and the management contract retains Kiro's account projection and Child join.

Current dev through `2a3cfa5abe` was merged again in `5856179cd1` without conflicts. It brings #6012's macOS plugin ACL fix and dev's Kiro projection test clock correction; `scripts/test-layout/layout.json` stays at 1,997 lines. The merge changes no link/relay or server-management-auth files.

A fourth review found that a one-second proof cache could survive a local port takeover, and that an adopted PID's start identity was only checked at adoption:

| Finding | Commit | Repair |
| --- | --- | --- |
| Cached ownership authorized the next keyed probe or relay after a port takeover. | b8142ad | Every keyed probe and every relayed fetch now obtains a fresh bounded asynchronous socket-owner proof; concurrent admissions do not share a cached success. |
| A reused adopted PID retained its old trusted start identity. | b8142ad | Re-read current argv and start time on every adopted admission, invalidate trust and mark the link failed on mismatch. |
| The TCP listener can change after the check and before connect. | bee1613 | Record this pre-existing residual race and a private Unix-domain SSH forward as future hardening in the link structure contract. |

A fifth review found that transient unreadable adopted identity was treated like a confirmed replacement:

| Finding | Commit | Repair |
| --- | --- | --- |
| One null or timed-out identity read permanently disabled a live adopted link. | 0eefebf | Return an explicit unknown verdict; deny only the current keyed admission and retry on the next check without discarding the adopted record. |
| A confirmed changed identity left the old adopted PID blocking recovery. | 0eefebf | Release the stale adoption and pidfile without signalling that PID; the next supervisor tick starts its own SSH tunnel. |

Windows CI follow-up: `88fbb539af` samples the relay hold clock once per attempt. The initial reconnect wait now receives the full 15-second budget even when the wall clock ticks during admission; later retries still subtract elapsed time.

Windows teardown follow-up: `0171b4856c` makes `server.stop(true)` await any timed-out `icacls.exe` child still reaping after config-directory hardening settles. The stop promise now marks the actual handle-release boundary before a caller removes the home.

Security review: Child join still refuses Tailscale identity, a non-standalone role and a mismatched live port before SSH. Linked data routes retain the Host/Origin gate, committed-key fingerprint, caller-credential stripping and inbound byte cap. The relay now sends no key or request without positive tunnel supervision, and the supervisor obtains a fresh bounded asynchronous exact-IPv4 owner proof before every keyed probe and relay fetch; adopted processes also have their current argv and start time checked each time. An unknown read refuses only that admission; a confirmed mismatch releases the adopted PID without signalling it. Desktop supervision stays bound to its live parent, and dashboard Stop is refused before teardown while CLI/tray Stop remains available. Routing self-heal writes only owned loopback routing after all distinct endpoints were proven dead and the locked bytes were rechecked. The existing home-bound stop proof and sibling Desktop-write gate remain intact.

![Child role selectable](https://github.com/lidge-jun/opencodex/blob/3aa948da9e5b1c6dc47c9c45ab08e47fa5b95ece/260927-child-link-turn-on/05-role-select-child-enabled.png?raw=true)
![Find Home sheet](https://github.com/lidge-jun/opencodex/blob/3aa948da9e5b1c6dc47c9c45ab08e47fa5b95ece/260927-child-link-turn-on/06-find-home-sheet.png?raw=true)

Co-authored-by: RHODIZSECURITY <180237049+RHODIZSECURITY@users.noreply.github.com>
@lidge-jun

Copy link
Copy Markdown
Owner

Thanks! This landed on dev through merge train batch 9E, #5998 (merge 5744e7a), as one commit with you as the author and a Co-authored-by trailer. Closing since the content is now on dev.

@lidge-jun lidge-jun closed this Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working maintainer-sponsored Maintainer sponsors this change to an auth, workflow, release, or dependency surface review-ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants