Files
claude/.claude/tasks/contracts/2026-10-11-model-router-w3c-forget-1457.md
T

5.5 KiB

CONTRACT — model-router-w3c-forget

  • date: 2026-10-11 | flow: feat | branch: feature/model-router-confirm (continues W3-A/B before their merge)
  • status: active

REQUEST (verbatim — IMMUTABLE)

d'ailleurs est-ce quil y a une comande pour clear les decision prise ? si jamais cest un user aure que moi si il peut clean me decisions de routage ? [orchestrator proposal: /route forget <nom|all|projects> + an optional per-user decisions file] → "seulement le forget"

CLARIFICATIONS

Q: scope / A: /route forget only; no per-user decisions file (the tracked routing.json stays the shared memory; another user inherits and may forget) [gated 2026-10-11] Q: public shape (orchestrator default, user may veto): /route forget <name> (a skill row, an agent row or a phase), /route forget all, /route forget projects; forgetting a changed row RESTORES it to its shipped phase (changed.from); the frontmatter floors are never touched (the answer says so when a changed row is restored) [stated 2026-10-11]

Q: GATE 1 cap (verifier ECARTS(2) incl. one real defect ForgetPlan → Plan, then ECARTS(2)/(2) coverage only; 284 kit tests) / A: user "Accepter et commiter"; security PASS (1 MEDIUM + 4 LOW parked in TODO); live T3 Keeps on orchestrate and escalate seen during the run [gated 2026-10-11]

ACCEPTANCE CRITERIA

  1. /route forget <name> (composer only, exactly one argument): for every kind (skills, agents, phases) removes confirmed.<kind>.<name>; restores a changed row to its from only when from is a string, the row exists, equals changed.to and from is a known phase (else the entry is kept and the answer says why); removes every projects[*].<kind>.<name> (emptied tables pruned); drops the key(s) from this session's asked set; nothing removed and nothing asked → "nothing to forget for " with NO write; key only asked this session → reset, no write; refused while a dialog is open; two words → usage. One kit test per clause (folded where one setup proves two).

  2. /route forget all and /route forget projects ASK FIRST (engine dialog, options Cancel / Forget, Cancel first; anything else, dismissed or headless = cancelled, nothing written; skipped when there is nothing to forget; the forget holds the single-dialog slot while asking): all empties confirmed, changed (rows restored under the same guards) and projects and clears the asked set; projects empties only projects. One kit test per clause.

  3. Writes go through the existing writer only (writeRouting: serialized, size-capped, refused when the file is absent or unparsable with the existing toast, config rebuilt after the write); the model (route tool, prompt rules, sub-agents) can never trigger a forget; a non-composer origin is refused like the other /route writes. Judged by reading + one kit test (route tool cannot forget) + the existing origin test extended.

  4. One answer formatter: "forgot : confirmed, row(s) restored, project exception(s) removed"; a restored row adds "(. → : at ; if <agents/.md | skills//SKILL.md> was aligned to , set model: , effort: and its lock in lib/tests/model-routing.test.sh, then make test)" (no file clause for a built-in agent: Explore, Plan); "; ~/.claude/model-router.json still sets and wins here" when the machine override pins it; "; current run may keep : /route clear to apply" when the run slot came from a restored skill row [wording per plan r3, gated 2026-10-11]; write outcomes: refused → "nothing saved", rebuild failure after a landed write → "saved, config not rebuilt: /route reload". Write outcomes: refused → "nothing saved", rebuild failure after a landed write (dedicated error) → "saved, config not rebuilt: /route reload", any other failure → "forget not applied". One kit test per text.

  5. lib/effort-shift.md names /route forget in ≤ 2 changed lines; README.md, USAGE.md and CHANGELOG.md no longer claim that only a dialog answer or /route ask writes routing.json (one clause each naming /route forget); the register.ts writer comment says the same; /route pending lists a forgotten key again. CHECK: grep -q 'forget <name|all|projects>' mods/model-router/hooks/register.ts && grep -q '/route forget' lib/effort-shift.md && [ "$(wc -l < lib/effort-shift.md)" -le 66 ] && grep -q 'route forget' README.md && grep -q 'route forget' USAGE.md && grep -q 'route forget' CHANGELOG.md && ! grep -q 'Only a dialog answer or /route ask on|off writes' README.md && echo W3C-DOC EXPECT: W3C-DOC EVIDENCE: MET exit=0 marker-found :: W3C-DOC

  6. Kit suite, mods suite and validate green; the census stays green on the shipped file. CHECK: cd mods/model-router && out="$(claude plugin test . 2>&1)" && printf '%s\n' "$out" | grep -qE '[0-9]+ pass' && ! printf '%s\n' "$out" | grep -qE '[1-9][0-9]* fail' && claude plugin validate . 2>&1 | grep -q 'passed' && cd ../.. && make test suite=lib/tests/mods.test.sh 2>&1 | grep -q 'all suites green' && bash lib/tests/effort-routing.test.sh >/dev/null 2>&1 && echo W3C-GREEN EXPECT: W3C-GREEN EVIDENCE: MET exit=0 marker-found :: W3C-GREEN

  7. Live smoke (orchestrator + user, after the gates, recorded [gated]): one /route forget typed in the terminal opens its dialog ($.ui.ask from an immediate command) and the answer lands in routing.json.

FILE SCOPE

mods/model-router/hooks/register.ts, mods/model-router/hooks/register.test.ts, lib/effort-shift.md, README.md (one clause), USAGE.md (one clause), CHANGELOG.md (one clause under Unreleased)