feat(agents): pin explicit reasoning effort on every agent and workflow call

Effort joins model as a mandatory pin: an omitted field inherits the
session effort, coupling every dispatch's thinking budget to whatever
the user happens to be chatting at (often xhigh) — the same
session-state coupling the model pin removes. The assignment follows
the model split:

- xhigh on every opus agent (judgement roles are the pipeline's
  quality floor and must not degrade with the session);
- high on every sonnet agent (tightly-scoped plan execution gains
  little from xhigh but pays its latency per dispatch, and these are
  the per-task in-loop roles — wall-clock is the efficiency metric;
  not lower than high, since re-loops cost more than saved thinking);
- medium inline in the workflow scripts for schema-bound
  extraction/verification stages that author no code (preflight,
  plan-extract, mini-verify, tree-check, finalize, build/suite
  verify).

Workflow agent() calls pass effort explicitly on every call — whether
frontmatter effort propagates through an agentType dispatch is
undocumented, so the scripts do not rely on it. Policy documented in
docs/agent-template.md § effort, mirroring § model.
This commit is contained in:
2026-07-02 15:43:36 +02:00
parent 52c87d19ce
commit edbbb68f97
18 changed files with 65 additions and 13 deletions
+5 -2
View File
@@ -43,6 +43,9 @@
// session-model inherit (which could route to an unintended tier, e.g. fable —
// banned for all plugin agents and workflows). Both phases here are mechanical
// (compiler-enumerated propagation, build/suite re-run), so both run sonnet.
// Effort policy mirrors it: every call pins an explicit effort — the edit
// (real code work) runs high, the build/suite verify (schema-bound check)
// runs medium. See docs/agent-template.md § effort.
//
// Carrier — Workflow `args`:
// edit_description: what type/signature change to make
@@ -125,7 +128,7 @@ const edit = await agent(
'Then run the project build and report: is the build clean, does any hole need a decision (with detail + bounce_to), ' +
'how many sites were touched, and — checked against `git status --porcelain` / `git diff HEAD`, NOT from memory — ' +
'whether the working tree actually changed (applied_changes).',
{ agentType: 'implementer', model: 'sonnet', label: 'edit+propagate', phase: 'Edit + propagate', schema: EDIT_SCHEMA },
{ agentType: 'implementer', model: 'sonnet', effort: 'high', label: 'edit+propagate', phase: 'Edit + propagate', schema: EDIT_SCHEMA },
)
if (!edit) return { status: 'BLOCKED', reason: 'edit agent did not return' }
if (edit.hole_needs_decision) {
@@ -167,7 +170,7 @@ const verify = await agent(
'every test passes and NO test was added, removed, or weakened versus the pre-edit baseline (compare `git diff ' +
'HEAD` for test-file changes). Also report working_tree_dirty — whether `git status --porcelain` / `git diff HEAD` ' +
'shows ANY change at all (a clean tree means no edit landed). Do NOT edit anything; do NOT commit.',
{ model: 'sonnet', label: 'verify(build+suite)', phase: 'Verify', schema: VERIFY_SCHEMA },
{ model: 'sonnet', effort: 'medium', label: 'verify(build+suite)', phase: 'Verify', schema: VERIFY_SCHEMA },
)
// ---- Phase 3 — verdict --------------------------------------------------