Skip to content

feat(templater): set each agent's effort by how often it fires, not by role - #94

Merged
protonspy merged 1 commit into
mainfrom
feat/agent-effort-ladder
Jul 28, 2026
Merged

feat(templater): set each agent's effort by how often it fires, not by role#94
protonspy merged 1 commit into
mainfrom
feat/agent-effort-ladder

Conversation

@protonspy

@protonspy protonspy commented Jul 28, 2026

Copy link
Copy Markdown
Owner

The dial

Reasoning effort was set per agent by what the agent is. It should be set by how often it fires, weighed against what being shallow costs there. Those pull in opposite directions, and the ladder below is where they balance.

agent dispatches per feat effort why
implementer ~7 high (unchanged) fires most, but it writes the code — a shallow implementation is the expensive kind
spec-author 3 medium ← was high authors a scaffolded artifact whose shape the template already fixes
code-reviewer 1–2 high (unchanged) pure judgment; lowering it saves almost nothing
security-reviewer 0–1 high (unchanged) rare, and the cost of a miss is asymmetric
quality-gate 1 low ← was medium runs commands and relays their output

Evidence

From a measured run's ledger (one feat, panel-shell):

  • $3.15 of $4.69 was sonnet, $1.54 opus. The argument that kept spec-author at high was that a shallow draft pushes real authoring back onto the opus reviewer as fix-lists, defeating the cost split — but the split was already lost at the sonnet end, three dispatches per feat over a largely pre-filled form. That reasoning is not deleted; it is rewritten in the test comment with the measurement that moved it, and with the signal to reverse it (fix-lists growing).
  • The same feat arrived "implemented" with 691 green tests and a drawer that never collapsed at any width — ARIA and state plumbed, layout fixed at two columns, data-drawer="open" read by no selector. The feat-exit review is what found it. That is what high effort buys on a reviewer, and why the two reviewers do not move.

quality-gate needs no measurement: its own prompt says "You decide nothing about the code — you execute the declared checks and relay their real output."

Also: the fix loop is bounded

