docs: README effort routing + /route, USAGE, ARCHITECTURE mods/, CHANGELOG — model-router wave 1
This commit is contained in:
@@ -26,6 +26,7 @@ claude-config/
|
||||
├── rules/ # Rule files deployed to ~/.claude/rules (path-scoped or always-on)
|
||||
├── agents/ # Execution units called by skills (never invoked directly)
|
||||
├── skills/ # Entry points invoked via /skill-name
|
||||
├── mods/ # Claude Code mods (function-hooks plugins), loaded through the skills/<name> symlink
|
||||
├── skills-external/ # Vendored skill packs: gstack submodule, design skills, superpowers, agent-skills, MengTo scroll skills, 21st and Higgsfield packs (machine-owned copies gitignored)
|
||||
├── templates/ # Per-project templates (CLAUDE.md, settings, memory registries, deploy runbook, gitignore)
|
||||
└── lib/ # Shared libs: gitflow, profiles, vendoring, effort pins, gates, archetypes, tests
|
||||
@@ -35,5 +36,6 @@ claude-config/
|
||||
|
||||
- `skills/` = entry points you invoke via `/skill-name`
|
||||
- `agents/` = execution units called by skills (never invoked directly by user)
|
||||
- `mods/` = Claude Code mods (function-hooks plugins); each loads through the tracked symlink `skills/<name>` as `<name>@skills-dir`, live at the next session
|
||||
- `templates/` = symlinked to `~/.claude/templates/` — copy into projects via `/onboard` or manually
|
||||
- **Graphify** builds a knowledge graph of any codebase (`/graphify query`), producing a navigable wiki in `graphify-out/wiki/`. This map helps Claude understand project structure, find relevant code faster, and reason across files. Essential for large-scope tasks (multi-file features, complex bugs, architectural changes). Small tasks should skip it and read files directly. Proposed only from 200 tracked code files: the session-start banner informs, the user decides; nothing builds a graph without that go.
|
||||
|
||||
@@ -7,6 +7,7 @@ Format follows [Keep a Changelog](https://keepachangelog.com/) and this project
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- **model-router mod**: `mods/model-router/`, a Claude Code mod (function-hooks plugin), routes the effort of every main-loop request from a phase table, along with the model and effort of the built-in sub-agents (Explore on sonnet/medium, Plan on opus/xhigh). It answers `Skill(effort-*)` itself, so the five `effort-*` skills no longer load while it is on. `ultrathink` in a prompt and a typed `/effort-<level>` set the main turn's default and minimum effort. The model gets a `route` tool and the user a `/route` command (`show|clear|off|on|reload|<phase>|model=<alias|id> effort=<level>|switch on|off|verbose on|off`). Optional per-machine config `~/.claude/model-router.json`, where `"enabled": false` turns it off on that machine. The spinner suffix and the status line show the route in force. It loads in every session through the tracked symlink `skills/model-router` (`model-router@skills-dir`). `make doctor` gains a Mods section; suite `make test suite=lib/tests/mods.test.sh`. Known limits: the main loop switches model only with `mainModelSwitch` on (default off, one cold-cache step per switch into another model), and the hooks send full model ids, so the `models` table has to follow new versions.
|
||||
- **Manual-push mode**: `git config gitflow.autopush false` (human-set) now stops every push the gitflow lib makes, not only the post-commit / post-merge hooks. `gitflow start` and `finish` branch, commit and merge locally and push nothing; `gitflow delete` leaves the `origin/` copy in place and prints `git push origin --delete <br>` for the user to run. `hooks/unpushed-guard.sh` stays silent at turn end in this mode and opens each session with one `ℹ manual push mode:` line counting the commits no remote holds across every local branch; an unparseable or unreadable `gitflow.autopush` value is treated as manual push mode too, and that line names it. `hooks/push-guard.sh` (PreToolUse, `Bash|Monitor`) refuses any `git push` Claude types while `gitflow.autopush` reads false in the session cwd or in a literal `-C`/`cd` directory the command names (global config counts outside a repo); the refusal tells the user to run it with `! git push`. It reads the mode through the same lib verb as every other reader and fails closed: an unparseable or unreadable value reads as manual, and an internal error, a missing `lib/gitflow.sh`, more than 20 distinct directory tokens in one command (capped before any token is classified), a `cd`/`-C` directory token mixing quoted and unquoted parts, or a payload jq cannot parse whose raw text looks like a push refuse the push (these pathological cases fire in auto mode too). Directory tokens are read as whole shell words, adjacent quoted segments and backslash escapes included. In manual mode it over-blocks any command where a `push` word follows a `git` token; the misses listed in its header fall to a new `autoMode.soft_deny` rule that no request in the turn clears. The session banner adds `🔒 push : manual (autopush=false) — ! git push` when the key reads false, and `🔒 push : manual (autopush bad) — ! git push` when the value is invalid. Skills read the mode through a new lib verb, `bash ~/.claude/lib/gitflow.sh push-mode`: it prints `auto`, `manual` or `invalid` (rc 0) and names an invalid value on stderr (printable characters only, 64 at most). It is the one reader a skill may call, since the `git config` read of the key is denied to Claude. Skills push nothing on their own, except the `/release-candidate` tag in auto-push mode on an explicit go. Every "on origin" or "not pushed" line they print comes from `git rev-list --count origin/<br>..<br>` read after the fact, with the complete `! git …` command when something is left for the user to push. An invalid value (anything but unset, true or false, or a read that fails) is manual push mode for every reader and is named where it is read (see Fixed). Tests: `lib/gitflow-test.sh` T11b (push-mode verb), T18m and T18q blocks, `lib/tests/unpushed-guard.test.sh` T10-T16, `lib/tests/push-guard.test.sh` (98 checks).
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -88,7 +88,7 @@ every call site.
|
||||
| doc-syncer | sonnet pin; audit mode dispatched `model="opus"` | two-mode: audit (drift judgment, opus) / patch (mechanical apply, sonnet) |
|
||||
| handover-doc-writer | sonnet pin; synthesize mode dispatched `model="opus"` | two-mode: synthesize (opus) / render (sonnet) — client deliverable |
|
||||
| interviewer, client-handover-writer | unpinned (inline-load = session model) | they ARE the main loop — a frontmatter pin would be inert |
|
||||
| Explore (built-in) | inherit session (Fable/Opus) | search feeds reflection — kept on the big model, not pinned down |
|
||||
| Explore, Plan (built-in) | model-router mod: Explore → sonnet/medium, Plan → opus/xhigh, set at spawn; an explicit `model=` on the call wins; mod off: inherit session | built-ins routed per phase by the mod |
|
||||
|
||||
The pure-execution skills `/doc`, `/status`, `/commit-change`,
|
||||
`/release-candidate` **dispatch** their agent (instead of inline-loading it)
|
||||
@@ -108,12 +108,26 @@ entry level (`/status` low … `/ship-feature` xhigh); the vendored externals
|
||||
`lib/effort-pins.txt`, re-applied by `lib/effort-pins.sh` after every
|
||||
vendoring step. Orchestrators shift per phase through the `effort-low` …
|
||||
`effort-max` skills (`lib/effort-shift.md`, always sent with another tool
|
||||
call: a lone Skill call applies nothing). Model pins stay tier aliases
|
||||
call: a lone Skill call applies nothing (mod off)). Model pins stay tier aliases
|
||||
(`sonnet`, `opus`, `haiku`, `fable`): the latest version of a tier is also
|
||||
the cheapest or same-priced, so the quality/price trade-off is tier × effort,
|
||||
never version. Census `lib/tests/effort-routing.test.sh`; transcript audit
|
||||
`python3 lib/effort-audit.py`.
|
||||
|
||||
### model-router mod
|
||||
|
||||
`mods/model-router/` is a Claude Code mod (a function-hooks plugin) that applies this table per request. It loads in every session through the tracked symlink `skills/model-router`, as `model-router@skills-dir`.
|
||||
|
||||
- Main loop: every request gets the effort of the phase in force. The mod answers `Skill(effort-*)` itself and applies the level from the next request on, so the five `effort-*` skills no longer load while it is on.
|
||||
- Built-in sub-agents: Explore runs on sonnet/medium, Plan on opus/xhigh. An explicit `model` on the Agent call wins.
|
||||
- User floor: `ultrathink` in a prompt, or a typed `/effort-<level>`, sets the main turn's default and minimum effort.
|
||||
- `/route` (user command) shows or sets the route: `show`, `clear`, `off`, `on`, `reload`, a phase name, `model=<alias|id> effort=<level>`, `switch on|off`, `verbose on|off`. The model sets routes through a `route` tool.
|
||||
- The spinner suffix and the status line under the prompt show the route in force.
|
||||
|
||||
Optional per-machine config: `~/.claude/model-router.json`. Keys: `models` (alias → full id), `windows` (context window per full id), `phases`, `agents`, `skills`, `prompt` (rules), `mainModelSwitch` (default `false`), `verbose` (default `false`), `spinner` (default `true`), `enabled` (default `true`; `false` turns the mod off on that machine). `/route reload` re-reads it.
|
||||
|
||||
Limits: the main loop changes model only with `mainModelSwitch` on, and each switch into another model costs one cold-cache step. The hooks send full model ids, so the `models` table has to follow new model versions.
|
||||
|
||||
---
|
||||
|
||||
## Install notes
|
||||
@@ -204,7 +218,8 @@ a different package, ships its own conflicting `graphify` bin) — see
|
||||
| `/profile` | Activate a skill profile (web / seo / web-full / full / max / backend / design / dev / qa / audit / minimal) (default: full) |
|
||||
| `/tour` | Grouped all-axes sweep — cleanup + security + reconcile + doc, fix and loop until clean |
|
||||
| `/site-motion` | Site-level motion: scroll engine choice, page transitions, pin/scrub sequencing across a page or Astro route (design stack) |
|
||||
| `/effort-low` … `/effort-max` | Effort shifters the orchestrators send per phase; type `/effort-max` to re-run a stuck turn at maximum |
|
||||
| `/effort-low` … `/effort-max` | Effort shifters the orchestrators send per phase (answered by the model-router mod when on); typed by you, they set the main turn's default and minimum effort |
|
||||
| `/route` | model-router mod: show or set the main-loop route (show, clear, off, on, reload, <phase>, model=… effort=…, switch on\|off, verbose on\|off) |
|
||||
|
||||
> This table lists personal skills. Gstack skills (investigate, review, retro,
|
||||
> office-hours, cso…) and marketplace plugins add many more — run
|
||||
@@ -452,7 +467,7 @@ make profile-reset # go to the default profile (full)
|
||||
make new-skill name=myskill # scaffold agent + skill files
|
||||
```
|
||||
|
||||
`doctor.sh` checks: symlinks, GStack submodule, vendored skills (curl-pinned externals in `plugins.lock.json` + `link.sh`'s `EXTERNAL_SKILLS`, per the active profile), Playwright browser cache, prerequisites (git, Node, Cargo, Python, Claude Code), plugins, permissions, token budget, config consistency, git hooks (global core.hooksPath + generated githooks/), scratchpad (TMPDIR quota), Higgsfield CLI and session, seo-data layer.
|
||||
`doctor.sh` checks: symlinks, GStack submodule, vendored skills (curl-pinned externals in `plugins.lock.json` + `link.sh`'s `EXTERNAL_SKILLS`, per the active profile), Playwright browser cache, prerequisites (git, Node, Cargo, Python, Claude Code), plugins, permissions, token budget, config consistency, git hooks (global core.hooksPath + generated githooks/), mods (loading link and `@skills-dir` state), scratchpad (TMPDIR quota), Higgsfield CLI and session, seo-data layer.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@ Tu veux...
|
||||
| `/pdf-translate` | Traduire un PDF vers une autre langue | Sortie HTML fidèle (images, layout, style préservés) |
|
||||
| `/impeccable` | Audit/polish design + détecteur anti-slop déterministe | 23 verbes ; `npx impeccable detect` (exit 0/2) |
|
||||
| `/tour` | Sweep groupé sur un ou plusieurs projets | Sécu + nettoyage + reconcile + doc, boucle jusqu'à un pass propre |
|
||||
| `/route` | Voir ou fixer la route du mod model-router | show / clear / off / on / reload / <phase> / model=… effort=… / switch on\|off / verbose on\|off |
|
||||
| `/profile` | Changer le profil de skills | web / seo / web-full / full / max / backend / design / dev / qa / audit / minimal |
|
||||
|
||||
> Cette table couvre les skills personnels principaux. Les plugins (gstack,
|
||||
@@ -185,6 +186,8 @@ la main relance un tour bloqué au maximum. Les skills externes vendorés
|
||||
`lib/effort-pins.txt`. Un skill chargé seul par Claude n'applique pas son
|
||||
niveau : il doit partir avec un autre appel d'outil dans le même message.
|
||||
|
||||
Avec le mod model-router (`mods/model-router/`, actif dans chaque session), le niveau suit la phase à chaque requête. Le mod répond lui-même à `Skill(effort-*)` : le niveau s'applique dès la requête suivante et le texte des skills `effort-*` n'est plus chargé. Écrire `ultrathink` dans un prompt, ou taper `/effort-<niveau>`, fixe le niveau par défaut et le minimum du tour principal. Les sous-agents intégrés suivent leur route : Explore en sonnet/medium, Plan en opus/xhigh. `/route` affiche ou fixe la route (`/route show`, `/route clear`, `/route off`). La config par machine, optionnelle, vit dans `~/.claude/model-router.json` ; `"enabled": false` y coupe le mod sur cette machine.
|
||||
|
||||
## Les plugins — décision rapide
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user