routing: make per-role effort user-configurable (config layer), persistent across plugin updates #54

Closed
opened 2026-07-24 16:23:34 +00:00 by crenshawdev · 3 comments
crenshawdev commented 2026-07-24 16:23:34 +00:00 (Migrated from github.com)

Problem

stakes picks a rung bundle per role, and model.overrides.<role> pins a model alias. Neither is a durable handle on effort. Effort is frozen in each rung agent file's frontmatter, and those files ship inside the plugin, so any edit a user makes there is replaced by the next plugin update.

The config layers that do survive an update (~/.claude/cadence/config.json global, .planning/config.json per repo) expose only:

  • stakes (solo / shipped / critical), which is project-wide, not per role
  • model.escalate_on_failure
  • model.overrides.<role>, a model alias pin that explicitly does not touch effort

So a user who wants cad-verifier running lighter, or cad-assumptions-analyzer heavier, has no persistent path. The model can be pinned; the effort cannot.

Scope, after v2.0.0

The tier half of the original issue is superseded and dropped: the per-role tier, base_effort, the profile matrix and the tier bump were all deleted in v2.0.0 (#63), so there is nothing left to expose. This issue is now the effort half only.

v2.0.0 also made that half cheaper. The rung ladder materialized every role's contract at each effort rung, so a config key would select an agent file that already exists rather than needing new dispatch machinery.

Desired behavior

route.mjs resolve reads a per-role effort rung from the config layer, falling back to the stakes cell when unset, with the same precedence model.overrides already follows (config over shipped default). One constraint the ladder imposes: the configured value must name a rung that actually exists for that role, and self-verify should fail naming the key when it does not, rather than resolving to the unsuffixed agent file silently.

Sketch

Leave model.overrides.<role> a bare alias, since changing its type is itself a break. Add a sibling map enumerated per role the same way, e.g. effort.overrides.<role>, with values drawn from the rung vocabulary.

## Problem `stakes` picks a rung bundle per role, and `model.overrides.<role>` pins a model alias. Neither is a durable handle on **effort**. Effort is frozen in each rung agent file's frontmatter, and those files ship inside the plugin, so any edit a user makes there is replaced by the next plugin update. The config layers that do survive an update (`~/.claude/cadence/config.json` global, `.planning/config.json` per repo) expose only: - `stakes` (solo / shipped / critical), which is project-wide, not per role - `model.escalate_on_failure` - `model.overrides.<role>`, a model alias pin that explicitly does not touch effort So a user who wants `cad-verifier` running lighter, or `cad-assumptions-analyzer` heavier, has no persistent path. The model can be pinned; the effort cannot. ## Scope, after v2.0.0 The tier half of the original issue is superseded and dropped: the per-role `tier`, `base_effort`, the profile matrix and the tier bump were all deleted in v2.0.0 (#63), so there is nothing left to expose. This issue is now the effort half only. v2.0.0 also made that half cheaper. The rung ladder materialized every role's contract at each effort rung, so a config key would select an agent file that already exists rather than needing new dispatch machinery. ## Desired behavior `route.mjs resolve` reads a per-role effort rung from the config layer, falling back to the stakes cell when unset, with the same precedence `model.overrides` already follows (config over shipped default). One constraint the ladder imposes: the configured value must name a rung that actually exists for that role, and self-verify should fail naming the key when it does not, rather than resolving to the unsuffixed agent file silently. ## Sketch Leave `model.overrides.<role>` a bare alias, since changing its type is itself a break. Add a sibling map enumerated per role the same way, e.g. `effort.overrides.<role>`, with values drawn from the rung vocabulary.
crenshawdev commented 2026-07-28 17:41:51 +00:00 (Migrated from github.com)

Collision to settle before either is scheduled: #63 proposes deleting the tier ladder entirely and replacing model-as-lever with effort-as-lever. This issue asks to make that same tier ladder user-configurable so it survives a plugin update. Both cannot land. Whichever wins, the other closes.

Collision to settle before either is scheduled: #63 proposes deleting the tier ladder entirely and replacing model-as-lever with effort-as-lever. This issue asks to make that same tier ladder user-configurable so it survives a plugin update. Both cannot land. Whichever wins, the other closes.
Owner

Narrowed at the v2.0.0 close and carried into v2.0.1. Recording what changed, since the body above has been rewritten.

The tier half is superseded and dropped. v2.0.0 deleted the machinery this issue proposed exposing: route-table.json carries no per-role tier or base_effort, and the profile matrix and tier bump are gone (#63). There is no tier left to make configurable.

The effort half is still unmet, and is now cheaper to satisfy. The original text is accurate on this point and stays true against shipped code: model.overrides.<role> pins a model alias and explicitly does not touch effort, and effort itself is frozen in each rung agent file's frontmatter, which a plugin update replaces. What v2.0.0 changed is the cost of the fix. The rung ladder means every role already has materialized agent files at each effort rung, so a config key selects an existing rung instead of needing new dispatch machinery.

The v2.0.0 close notes had this issue down as closing wholesale as superseded. That was right about tier and wrong about effort, which is why it stayed open and moved rather than closing.

Narrowed at the v2.0.0 close and carried into v2.0.1. Recording what changed, since the body above has been rewritten. **The tier half is superseded and dropped.** v2.0.0 deleted the machinery this issue proposed exposing: `route-table.json` carries no per-role `tier` or `base_effort`, and the profile matrix and tier bump are gone (#63). There is no tier left to make configurable. **The effort half is still unmet, and is now cheaper to satisfy.** The original text is accurate on this point and stays true against shipped code: `model.overrides.<role>` pins a model alias and explicitly does not touch effort, and effort itself is frozen in each rung agent file's frontmatter, which a plugin update replaces. What v2.0.0 changed is the cost of the fix. The rung ladder means every role already has materialized agent files at each effort rung, so a config key selects an existing rung instead of needing new dispatch machinery. The v2.0.0 close notes had this issue down as closing wholesale as superseded. That was right about tier and wrong about effort, which is why it stayed open and moved rather than closing.
john changed title from routing: make per-role tier and effort user-configurable (config layer), persistent across plugin updates to routing: make per-role effort user-configurable (config layer), persistent across plugin updates 2026-07-30 04:52:36 +00:00
john modified the milestone from v2.0.0 to (deleted) 2026-07-30 04:52:36 +00:00
john modified the milestone from (deleted) to v2.1.0 2026-07-30 05:15:35 +00:00
Owner

Closed by v2.2.0 (RNG-02). model.effort.<role> keys now live in cadence-core/config.schema.json, one per role. Each accepts only the rungs that role actually has and refuses anything else by naming the allowed set, and a rung a role lacks fails self-verify by key.

They sit in the config layer rather than in the rung agent frontmatter, so they survive a plugin update, which was the durability half of this ask.

Verified against the tree at the v2.3.0 close: config.schema.json:19-20 and the sibling model.effort.* entries.

Closed by v2.2.0 (RNG-02). `model.effort.<role>` keys now live in `cadence-core/config.schema.json`, one per role. Each accepts only the rungs that role actually has and refuses anything else by naming the allowed set, and a rung a role lacks fails self-verify by key. They sit in the config layer rather than in the rung agent frontmatter, so they survive a plugin update, which was the durability half of this ask. Verified against the tree at the v2.3.0 close: `config.schema.json:19-20` and the sibling `model.effort.*` entries.
john closed this issue 2026-08-05 17:08:59 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: crenshawdev/cadence-archived#54
No description provided.