Commit Graph
1126 Commits
Author SHA1 Message Date
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
bchanot 6104545e76 feat(skills): push state read from facts, never pushed by the skills
Run C2 of manual-push mode (BDR-111/BDR-112). The four flows that pushed
on their own, or claimed the branch was on origin, now read the truth
after the fact and hand the user the exact command:

- client-handover-writer: the "Push to origin now?" question and its
  push block are gone (the hooks had already pushed in auto-push mode;
  push-guard denies it in manual mode). A reusable PUSH STATE READ
  (branch, origin probe, `git rev-list --count origin/<br>..<br>`, the
  verb only to word the reason) runs after commit-change, at the top of
  the deploy pause, after "Deployed" and before each end report. The
  branch name is validated against an allowlist before it is placed in
  any command or hint (a hostile branch name is otherwise a shell
  injection). Pending → the user pushes BEFORE the deploy pause; the
  deploy brief says "after your push". `Push:` line in both reports.
- release-candidate STEP 6: two ahead counts + the verb; anything other
  than auto with both counts 0 prints one user command
  `! git push --atomic origin main develop v<X.Y.Z>` and stops; the tag
  gate stays for auto mode; `hold` notes --follow-tags; version regex.
- release-executor: push claims qualified (auto-push mode, best effort).
- tour: mode-agnostic rule; STEP 3 reads one `git -C <project>` fact per
  project (suffix-aware branch, --remotes=origin, origin probe) and the
  summary row says on origin / local only with the user command.
2026-10-07 14:02:51 +02:00
bchanot 5cf049d235 feat(gitflow): push-mode verb; /close reports the push state instead of pushing
Run C1 of manual-push mode (BDR-111/BDR-112).

- lib/gitflow.sh: `gitflow.sh push-mode` prints auto | manual | invalid
  (rc 0; an invalid value is named on stderr). It is the one reader a
  skill may call: the bare `git config … gitflow.*` read is denied to
  Claude since run B. Ignores GITFLOW_NO_PUSH by design (documented).
- skills/capitalize/SKILL.md STEP 5C: the explicit `git push origin
  develop` is gone — `finish` has pushed develop itself since BDR-095,
  mode-aware since run A. 5C is now three separate read-only calls
  (finish; push-mode; `git rev-list --count origin/develop..develop`)
  and prose outcomes keyed on the real ahead count: pushed / manual push
  mode, you push / not on origin / push FAILED / invalid value named,
  plus a finish-failure outcome (merge vs delete rc distinguished).
  STEP 6 closing lines and the recap carry every outcome; the
  `--no-push` line reads the branch's own ahead count ("this disk only"
  only when true). Invariant: no `git push` inside any Bash call; the
  user hints are prose.
- skills/close/SKILL.md, lib/gitflow-aiguillage.md: "push" claims
  qualified "in auto-push mode".
- lib/gitflow-test.sh T11b: six cases for the verb (default, true,
  false, non-boolean with stderr + rc 0, corrupt config, usage).

Polish items from the gates are listed in TODO.md (C1 polish).
2026-10-07 13:39:01 +02:00
bchanot 472168d432 docs(gitflow): push-guard — SETTINGS push discipline + guardrails table, gitflow skill, ARCHITECTURE, README, CHANGELOG 2026-10-07 12:42:15 +02:00
bchanot 4630b625f7 chore(memory): BDR-112 + LRN-194..196 + journal — feat manual-push-guard run B 2026-10-07 12:41:46 +02:00