Skip to content

feat(agent): xhigh and max reasoning-effort rungs where the model's provider takes them - #1123

Open
Handsome-wzw wants to merge 16 commits into
mainfrom
feat/effort_xhigh_max
Open

Handsome-wzw wants to merge 16 commits into
mainfrom
feat/effort_xhigh_max

Conversation

@Handsome-wzw

Copy link
Copy Markdown
Contributor

Summary

Two more reasoning-effort rungs, xhigh and max, for a conversation whose
model is served by the Anthropic Messages adapter -- the follow-up #1113 left
out on purpose.

Base: cut from feat/session_reasoning_effort (#1113), which is not merged
yet, so this PR shows #1113's commits beside its own until #1113 lands. The
change of this PR is the one feat(agent) commit; the merges after it bring
in origin/main and #1113's later head (its merge with main and its fix that
reads the opened conversation's effort), so the diff against main is #1113
plus this.

Design, settled from the code:

  • The words a session may pick come from the provider of the session's
    model, not from one global tuple. New LLMProvider.reasoning_efforts(model)
    (raven/providers/base.py) answers the four every wire takes
    (REASONING_EFFORTS); AnthropicMessagesProvider answers the keys of its
    _ADAPTIVE_EFFORTS table, which is six (xhigh, max over high), one
    answer per wire rather than per model (a model that refuses a rung says so in
    a 400 and rewrite_on_400 already turns the label into a budget there); the
    OpenAI-shaped adapters and litellm keep the four. LazyProvider,
    PerModelProvider, ResolvingProvider and EndpointRotorProvider forward it
    the way they forward reasoning_wire_keys, pinned by name in a test.
  • session.set_effort answers options from the provider of the session's
    own binding (a draft gets the default model's), and refuses a word the
    provider does not take with a sentence naming the model and the words it
    takes. With no loop or a provider that cannot answer, the four stand.
  • The console checker for agents.defaults.reasoningEffort stays at the four,
    on purpose: that key reaches every model call on every vendor and every
    sub-agent (RAVEN_PARENT_REASONING_EFFORT), so a rung only one wire takes
    would be refused everywhere else with no per-session way out. Written on
    REASONING_EFFORTS and at the checker. The settings page therefore keeps
    its four rungs.
  • The record may carry any rung this raven knows: REASONING_EFFORT_RUNGS
    (config/schema.py) is the retry descent's REASONING_EFFORT_LADDER read
    upward, so a pick and a retry never disagree about which rung is higher, and
    session_effort.of reads xhigh/max back after a restart.
  • The model can move after the pick (/model, the picker), so the turn asks
    its own provider again: session_effort.fit runs a pick the new wire does
    not take at the highest rung it does take (max on a Claude, then a switch
    to a four-word model, runs at high), logged, rather than at a request the
    wire would refuse or at the default the person moved away from. The pick
    only: a mode's reasoningEffort is the catalogue's word and goes out as
    named, as before. A provider that cannot answer leaves the pick as named,
    and nothing on that path fails a turn.
  • lower_reasoning_effort already descended from max/xhigh; the tests now
    say so explicitly, on the label-only wire and on the Anthropic one.

Surfaces: the picker row names the two rungs (gui.effort.xhigh / .max,
en + zh) and, after a model switch, re-reads the row so the words are the new
model's; a pick the words no longer carry is drawn after them, ticked, so it
can be moved off rather than a row with no rung pressed. The TUI's /effort
help and usage list the six words and say where the top two apply. The offline
page library's conversation runs on a Claude, so its fixture offers six. The
using-raven guide (en + zh), CHANGELOG (Unreleased, its own bullet) and
CONTEXT.md's Session Reasoning Effort entry say the above; openrpc.json
describes effort and options as the model's words, and both generated
contracts were regenerated.

Type

  • Fix
  • Feature
  • Docs
  • CI / tooling
  • Refactor
  • Other

Verification

  • pytest tests/test_session_effort.py tests/test_rpc_session.py tests/test_agent_loop_usage_sink.py tests/test_agent_loop_empty_recovery.py tests/test_provider_protocol.py tests/test_rpc_settings.py tests/test_rpc_console.py tests/test_import_cycle_budget.py tests/test_rpc_schema_match.py tests/test_rpc_registration.py tests/test_rpc_session_init_bundle.py -- pass

  • full pytest tests -- see the first comment for the count and the baseline failures

  • scripts/coverage_gate.py diff --base-ref origin/main -- see the first comment

  • ruff check / ruff format --check / ty check on the touched modules, lint-imports -- clean

  • ui-web: npm run gen (contract regenerated), vitest run (all gates), type-check, lint -- clean

  • ui-tui: npm run gen:rpc, npm run gen:i18n, vitest run, type-check, lint -- clean

  • mkdocs build --strict -- clean

  • The picker row was checked on the built page's offline library (?stub=1) in light, dark and zh; the screenshots were shown to the owner before this PR was opened

  • Relevant tests pass locally

  • Relevant lint / type checks pass locally

  • User-facing docs or screenshots are updated when needed

Risk

  • Security impact considered -- the method still writes one word (or null) to a session's own metadata; the word is now checked against the provider's answer rather than a tuple, and a provider that cannot answer falls back to the four
  • Backward compatibility considered -- the four words every wire takes are unchanged; a page or TUI that never saw the new rungs shows a word it does not know as the server spelt it; the global key accepts what it accepted; a record carrying xhigh/max is read as no pick by a build without this change
  • Rollback path is clear for risky changes -- revert the PR; the record's key is unchanged, and the previous reader ignores the two words

Related Issues

Follows #1113.

Handsome-wzw and others added 6 commits October 26, 2026 15:56
…session.set_effort)

One conversation can now ask for more or less thinking than the configured
default without moving that default. The pick rides the session's metadata
beside `model` (`raven.agent.session_effort`), so it outlives the gateway and
a resumed conversation runs at what it was left at; the turn entrance hands
it to `_run_agent_loop`, which ranks it over the mode's effort and the
configured `agents.defaults.reasoningEffort`, under a hook's rollback
override. Raven's own calls only: sub-agents keep the configured default.

Surfaces: `session.set_effort` (report, set or clear; every answer names what
the default is on this install and the words), `session.info` carries
`reasoning_effort` for the status bar, the WebUI's model picker gains an
effort row under the tier row, and the TUI gains `/effort`.

The settings page drew an unset `agents.defaults.reasoningEffort` as Low; the
unset state is now its own rung, Provider default, and the key accepts null
so that rung clears it. The using-raven guide documents both levels.

Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
… left

A switch asks for the conversation being opened before the page's current
session moves over to it, and the effort read built its request from "the
current session": opening B from A asked for A's effort and painted it on
B -- and a pick of that very rung on B was taken as already in force. The
read now names the conversation and the switch it belongs to, the way the
permission-mode read does, and the source drops an answer whose switch has
been overtaken rather than painting a view the reader has left.

Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
…rovider takes them

The words a session may pick now come from the provider of the session's
model rather than from one global tuple: LLMProvider.reasoning_efforts
answers the four every wire takes, the Anthropic Messages adapter answers
its _ADAPTIVE_EFFORTS table (xhigh and max over high), and the lazy,
per-model, resolving and rotor wrappers forward it the way they forward
reasoning_wire_keys. session.set_effort answers options from the session's
own binding and refuses a word the provider does not take, naming the model
and the words it takes. The console checker for agents.defaults.reasoningEffort
stays at the four on purpose: that key reaches every model call on every
vendor and every sub-agent.

The record may carry any rung this raven knows (REASONING_EFFORT_RUNGS, the
retry descent's ladder read upward), because the model can move after the
pick: the turn asks its provider again (session_effort.fit) and runs a pick
the new wire does not take at the highest rung it does take, logged, rather
than at a request the wire would refuse; a mode's effort goes out as named.

Surfaces: the picker row names the two rungs (en + zh), wraps whole words
when seven do not fit one line, re-reads its words after a model switch and
draws a pick the words no longer carry after them, ticked; the TUI's /effort
help and usage list the six words; the offline library offers six for its
Claude; the using-raven guide (en + zh), CHANGELOG and CONTEXT.md say the
above; openrpc.json describes effort and options as the model's words, and
both generated contracts are regenerated.

Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
…nto feat/effort_xhigh_max

# Conflicts:
#	ui-web/src/features/model/source.test.ts
@Handsome-wzw
Handsome-wzw requested a review from LivXue as a code owner October 27, 2026 03:50
@Handsome-wzw
Handsome-wzw requested a review from 0xKT October 27, 2026 03:50
@Handsome-wzw

Copy link
Copy Markdown
Contributor Author

Verification on the pushed head (merged with origin/main and with #1113's current head 516c7e7d4):

  • full pytest tests (merged tree, -n auto): 35982 passed, 3 failed, 255 skipped, 2 xfailed, 7m32s. The 3 failures are this Mac's known baseline, unrelated to the change: test_rpc_files::test_a_host_without_libreoffice_says_so, test_simulation_scenario::test_a_fresh_trial_refreshes_the_subagent_homes_before_it_runs, test_simulation_suite::test_a_stopped_run_is_marked_in_its_record_and_finished_with_its_evidence.
  • scripts/coverage_gate.py diff --base-ref origin/main: 99.26% (134/135 executable changed lines). The one uncovered line is feat(agent): per-conversation reasoning effort (picker row, /effort, session.set_effort) #1113's _set_effort dispatcher wrapper in raven/rpc/methods/session.py, which the diff against main still counts until feat(agent): per-conversation reasoning effort (picker row, /effort, session.set_effort) #1113 merges.
  • related set (test_session_effort, test_rpc_session, test_agent_loop_usage_sink, test_agent_loop_session_effort, test_agent_loop_empty_recovery, test_provider_protocol, test_rpc_settings, test_rpc_console, test_import_cycle_budget, test_rpc_schema_match, test_rpc_registration, test_rpc_session_init_bundle): pass. ruff check / ruff format --check / ty check on the touched modules, lint-imports: clean; the import-cycle budget is unchanged (providers/base now imports config/schema, which reaches nothing back).
  • ui-web: npm run gen (contract regenerated), vitest run 258 files / 4419 tests, type-check clean, lint 0 errors (the 4 warnings main has), npm run build + build.py (boot snapshots match), check-page / check-css / check-class-namespace OK.
  • ui-tui: npm run gen:rpc, npm run gen:i18n, vitest run 146 files / 2286 tests, type-check, lint: clean. (One timing case in modelPicker.test.tsx failed once under a loaded first full run, passed alone and did not recur on the merged tree.)
  • mkdocs build --strict: clean.
  • Range gates run locally as CI runs them (check_source_language, check_large_files, check_commit_messages on origin/main..HEAD, check_pr_title, check_pr_body): pass.
  • The picker row was checked on the built page's offline library (?stub=1): en light / dark (seven rungs wrap as whole words, 5 + 2) and zh (seven rungs on one line); the screenshots were shown to the owner before this PR was opened.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No blockers; this can merge as far as I am concerned.

Reviewed github/main...HEAD at 35489d530c28, including the repository rules and canonical Session Reasoning Effort term, the full diff, provider and loop callers, RPC/schema/generated-client boundaries, WebUI/TUI state flows, relevant history, backward compatibility with older providers/gateways, and the test changes. I specifically tried to refute the model-switch fitting behavior, provider-wrapper routing, draft staging, stale async reads, persisted session precedence, and the claim that tests were not weakened; I found no concrete failure.

Verification:

  • uv run pytest tests/test_session_effort.py tests/test_provider_protocol.py tests/test_rpc_session.py tests/test_agent_loop_empty_recovery.py tests/test_agent_loop_usage_sink.py tests/test_rpc_session_init_bundle.py tests/test_rpc_settings.py -q: 595 passed.
  • uv run pytest tests/test_rpc_schema_match.py tests/test_l4_entrances.py tests/test_source_language_check.py -q: 559 passed.
  • WebUI focused Vitest run: 221 passed; TUI focused Vitest run: 12 passed.
  • WebUI generated RPC check and type check passed. TUI generated RPC/i18n checks and type check passed.
  • Source-language, large-file, diff-whitespace, and generated-file cleanliness checks passed.

@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member

Windows compatibility review — PR #1123 @ 35489d530c28bb4ebf6073cda0cb6d6d6610ff1f

Scope: full base 4718421324 → this head (55 files). The PR is stacked on #1113; its effort core is identical to the 516c7e7d head reviewed there. Its own delta on top is 33 files (+688/−60): reasoning_efforts() capability reporting with provider forwarding (base, anthropic_messages, endpoint_rotor, lazy, per_model_provider, resolving_provider), the xhigh/max rungs in the session/RPC validation and pickers, docs, and tests.

Result: no Windows-specific issue.

Verification (native Windows 11, CPython 3.12.13, isolated worktree D:\tmp\rv-1123 at this head; scratch HOME/USERPROFILE, PYTHONUTF8=1; node_modules borrowed read-only from the main checkout):

vitest run src/state/effort.test.ts src/features/model/source.test.ts
→ 2 files, 57 passed

pytest tests/test_session_effort.py tests/test_rpc_session.py \
       tests/test_agent_loop_usage_sink.py tests/test_agent_loop_empty_recovery.py \
       tests/test_provider_protocol.py -q
→ 409 passed in 19.21s

Limitations: TUI tests not run (harness unavailable in this checkout); no live model provider was called, so the xhigh/max wire behaviour is exercised through the provider-protocol tests only.

@0xKT

0xKT commented Oct 27, 2026

Copy link
Copy Markdown
Member

Merge conflict: @Handsome-wzw this PR no longer merges cleanly into main.

Measured just now with git merge-tree --write-tree of main 26352da0 and this head 35489d53. Main moved with #1110 (Agent Plugins loader), #1064 (conditional branches) and #1066 (DAG file references), each of which changed CHANGELOG.md. Conflicting files: CHANGELOG.md.

After a rebase onto current main I re-check what moved before the grade comes back.

@gloryfromca

Copy link
Copy Markdown
Member

Blocking: resolve the CHANGELOG.md conflict against current GitHub main before merge.

Confirmed independently at head 35489d530c28 against GitHub main 26352da09a33: git merge-tree --write-tree HEAD github/main exits 1 with a content conflict in CHANGELOG.md, and GitHub reports mergeable: false / mergeable_state: dirty. The branch code is otherwise unchanged; uv run pytest tests/test_session_effort.py -q passes (9 passed).

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No blockers; this can merge as far as I am concerned.

Reviewed the delta from the previously reviewed head 35489d530c28 to d2e73da75f01. The new commit merges current GitHub main; the only hand-resolved conflict was CHANGELOG.md, and the resolution preserves both effort entries and the upstream entries. The PR diff against its new merge base remains the expected 55-file effort change, git merge-tree --write-tree HEAD github/main succeeds, and no effort implementation or test was weakened by the refresh. I rechecked the repository/domain rules, merge history and resolution, overlapping runtime/RPC/provider/frontend callers, generated contracts, backward-compatible surfaces, architecture checks, and test changes.

Verification on this head:

  • Focused Python runtime/RPC/provider/schema/layer/source-language suite: 1,169 passed.
  • Focused WebUI suite: 221 passed; generated RPC check and type check passed.
  • Focused TUI suite: 12 passed; generated RPC/i18n checks and type check passed.
  • PR diff whitespace and merge-tree checks passed.

@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member

Windows compatibility re-review — PR #1123 @ d2e73da75f01e9ed92cc08b68f1b2c37e2c190eb

Scope: the head moved from the previously reviewed 35489d53. Against the new main tip 26352da0, the PR's own effort/provider code is byte-identical to the reviewed head — raven/agent/session_effort.py, raven/config/schema.py and the six provider files total the same +188 lines; the rpc/methods/session.py / rpc/models.py changes in the raw delta are main's #1119 merge, not this PR.

Result: no Windows-specific issue; the previous conclusion holds.

Verification (native Windows 11, isolated worktree D:\tmp\rv-1123-n2 at this head; scratch HOME/USERPROFILE, PYTHONUTF8=1; node_modules borrowed read-only from the main checkout):

vitest run src/state/effort.test.ts src/features/model/source.test.ts
→ 2 files, 57 passed

pytest tests/test_session_effort.py tests/test_rpc_session.py \
       tests/test_agent_loop_usage_sink.py tests/test_agent_loop_empty_recovery.py \
       tests/test_provider_protocol.py -q
→ 424 passed in 14.37s

The provider additions remain capability metadata only (reasoning_efforts forwarding), with no HTTP/TLS/proxy, path, subprocess, encoding, or platform code.

Limitations: TUI tests not run; no live model provider was called.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Blocking: carried from #1113. This PR targets main and contains #1113's earlier head 516c7e7d (merged in through 35489d5), so merging it as it stands merges #1113's open defect too: the Provider default rung clears agents.defaults.reasoningEffort, but a running gateway keeps sending the effort it booted with while session.info / session.set_effort report the clear (thread on #1113, anchored to raven/agent/loop/turn_path.py; the judge reproduced it there).

This PR's own commit a23029c0 reads fine on its own:

  • LLMProvider.reasoning_efforts defaults to the four words; anthropic_messages answers its _ADAPTIVE_EFFORTS keys (low to max).
  • The lazy, per-model, resolving and rotor wrappers forward it the way they forward reasoning_wire_keys.
  • _effort_words falls back to the four when the provider cannot answer.
  • session_effort.fit runs a pick the new wire does not take at the highest rung it does take, and logs it. effective_model is bound before the call at turn_path.py:1003.
  • The console key stays at the four on purpose.

This clears once #1113's fix lands and this branch is rebased onto it, so its diff against main carries the fixed code. Read only; local tests not run.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Blocking: merge the #1113 clear fix and resolve the current CHANGELOG.md conflict before merge.

Confirmed on this head: gen_overrides still omits reasoning_effort when both the session pick/mode and live configured default are null, so the provider can reuse its frozen boot-time word while the RPC surfaces report the provider default. The current #1113 branch fixes this in 5057b49f by resolving the effort once and always sending None explicitly; that fix is absent here. The affected existing suite passes (uv run pytest tests/test_agent_loop_usage_sink.py tests/test_rpc_session.py tests/test_rpc_settings.py -q: 407 passed), consistent with the transition lacking coverage on this head. I am confirming the facts, not re-grading or resolving the blocker opened here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Merged rather than rebased (branches here merge, never rebase): 754ff3160 brings in #1113's head 01f245518, which holds the clear fix 5057b49f0, so this PR's diff against main now carries the fixed turn -- session_reasoning_effort ranks pick > mode's word > configured default and the call sends it every time, None included. The pick fitting from a23029c0 sits in front of it: turn_effort = self.session_reasoning_effort(session_key, _fit_reasoning_effort(...)) in raven/agent/loop/turn_path.py. Head c325201e2; the verification comment on the PR has the local counts.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No blockers; this can merge as far as I am concerned.

Confirmed on c325201e2d6a: #1113 fix 5057b49f0 is now in the ancestry, the conflict resolution fits the session pick before session_reasoning_effort ranks it, and gen_overrides always carries the resulting value, including explicit None. The new clear-transition coverage passes. Current GitHub main is also in the ancestry and git merge-tree --write-tree HEAD github/main succeeds. My prior blocker is withdrawn; I am leaving resolution of this thread to its opener.

Handsome-wzw and others added 2 commits October 27, 2026 16:27
…xt turn

Picking Provider default clears agents.defaults.reasoningEffort, and
session.info / session.set_effort reported the clear, but a gateway that
booted while the key held a word kept calling at that word: the turn left
reasoning_effort out of the call when the live reader answered None, and
the provider filled the missing argument from its own copy of the key,
frozen at construction (ResolvingProvider). The display and the wire
disagreed in exactly the way the per-conversation effort set out to end.

The turn now sends the effort in force on every call, None included: an
explicit None reaches the provider as None (its own default, nothing on the
wire) instead of the boot copy, so a clear lands on the next turn the way a
word change already did. The exhaustion wrap-up and the watch-work
judgement send it the same way.

The ranking has one home, session_effort.in_force (pick > mode's word >
configured default, None one answer with one meaning), which the turn
runs at through session_reasoning_effort on the loop and the RPC reports
from, the way session_tier is shared; the two used to spell it out apart
and to read an absent word differently.

Tests: a real provider booted at high with the live key cleared records
None on the next turn (low as the control), the three cases that pinned
"the key is left out" now pin "the key is sent as None", and in_force has
its own unit tests. CONTEXT and the CHANGELOG entry say the rule.

Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
@0xKT

0xKT commented Oct 27, 2026

Copy link
Copy Markdown
Member

Merge conflict: @Handsome-wzw this PR no longer merges cleanly into main.

Measured just now with git merge-tree --write-tree of main 984d47d4 and this head d2e73da7. Main moved with #1124 (add buttons on the skills and plugins pages that lead into the chat), which changed CHANGELOG.md. Conflicting files: CHANGELOG.md.

After a rebase onto current main I re-check what moved before the grade comes back.

@gloryfromca

Copy link
Copy Markdown
Member

Blocking: merge the #1113 clear fix and resolve the current CHANGELOG.md conflict before merge.

The second condition also reproduces independently: after fetching GitHub main at 984d47d4b74c, git merge-tree --write-tree HEAD github/main exits 1 with a content conflict in CHANGELOG.md, and GitHub reports mergeable: false / mergeable_state: dirty. The branch remains at d2e73da75f01.

…nto feat/effort_xhigh_max

# Conflicts:
#	CONTEXT.md
#	raven/agent/loop/turn_path.py
#	raven/rpc/methods/session.py
@Handsome-wzw

Copy link
Copy Markdown
Contributor Author

Merged on top of the previous head d2e73da75, no rebase and no force-push:

git diff origin/feat/session_reasoning_effort -- CHANGELOG.md is this PR's bullet alone; the Added order stays this PR's bullet, then #1113's, then main's.

Local checks on c325201e2:

  • full pytest tests (-n auto): 36319 passed, 3 failed, 258 skipped, 2 xfailed, 7m32s -- run on the tree one blank line short of this head (ruff format wanted one more between two functions in rpc/methods/session.py; folded into 47f5d64e7, with the related group and ruff rerun on the final tree). The 3 are this Mac's known baseline, failing the same way on main: test_rpc_files::test_a_host_without_libreoffice_says_so, test_simulation_scenario::test_a_fresh_trial_refreshes_the_subagent_homes_before_it_runs, test_simulation_suite::test_a_stopped_run_is_marked_in_its_record_and_finished_with_its_evidence
  • related group (test_session_effort, test_agent_loop_session_effort, test_agent_loop_iteration_hooks, test_watch_work, test_agent_loop_empty_recovery, test_agent_loop_usage_sink, test_provider_protocol, test_rpc_session, test_import_cycle_budget): 533 passed (325 of them, the five session/effort files, rerun on the final head); ruff check / ruff format --check clean; lint-imports 10 kept, 0 broken
  • ui-web: gen:check in sync, tsc --noEmit clean, eslint 0 errors / 4 warnings (as on main), vitest run 261 files / 4452 tests passed
  • ui-tui: lint:rpc / lint:i18n in sync, tsc --noEmit clean, vitest run 146 files / 2286 tests passed
  • check_commit_messages / check_source_language / check_large_files / commitlint over origin/main..HEAD: all pass

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No blockers; this can merge as far as I am concerned.

Reviewed the delta from d2e73da75f01 to c325201e2d6a, including the repository and domain rules, merge history and three hand-resolved overlaps, affected loop/RPC/provider callers, backward-compatible None semantics, architecture boundaries, and whether tests were weakened. The prior clear defect is fixed: provider-aware fitting feeds the shared in-force ranking, and every model call receives the resolved effort, including explicit None. Current GitHub main is in the ancestry and the merge-tree check is clean. I found no new concrete failure.

Verification on this head:

  • Focused session-effort, loop, provider, RPC, and import-boundary suite: 533 passed.
  • WebUI generated RPC check and type check passed.
  • TUI generated RPC/i18n checks and type check passed.
  • Source-language, large-file, diff-whitespace, and merge-tree checks passed.

@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member

Windows compatibility re-review — PR #1123 @ c325201e2d6a9d8bb0fac5ea8541dc4345ca4f7d

Scope: the head moved from the previously reviewed d2e73da7. The only change in the PR's own files is the base PR's session_effort.in_force() helper (+23 lines, stacked from #1113); the reasoning_efforts() capability additions in raven/providers/** and the RPC/UI effort rows are unchanged. The rest of the raw delta is main's merges.

Result: no Windows-specific issue; the previous conclusion holds.

Verification (native Windows 11, isolated worktree D:\tmp\rv-1123-n3 at this head; scratch HOME/USERPROFILE, PYTHONUTF8=1; node_modules borrowed read-only from the main checkout):

vitest run src/state/effort.test.ts src/features/model/source.test.ts
→ 2 files, 57 passed

pytest tests/test_session_effort.py tests/test_rpc_session.py \
       tests/test_agent_loop_usage_sink.py tests/test_agent_loop_empty_recovery.py \
       tests/test_provider_protocol.py -q
→ 426 passed in 19.03s

The provider additions remain capability metadata (reasoning_efforts forwarding); no HTTP/TLS/proxy, path, subprocess, encoding, or platform code.

Limitations: TUI tests not run; no live model provider was called.

Handsome-wzw and others added 3 commits October 27, 2026 21:19
…ords

Inside a direct chat with a sub-agent instance, /effort sent the main
conversation's session_key and then said "this conversation" in the
instance's pane: the main record moved while the reader was told the
instance's had. The pick is the main conversation's and an instance has
none of its own to set from here, so the command is refused there, naming
the instance and the way back, the way /instance does. The reset words are
/mode's RESET_WORDS now rather than a second copy of the same three.

Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
…omotion's ticket

A draft's effort pick was staged before the session.set_effort read that
answers the default and the words, and left staged when that read failed:
the toast said the pick was not made and the old rung was repainted, but
the first send's applyStagedEffort ran the turn at it. The pick is still
staged first, so a send during the round trip carries it, and a failed
read puts back the last pick whose read landed -- not merely the value
staged before the failing call, which is another in-flight pick when two
went out and both failed.

The re-read after the promotion wrote the staged effort took the view's
ticket after the awaited write, so a reader who opened another
conversation while the write was in flight got the minted session's rung
painted over that conversation's own read. The promotion's ticket now
rides into applyStagedEffort the way it rides into applyStagedModel, and
the source drops the late answer.

The tier row's tooltip (gui.tier.scope) said reasoning depth follows the
tier, one row above a row titled with the same words; the shipped tiers
leave the effort alone, so the tooltip now names sub-agents only. The TUI
catalogue is regenerated from it.

Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
…arry the pick on a fork

The exhaustion wrap-up and the watch-work judgement forward the effort in
force, explicit None included, but nothing failed when either call site
went back to the policy's word or the wrap-up helper left the key out on
None. Two tests now drive each side call to a provider booted at high:
the configured default where the policy names none, the session's own
pick, and a cleared key that must arrive as None rather than be filled
from the boot copy. The watch-work case is pinned at the provider, through
chat_stream, with the spawn roster naming an on-call agent so the look
earns the judgement.

The agent's raven_config door kept its own copy of the effort words and
refused null for agents.defaults.reasoningEffort while the settings page
accepted it. The setting reads REASONING_EFFORTS and is nullable, so the
words have one owner and the agent can clear the key the way the page
does.

A fork carried the parent's model but dropped its effort pick, so a forked
conversation ran at the default until resumed; FORK_CARRIES names what a
fork carries, with the pick beside the model. session_effort.write's
docstring promised a "pending" report that session.set_effort never makes;
it now says what the answer is for. CONTEXT.md, the using-raven guide and
the CHANGELOG entry carry the three user-visible facts.

Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
…nto feat/effort_xhigh_max

# Conflicts:
#	CONTEXT.md
#	docs-site/docs/using-raven.md
#	docs-site/docs/using-raven.zh.md
#	ui-tui/src/app/slash/commands/session.ts
#	ui-web/src/features/model/source.test.ts
@Handsome-wzw

Copy link
Copy Markdown
Contributor Author

Merged #1113's current head 1a0e9c2e6 on top of c325201e2 (merge f050cb46d; no rebase, no force-push). That brings in its three latest commits -- 251cdb551 (/effort refused in a direct chat, /mode's reset words), bffb9803f (a refused draft pick put back; applyStagedEffort re-reads under the promotion's ticket), 1a0e9c2e6 (the side calls' effort pinned, raven_config clears the key, a fork carries the pick). origin/main has not moved since 06509f8e4.

Five conflicts, none in Python; each was the two branches adding a sentence or a fake at the same place, kept together:

git diff origin/feat/session_reasoning_effort -- CHANGELOG.md is still this PR's bullet alone. Generated files (ui-web gen:check, ui-tui lint:rpc / lint:i18n) are in sync.

Local checks on f050cb46d:

  • full pytest tests (-n auto): 36334 passed, 3 failed, 258 skipped, 2 xfailed, 6m22s; the 3 are this Mac's known baseline, failing the same way on main: test_rpc_files::test_a_host_without_libreoffice_says_so, test_simulation_scenario::test_a_fresh_trial_refreshes_the_subagent_homes_before_it_runs, test_simulation_suite::test_a_stopped_run_is_marked_in_its_record_and_finished_with_its_evidence
  • related group (session effort, loop session effort, rpc session, config self_surface, raven_config tool, session manager, usage sink, empty recovery, provider protocol, import cycle budget, iteration hooks, watch work): 957 passed; ruff check / ruff format --check clean; lint-imports 10 kept, 0 broken; mkdocs build --strict clean
  • ui-web: tsc --noEmit clean, eslint 0 errors / 4 warnings (as on main), vitest run 261 files / 4457 tests passed (source.test.ts + effort.test.ts alone: 62)
  • ui-tui: tsc --noEmit clean, eslint clean, vitest run 146 files / 2289 tests: 2288 passed and one load-timing case, subagentsHub.test.tsx > a rename carries the prior probe status forward under the new name, which failed once under the concurrent Python run and passes 3/3 alone (no file it touches changed on this branch)
  • check_commit_messages / check_source_language / check_large_files / commitlint over origin/main..HEAD: all pass

LivXue's thread on #1113 about the words being the model's is left as it is; nothing here answers it.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No blockers; this can merge as far as I am concerned.

Reviewed the delta from c325201, including all five conflict resolutions and the three newly merged #1113 fixes. I checked the repository rules and domain terms; the resulting diff and affected callers; the merge history and current main; backward compatibility; test changes for weakening; and the provider/session/UI architecture boundaries. The resolutions preserve the provider-specific xhigh/max behavior while correctly integrating draft recovery, promotion-ticket guarding, side-call effort pinning, config clearing, fork inheritance, and the TUI direct-chat guard.

Verification on this head: 953 affected Python tests passed; 133 focused Web tests passed; 12 focused TUI tests passed; Web and TUI type checks passed; generated Web RPC plus TUI RPC/i18n checks passed; git diff --check passed; current GitHub main is in the branch ancestry and git merge-tree --write-tree HEAD github/main succeeds. I found no new defect, compatibility break, weakened test, or unresolved conflict introduced by this merge.

The only open review thread was opened by another reviewer; its defect is fixed and my prior reply already withdrew my supporting objection, so I did not resolve someone else's thread.

@LivXue

LivXue commented Oct 27, 2026

Copy link
Copy Markdown
Member

Windows compatibility re-review — PR #1123 @ f050cb46d1d585e2c96b90c62f1dc303cea4874b

Scope: the head moved from the previously reviewed c325201e. The delta is the stacked #1113 changes (effort source/runtime keyed to the opened conversation, session fork carrying reasoning_effort, self-surface nullable effort) plus main's merges; #1123's own additions — the reasoning_efforts() capability forwarding in raven/providers/** and the effort rows — are unchanged.

Result: no Windows-specific issue; the previous conclusion holds. The delta is browser/TUI state and config-catalogue logic, with no path, subprocess, encoding, or platform primitive.

Verification (native Windows 11, isolated worktree D:\tmp\rv-1123-n4 at this head; scratch HOME/USERPROFILE, PYTHONUTF8=1; node_modules borrowed read-only from the main checkout):

vitest run src/state/effort.test.ts src/features/model/source.test.ts
→ 2 files, 62 passed

pytest tests/test_session_effort.py tests/test_rpc_session.py \
       tests/test_agent_loop_usage_sink.py tests/test_agent_loop_empty_recovery.py \
       tests/test_provider_protocol.py tests/test_agent_loop_session_effort.py -q
→ 441 passed in 25.12s

Limitations: TUI tests not run; no live model provider was called.

This branch has not been deployed

No deployments
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.

4 participants