spec-author step 4 said "re-validate until it returns 0" — an open loop. The finding it cannot resolve on the second pass (usually a tasks.md shape that does not match the spec's development_flow) is not one it resolves on the fourth either, and every pass re-reads a spec that is commonly 800+ lines to retry a fix it already tried. Two rounds, then report what is left quoting the finding verbatim and what was tried — the orchestrator decides in one turn what the loop was spending many on.

Verification

  • make check green.
  • New TestAgentEffortLadder pins all five values in one place, with the reasoning per tier in its comment and an explicit instruction: change a value here only together with the reasoning that moved it.
  • A new assertion forbids the string re-validate until it returns 0, so the open loop cannot come back by edit.
  • Existing TestSpecAuthorAgentShipped / …EncodesDiscipline still hold.

Installed workspaces pick this up via csdd update (a hand-edited agent is preserved as a numbered .old backup, as always).

🤖 Generated with Claude Code

https://claude.ai/code/session_01ARBSaXgJ7ssW1hvpy6r64y

Summary by CodeRabbit

  • New Features

    • Added clearer validation guidance for authored specifications, including a maximum of two fix-and-revalidate rounds.
    • Remaining validation findings must now be reported explicitly after the allowed attempts.
  • Improvements

    • Adjusted agent effort levels to better match their responsibilities, including a lower effort setting for quality checks and specification authoring.

…y role

`spec-author` ran at high effort three times per feat and `quality-gate` at
medium, and both were the wrong end of the same trade.

spec-author authors a SCAFFOLDED artifact whose shape the template already
fixes, three times per feat. The argument for high was that a shallow draft
pushes the real authoring back onto the opus reviewer as fix-lists, defeating
the cost split — but a measured feat put $3.15 of its $4.69 on sonnet, so the
split was already lost at that end. Medium, with the fix-list count as the
signal to move it back.

quality-gate runs the declared commands and relays their output; its own prompt
says it decides nothing about the code. Low.

The two reviewers stay at high deliberately. They fire once or twice per feat,
so lowering them saves almost nothing, and they are pure judgment: the same
measured feat arrived "implemented" with 691 green tests and a drawer that
never collapsed at any width — the review is what found it.

The validate/fix loop is bounded at two rounds. "Re-validate until it returns 0"
is an open loop, and the finding it cannot resolve on the second pass is the one
it will not resolve on the fourth either, having re-read an 800-line spec each
time to retry a fix it already tried.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ARBSaXgJ7ssW1hvpy6r64y
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The agent templates update effort tiers, bound the spec-author validation/fix loop to two rounds, and expand templater tests to verify both the workflow wording and expected effort metadata.

Changes

Agent template updates

Layer / File(s) Summary
Bound spec-author validation workflow
internal/templater/templates/agents/spec-author.md.tmpl, internal/templater/templater_test.go
The spec-author prompt now permits at most two validation/fix rounds, requires remaining findings to be reported, and tests reject the previous unbounded-loop wording.
Align and verify agent effort tiers
internal/templater/templates/agents/*.md.tmpl, internal/templater/templater_test.go
The spec-author effort changes to medium, quality-gate changes to low, and a new test verifies the expected effort tier for each agent.

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

Possibly related PRs

  • protonspy/csdd#87: Introduced and used the spec-author sub-agent/template behavior updated here.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: agent effort levels are reassigned based on usage frequency rather than role.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/agent-effort-ladder

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/templater/templater_test.go`:
- Around line 623-635: Update TestAgentEffortLadder to isolate or parse each
agent template’s frontmatter before checking the expected effort value, ensuring
the assertion validates frontmatter metadata rather than matching prose
elsewhere in the body. Keep the existing agent-name coverage and expected effort
mappings unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 361c8208-3cdb-44d8-a7cd-00dc501345fd

📥 Commits

Reviewing files that changed from the base of the PR and between 286c278 and e399883.

📒 Files selected for processing (3)
  • internal/templater/templater_test.go
  • internal/templater/templates/agents/quality-gate.md.tmpl
  • internal/templater/templates/agents/spec-author.md.tmpl

Comment on lines +623 to +635
for name, want := range map[string]string{
"implementer.md": "effort: high",
"spec-author.md": "effort: medium",
"code-reviewer.md": "effort: high",
"security-reviewer.md": "effort: high",
"quality-gate.md": "effort: low",
} {
body, ok := agents[name]
if !ok {
t.Errorf("AgentFiles is missing %s", name)
continue
}
if !strings.Contains(body, want) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the effort value inside frontmatter.

TestAgentEffortLadder searches the entire template body, so it can pass if the expected effort: string appears in prose while the actual frontmatter is wrong. Since this test is intended to pin metadata, parse or isolate the frontmatter before asserting.

Proposed fix
 	for name, want := range map[string]string{
 		"implementer.md":       "effort: high",
 		"spec-author.md":       "effort: medium",
 		"code-reviewer.md":     "effort: high",
 		"security-reviewer.md": "effort: high",
 		"quality-gate.md":      "effort: low",
 	} {
 		body, ok := agents[name]
 		if !ok {
 			t.Errorf("AgentFiles is missing %s", name)
 			continue
 		}
-		if !strings.Contains(body, want) {
+		parts := strings.SplitN(body, "---", 3)
+		if len(parts) != 3 || !strings.Contains(parts[1], "\n"+want+"\n") {
 			t.Errorf("%s should carry %q", name, want)
 		}
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for name, want := range map[string]string{
"implementer.md": "effort: high",
"spec-author.md": "effort: medium",
"code-reviewer.md": "effort: high",
"security-reviewer.md": "effort: high",
"quality-gate.md": "effort: low",
} {
body, ok := agents[name]
if !ok {
t.Errorf("AgentFiles is missing %s", name)
continue
}
if !strings.Contains(body, want) {
for name, want := range map[string]string{
"implementer.md": "effort: high",
"spec-author.md": "effort: medium",
"code-reviewer.md": "effort: high",
"security-reviewer.md": "effort: high",
"quality-gate.md": "effort: low",
} {
body, ok := agents[name]
if !ok {
t.Errorf("AgentFiles is missing %s", name)
continue
}
parts := strings.SplitN(body, "---", 3)
if len(parts) != 3 || !strings.Contains(parts[1], "\n"+want+"\n") {
t.Errorf("%s should carry %q", name, want)
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/templater/templater_test.go` around lines 623 - 635, Update
TestAgentEffortLadder to isolate or parse each agent template’s frontmatter
before checking the expected effort value, ensuring the assertion validates
frontmatter metadata rather than matching prose elsewhere in the body. Keep the
existing agent-name coverage and expected effort mappings unchanged.

@protonspy
protonspy merged commit 11dfe9b into main Jul 28, 2026
7 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.

1 participant