Skip to content

Apply agent profile reasoning/temperature frontmatter (#828) - #829

Merged
yogthos merged 1 commit into
dirge-code:mainfrom
chrismurrph:fix/828-profile-reasoning
Aug 30, 2026
Merged

Apply agent profile reasoning/temperature frontmatter (#828)#829
yogthos merged 1 commit into
dirge-code:mainfrom
chrismurrph:fix/828-profile-reasoning

Conversation

@chrismurrph

Copy link
Copy Markdown
Contributor

Fixes #828. Implements option 1 from the issue, as requested.

What was wired

Both keys, by two mechanisms — the codebase offers a different hook for each.

reasoning/agent <name> parses def.reasoning with the same parser /effort uses and writes it to session.effort_override, the same field /effort writes, so the existing re-application on rebuild makes it stick. The pre-profile override is captured in a new effort_before_agent: Option<Option<ThinkingLevel>> on the context — the effort sibling of the existing route_before_agent — and /agent off takes and restores it. The switch summary line gains · effort <level>.

temperature — there is no runtime setter on AnyAgent, so build_agent_inner now consults the agent layer ahead of cli.resolve_temperature(cfg):

let profile_temp = context.agent_layer.as_ref().and_then(|d| d.temperature);
if let Some(temp) = profile_temp.or_else(|| cli.resolve_temperature(cfg)) {

/agent rebuilds the agent and /agent off clears the layer before rebuilding, so apply and restore both fall out with no capture state, and a profile omitting the key falls through untouched. The existing clamp and warn are unchanged.

Decisions

  • Precedence vs /effort: the profile wins at activation (it displaces a live /effort max); a later /effort overrides it like any current level.
  • /agent off restores the pre-profile value, discarding an /effort issued while the profile was active — the same symmetry route_before_agent already has with a mid-profile /model.
  • Capture guard is effort_before_agent.is_none(), not the agent layer, so an A-without-key → B-with-key hop captures at B, and A-with → B-with keeps the pre-agent capture.
  • None means leave alone. A profile omitting reasoning neither applies nor captures; omitting temperature falls through to CLI/config.
  • Invalid values fail soft — one warning worded like /effort's, no capture, no override change, and the switch still proceeds.
  • Applied even when the model route is refused, since the profile stays active on refusal today; its effort layer now does too.
  • Subagent path deliberately left excluded. It is a separate one-shot/filtered-loop build that does not share this mechanism. docs/agents.md is updated to say the main loop applies both and that the subagent exclusion stands.

Docs

The key table entries for reasoning and temperature are rewritten — reasoning previously advertised only low/medium/high, where the parser takes all seven /effort levels — and the subagent-path sentence now states what the main loop does.

Tests

9 new, inline in switch.rs: applied-and-captured; profile beats a live override at activation; restore returns the pre-profile value; restore when there was none before; restore discards a mid-profile change; profile hop keeps the pre-agent capture; restore without a capture is a no-op; invalid value changes nothing; all seven levels parse.

Full suite 5432 passed, 0 failed, 1 ignored (baseline 5423 + these 9). clippy --all-targets -- -D warnings clean, cargo fmt --check clean.

Verified end to end

Driven in a real TUI with RUST_LOG=dirge::wire=info DIRGE_DUMP_REQUESTS=1 and a probe profile (model: low, reasoning: off):

model="claude-sonnet-5"    reasoning=true     turn 1, default provider
/agent probe828            → active agent: probe828 · model claude-haiku-4-5 · effort off
model="claude-haiku-4-5"   reasoning=false    turn 2  ← was true before this change
/agent off                 → agent deactivated · model restored to claude-sonnet-5
model="claude-sonnet-5"    reasoning=true     turn 3  ← restore

Disclosures

  • The temperature leg has no behavioural test. The wire dump does not carry temperature and rig's builder exposes no getter, so it is verified by code path and compilation only. If you would rather see it proven before merging, say so and I will find a way.
  • Built and tested with --no-default-features --features no-plugin — the plugin feature needs a janet toolchain unavailable on this host (Build fails on Linux #712). CI covers it.
  • Two adjacent things noticed and left alone: the docs/agents.md key table omits subagent_allow and subagent_timeout_secs, both parsed in agent_defs.rs; and /effort with no args labels a profile-applied level "(session override)", which is now mildly misleading since a profile writes that same field.

)

The reasoning and temperature frontmatter keys were parsed into AgentDef
but never read. Wire them into the main loop:

- /agent <name> applies the profile's reasoning via session.effort_override
  (the same mechanism /effort uses, so rebuilds keep it sticky), capturing
  the pre-profile override in ContextFiles.effort_before_agent — the effort
  sibling of route_before_agent. /agent off restores it.
- The profile wins over a live /effort override at activation; a later
  /effort overrides it; /agent off restores the pre-profile value, mirroring
  how the model restore discards a mid-profile /model.
- An unrecognised reasoning value warns and leaves effort untouched; the
  switch proceeds (fail-soft, matching /effort's unknown-level handling).
- temperature is consulted from the active agent layer at agent build time
  (profile > CLI > config), so /agent's rebuild applies it and /agent off's
  rebuild falls back automatically. Same clamp/warn as before.
- Subagent path unchanged (still model + prompt only); docs updated: the
  key table now lists all seven /effort levels and the new semantics.

Verified end-to-end with the wire dump: turn under the profile flips to
model=claude-haiku-4-5 reasoning=false, /agent off returns to
claude-sonnet-5 reasoning=true.
@yogthos
yogthos merged commit ccfef8e into dirge-code:main Aug 30, 2026
15 checks passed
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.

Agent profile reasoning and temperature frontmatter keys are parsed but never applied (main loop or subagent)

2 participants