Commit Graph
1130 Commits
Author SHA1 Message Date
bchanot 5bab61e13a chore(model-router): routing.json decision — doc-syncer kept on write (live first-use dialog, user Keep) 2026-10-11 11:57:56 +02:00
bchanot 304a02d70a docs: README/USAGE first-use dialog, routing.json source + config layers, ARCHITECTURE, CHANGELOG Unreleased — feat model-router wave 3-A 2026-10-11 11:57:56 +02:00
bchanot 22455c051f feat(model-router): wave 3-A — first-use route confirmation, decision memory, project exceptions
routing.json (tracked, reached through the plugin directory) is now the
single source of the phase table and of every skill/agent row, plus the
decisions: confirmed rows/phases, changed rows (from/to) and projects
exceptions keyed by a normalized git remote (credentials never stored, no
machine paths). First use of a rowed typed skill, a rowed agent spawn or a
main-loop phase opens the engine's dialog (Later / Keep / two alternative
phases; Other = a phase name); a change asks Everywhere or This project
only. One dialog at a time, never in headless, never inside an agent,
never written by the model: only a dialog answer or /route ask writes,
serialized, size-capped, never creating the file. Layers: routing.json <
~/.claude/model-router.json; the project tree is never read. /route
pending, /route ask on|off. Census reads rows and phases from the file and
tolerates a user-changed row (WARN). Kit suite 86 → 190 tests.

Contract .claude/tasks/contracts/2026-10-10-model-router-w3a-confirm-1201.md,
plan r4: 3 lenses + 1 confirmation, feater + 4 rounds, GATE 0 MET,
verifier CONFORME then re-verify after security, security BLOCK(1) fixed
then PASS. Live: T2 dialogs answered by the user from the hot-loaded mod.
2026-10-11 11:48:25 +02:00
bchanot 45bb86ff1d Merge feature/model-router-w2 into develop 2026-10-10 11:43:59 +02:00
bchanot c1767a5032 chore(memory): BDR-115 amendment 2 + LRN-210/211 + EVAL-042 + journal/TODO/contract w2b — feat model-router wave 2 2026-10-10 11:32:58 +02:00
bchanot 6f0df37f5b docs: README model/effort routing + mod bullets, USAGE niveau d'effort, ARCHITECTURE, CHANGELOG Unreleased (Removed, Changed, breaking 3.0.0) — feat model-router wave 2 2026-10-10 11:32:57 +02:00
bchanot 1f2d33b7a6 feat(model-router): wave 2-B — orchestrators declare phases, shifters and pins removed, frontmatter = off-state floor
The 15 Skill(effort-*) citers now call mcp__model-router__route per phase
(orchestrate at a dispatch span, reflect/plan for the skill's own level,
apply at the bookkeeping tail, escalate at the verify-secure caps); built-in
judgment dispatches carry an explicit effort= param. lib/effort-shift.md is
the route doctrine, lib/model-gate.md the mod rule (route answer = witness,
/route on as remedy). Deleted: skills/effort-*, lib/effort-pins.txt/.sh,
lib/model-check.sh, their tests, the installers' re-apply blocks. The mod
drops its Skill(effort-*) bridge. The tracked model:/effort: frontmatter
stays as the off-state floor, census-locked equal to the rows
(lib/tests/effort-routing.test.sh rewritten, 140 checks; analyzer → xhigh).

Contract .claude/tasks/contracts/2026-10-10-model-router-w2b-1045.md, plan
r4 § W2-B: GATE 0 MET, verifier ECARTS(7) then CONFORME 10/10, security
PASS, full make test green (design-tool-gate env red only).
2026-10-10 11:24:54 +02:00
bchanot 65dff0e768 chore(memory): journal + TODO + contract w2a — feat model-router wave 2-A 2026-10-09 17:22:43 +02:00
bchanot bb56f3e41e feat(model-router): wave 2-A — phase rows for every repo skill and agent, run slot, typed-slash routing
Rows by role replace the pins as the live source (frontmatter stays as the
off-state floor): phases write=work/high and apply=work/low, 56 skill rows,
21 agent rows + Explore/Plan. Agents get the row's model at spawn (within
the tier, upward only, explicit params win, project-defined agents skipped
via agent.offer) and its effort per step. A typed slash of a rowed skill
routes main through a name-bound marker (composer|sdk|bridge, pending slot
mid-turn) or the idle fallback; a best-tier row lives in a runMain slot
that survives turn end and route calls. An unrowed skill leaves the route.
Typed /effort-* floor code removed (bridge kept until W2-B). The route
answer always names the id. Override rows accept null. Kit suite 58 → 88.

Contract .claude/tasks/contracts/2026-10-09-model-router-w2a-1546.md, plan
r4 .claude/tasks/plans/2026-10-09-model-router-w2-1546.md: 3 lenses + 2
confirmations, feater + 4 rounds, GATE 0 MET, verifier 3x ECARTS on test
coverage only (user-accepted at the cap), security PASS.
2026-10-09 17:22:07 +02:00
bchanot 862740da9d chore(memory): journal — make test hotfix merged, session close before wave 2 2026-10-09 15:37:29 +02:00
bchanot 5e0e5c0bc4 Merge bugfix/make-test-names-red-suites into develop 2026-10-09 15:37:17 +02:00
bchanot ca9645833c chore(memory): LRN-207/208/209 + EVAL-041 — availability signal, blind security brief, scoped test runs, W1-C challenge value 2026-10-09 15:36:59 +02:00
bchanot b09e84497a chore(memory): journal — make test summary hotfix 2026-10-09 15:31:27 +02:00
bchanot efdd491d63 fix(make): test target names every red suite and prints a summary
A full make test printed only the == headers and an aggregate exit code,
so finding the red suite meant re-running every suite one by one (the
pre-merge check of 2026-10-09 took 7.5 min for that reason). The loop now
prints FAIL <suite> as it happens and ends with 'all suites green' or
'<n> suite(s) red: <names>'; the exit code is unchanged.
2026-10-09 15:31:26 +02:00
bchanot ff741e3a82 chore(memory): journal — model-router wave 1 merged into develop 2026-10-09 15:25:39 +02:00
bchanot abbdf7926d Merge feature/model-router-mod into develop 2026-10-09 15:25:06 +02:00
bchanot a4f660d0b6 chore(tasks): model-router W1-C live checks part 1 done, part 2 queued; journal 2026-10-09 15:14:55 +02:00
bchanot 6f31f49d7c chore(tasks): model-router W1-C done — contract evidence, TODO (accepted MEDIUMs, residuals, live checks), journal 2026-10-09 15:09:07 +02:00
bchanot d0fa1001bb feat(mods): model-router adaptive tiers — absolute tiers, availability breaker, derived phases
Phases name absolute tiers (best fable>opus>sonnet, big opus>fable>sonnet,
work sonnet>opus, cheap haiku>sonnet) resolved to the first available full
id; per-model circuit breaker fed by StopFailure kinds (rate_limit,
overloaded, billing_error, model_not_found) and PostModelSwitch auto, with
episode backoff 15→300 min, cleared by a user /model or /route reload and
kept across /clear; fallback chain fable→opus→sonnet→haiku with the effort
unchanged; main loop upgrades to a phase's tier by itself under a context
cap (fails closed on unknown usage), downgrades only with the switch on,
sticky within a turn; derived orchestrate on background dispatches;
prompt default rules (plan/reflect, Unicode guards, skipped on slash
commands, floor matches and mid-turn). 58 plugin tests.
2026-10-09 15:08:49 +02:00
bchanot 977be7cad8 chore(tasks): model-router W1-C plan r3 + r4 after two confirmation passes 2026-10-09 13:22:07 +02:00
bchanot 140c16a67f chore(tasks): model-router W1-C plan r2 + contract amendments after the FATAL round 2026-10-09 12:55:14 +02:00
bchanot 2d8cd6bf4c chore(tasks): model-router W1-C contract + plan (absolute tiers, breaker fallback, derived phases) 2026-10-09 12:40:19 +02:00
bchanot e79db7e6df chore(memory): model-router wave 1 closed — TODO W2 queued, journal 2026-10-09 11:16:32 +02:00
bchanot b22f8947f9 docs: README effort routing + /route, USAGE, ARCHITECTURE mods/, CHANGELOG — model-router wave 1 2026-10-09 11:04:10 +02:00
bchanot a6e200392c chore(memory): BDR-115 amendment (skills-dir load, floor, kill switch) + journal B2 2026-10-09 10:52:28 +02:00
bchanot 3c44dd00d3 chore(tasks): model-router B2 done — contract evidence, TODO close-out queue 2026-10-09 10:51:51 +02:00
bchanot 6430ac65ec feat(mods): model-router active in every session — skills-dir link, mods suite, doctor section, CLAUDE.md
Tracked relative symlink skills/model-router -> ../mods/model-router: Claude
Code loads the mod in place as model-router@skills-dir wherever link.sh
links ~/.claude/skills (no CLAUDE_CODE_PLUGIN_DIRS: absolute paths in the
tracked settings.json). Engine-laid mods/*/tsconfig.json gitignored.
lib/tests/mods.test.sh: manifest name, link target, claude plugin validate
and test per mod, capability-probed, time-bounded, SKIP with reason.
doctor.sh: fail-soft Mods section (link by -ef, one guarded plugin list).
CLAUDE.md: mods/ section (loading, per-machine enabled:false switch,
dev-copy shadowing, tests).
2026-10-09 10:51:13 +02:00
bchanot 24e180ade0 chore(tasks): model-router B1 done — contract evidence, TODO, journal 2026-10-09 10:13:03 +02:00
bchanot 1ff608a68c feat(mods): model-router user effort floor — ultrathink and typed /effort-<l> set the main turn's default and minimum
One decision helper (mainEffort) feeds the plan and every answer text;
per-axis precedence (sticky > turn route > floor > engine); a mid-turn
prompt floors the running turn and the next; per-machine kill switch
"enabled": false in ~/.claude/model-router.json, kept across /clear and
across a failed reload; typed /effort-<l> attested at prompt.submit so a
sub-agent preload cannot floor the main loop. 30 plugin tests.
2026-10-09 10:12:28 +02:00
bchanot 868a7f0515 chore(tasks): model-router B1/B2 plans r2 after the 6-lens challenge round 2026-10-09 09:24:32 +02:00
bchanot 77ad7cf494 chore(tasks): model-router W1-B split — floor + wiring contracts/plans, skills-dir loading decision, journal 2026-10-08 18:37:32 +02:00
bchanot ae0179f491 chore(tasks): model-router contract criteria 7-11, TODO hardening done + residuals, journal 2026-10-08 16:53:43 +02:00
bchanot 346d6aeab2 feat(mods): model-router hardening — user-only /route, effort-only agent routes, config caps, visible fail-open
Security-gate round on the wave 1-A mod: /route answers only a composer
origin; an in-agent route call can no longer change the agent's model
(effort only, model fixed at spawn); config patterns capped (200 chars,
4096-char scan), phase keys restricted, override file refused above 64 KB,
additionalProperties false on the tool schema; every .catch logs once per
session; post-next bookkeeping isolated. 14 plugin tests, verifier 11/11.
2026-10-08 16:53:43 +02:00
bchanot 64702d50ea chore(memory): BDR-115 + LRN-205/206 + EVAL-040 — model-router architecture, tool output schema, plugin test kit, challenge value 2026-10-08 16:38:08 +02:00
bchanot 6dc2d748fc chore(memory): journal + TODO — model-router wave 1-A done, hardening + 1-B queued 2026-10-08 16:27:43 +02:00
bchanot e8ca713d9e chore(tasks): model-router w1a contract + plan r3 2026-10-08 16:26:57 +02:00
bchanot b721c94dcb feat(mods): model-router mod, wave 1-A — per-request model/effort routing
Function-hooks plugin under mods/model-router: routes effort (and, behind a
flag, the model) of every main-loop request, sets built-in sub-agents' model
at spawn with full ids, answers Skill(effort-*) itself (single writer, no
pairing rule), exposes the route tool and /route, validates the optional
~/.claude/model-router.json. 11 plugin tests, validate + tsc clean.
Contract .claude/tasks/contracts/2026-10-08-model-router-w1a-1533.md.
2026-10-08 16:26:57 +02:00
bchanot b73d1b127e chore(memory): model-router wave 0 — plan, LRN-203/204, BLK-029, journal 2026-10-08 15:25:11 +02:00
bchanot f24682b3f3 chore(memory): BDR-112 amendment — manual-push mode user-tested, dotfiles prompt handed over 2026-10-07 17:45:01 +02:00
bchanot 6b528dc85f chore(memory): journal + TODO — manual-push-mode merged into develop (669db06) 2026-10-07 17:37:57 +02:00
bchanot 669db06485 Merge feature/manual-push-mode into develop 2026-10-07 17:37:38 +02:00
bchanot 3721cf522a chore(memory): BDR-114 + LRN-200..202 + journal — feat manual-push-mode run D 2026-10-07 17:24:31 +02:00
bchanot 1203a9a735 docs(gitflow): run D — invalid autopush value fails closed everywhere; CHANGELOG, SETTINGS, gitflow skill 2026-10-07 17:24:30 +02:00
bchanot 4a747c8144 docs(doctrine): manual-push mode — invalid value counts as manual; Claude never pushes, even when asked 2026-10-07 17:24:29 +02:00
bchanot 64ca0f8e09 docs(skills): invalid autopush value is fail-closed everywhere; prose aligned
Run D3 of manual-push mode (BDR-114). With every reader now failing
closed, the skill prose stops saying the lib and hooks still push on an
invalid value:

- capitalize STEP 5C / STEP 6: the invalid outcome is split on the ahead
  count (nothing pushed vs pushed anyway by a stale fail-open hook or a
  manual push); the verb's stderr line is quoted verbatim; neighbouring
  closing lines carry push-mode qualifiers so none shadows the invalid
  case; the --no-push lines follow the same rule.
- client-handover: "COMMIT + PUSH" labels become "COMMIT + PUSH STATE
  READ"; the STEP 5 residual sentences no longer imply the pipeline
  pushes; the invalid value is named as a case where the user pushes.
- release-executor: prep span checks the version format by reading the
  string (never in a Bash command); manual mode and an invalid value
  both leave main/develop local.
2026-10-07 17:11:58 +02:00
bchanot 3c59333fcf fix(push-guard): single reader, whole-word dir tokens, payload fallback, bad-value banner
Run D2 of manual-push mode (BDR-114).

- push-guard sources lib/gitflow.sh once (absolute path) and reads each
  candidate dir through gitflow_push_mode; a missing lib denies.
- Dir tokens are extracted as whole shell words: a fully quoted token
  (inner apostrophe allowed) is resolved, a backslash-escaped space is
  unescaped deterministically, a token mixing quoted and unquoted parts
  is refused (fail closed) instead of resolving to its parent.
- A payload jq cannot parse is scanned as raw text with its JSON escapes
  folded; a push-looking one gets the static deny through the trap.
- The 20-token cap runs before any per-token classification (a flood of
  20 000 tokens is refused in 0.13 s; T58 locks it under 5 s).
- `case "$mode"` has a deny default; missing core tools warn and allow.
- T42 compares the deny list against main (the last release) instead of
  HEAD; literal-true, mixed-token, broken-payload, lib-missing and
  banner-on-bad-value cases added (98 checks).
- session-start banner reads the mode through the verb and shows
  `push : manual (autopush bad)` on an unparseable value.
- tour hints quote "<abs project>".
2026-10-07 17:11:56 +02:00
bchanot 472cccbc52 fix(gitflow): every autopush reader fails closed and names an invalid value
Run D1 of manual-push mode (BDR-114). `git config --bool --default true
gitflow.autopush` only covered a MISSING key: an unparseable value made
git die with empty output, the `= false` test failed, and every push ran
again. A typo on a work machine silently re-enabled the pushes it was
meant to stop.

- lib/gitflow.sh: `_gitflow_push_off` reads the mode through the lib
  verb (`push-mode`); anything but `auto` is push-off, and the verb's
  stderr line names an invalid value during start/finish.
- Emitted post-commit/post-merge hooks (POSIX sh, standalone): push only
  when the key reads `true` or is unset; `false` exits quietly; any
  other result prints one stderr line ("NOT pushed, treated as manual
  push mode") and exits 0. Mirrors gitflow_push_mode.
- .githooks/ and githooks/ regenerated files-only through `emit-hook`
  (no config read or write; .git/config hash unchanged).
- hooks/unpushed-guard.sh: mode from the lib verb (absolute lib path
  resolved before any cd, no temp file); anything but auto is manual;
  the SessionStart line names an invalid or unreadable value.
- Tests: gitflow-test T18q block (invalid → start, hook and finish push
  nothing and say so; `true` → the hook pushes; emitted hook is
  POSIX-clean), unpushed-guard T14 rewritten.
2026-10-07 16:45:31 +02:00
bchanot e4bc6212ef docs(gitflow): run C — push-mode verb, skills never push; CHANGELOG, SETTINGS, gitflow skill, README, USAGE 2026-10-07 14:48:27 +02:00
bchanot 0b08ceda97 chore(memory): BDR-113 + LRN-197..199 + journal — feat manual-push-mode run C 2026-10-07 14:48:07 +02:00
bchanot 3881f462c6 fix(gitflow): run C polish — 5C coherence, sanitized verb stderr, hermetic suite
Closes the non-gap observations the gates left on runs C1/C2:

- capitalize STEP 5C/6: heading no longer says "+ push"; the --no-push
  fact read is its own paragraph and scoped to that path; the
  auto-persisted line requires finish rc 0 AND ahead = 0; rc 5/2/6
  (merged, branch not deleted) still report the push state; the
  "not on origin" line carries the once-a-remote-exists hint.
- gitflow.sh push-mode: the raw config value echoed on stderr is reduced
  to printable characters (LC_ALL=C, BSD tr safe) and capped at 64.
- gitflow-test.sh exports the hermetic git config env in the file, so a
  bare run on a global-manual machine stays green.
- client-handover-writer: the branch allowlist refuses a leading dash.
2026-10-07 14:35:08 +02:00