Compare commits

..

1 Commits

Author SHA1 Message Date
torben b1883befc7 docs: Modellwahl nach Pruefbarkeit; stack-dev bricht an den Phasenwechseln fuer den Model-Switch (4.3.3)
CI / verify (push) Successful in 49s
Release / release (push) Successful in 36s
Files changed:
- CHANGES.md
- VERSION
- instructions/claude-code-model-selection.md
- instructions/dev/stack-dev/SKILL.md
2026-09-03 21:30:54 +02:00
4 changed files with 160 additions and 23 deletions
+57
View File
@@ -20,6 +20,63 @@ their date-only headings.
---
## 4.3.3 - 2026-09-03 - Modellwahl nach Pruefbarkeit statt nach Aufgabenname; stack-dev bricht an den Phasenwechseln fuer den Model-Switch
**Author:** Torben Nehmer
`instructions/claude-code-model-selection.md` routete bisher nach Skill: eine Zeile "Stack
development -> Opus/high" fuer alles, was `tools/`, `types/` oder `instructions/` anfasst. Das ist
zu grob in beide Richtungen - es verteuert die lange, mechanische Mitte einer Stack-Sitzung, und es
sagt nichts darueber, dass Anfang und Ende derselben Sitzung anders zu behandeln sind.
**Die neue Achse ist "was faengt hier einen Fehler ab".** Wo ein Check in Code steht - `pytest`,
`docs verify`, `instructions verify`, CI, die Gates - kostet der Fehler eines schwaecheren Modells
eine Runde und faellt auf. Wo die einzige Durchsetzung eine Sitzung ist, die Prosa liest, faellt
derselbe Fehler gar nicht auf: er wird ausgeliefert und bleibt stehen. Das ist dasselbe Argument,
das `docs/why-gates-are-code.md` fuer Gates fuehrt, angewandt auf die Modellwahl.
Stack-Entwicklung ist damit **nicht mehr eine Zeile, sondern drei**:
| Phase | Was einen Fehler faengt | Modell |
|---|---|---|
| Design, Versionsstelle, Grenzuebertritts-Urteil | nichts | Opus/high |
| Code, Tests, mechanische Doku-Synchronisation | pytest, CI, `docs verify` | Sonnet/high |
| Issue-Abschluss, `docs/`-Veralterung, Changelog-Prosa | nichts, per Konstruktion | Opus/high |
Die Mitte ist die lange Phase und die mit den Checks - dort liegt die Ersparnis. Die beiden
Raender sind kurz (Minuten, nicht Stunden), haben aber keinen maschinellen Waechter: `wikitool`
kennt den Issue-Tracker bewusst nicht, und eine `docs/`-Seite traegt keinen normativen Satz, also
gibt es dort nichts zu verifizieren. Sie oben zu lassen ist billig und schuetzt genau die Arbeit,
die still scheitert.
Zwei Praezisierungen dazu: **Effort ist der billigere Hebel als das Modell** - `medium` steht fuer
Stack-Arbeit bewusst in keiner Zeile, weil Mehrdatei-Konsistenz das ist, was ein reduzierter
Effort zuerst aufgibt; `high` ist die Untergrenze, sobald mehr als eine Datei oder ein Contract
betroffen ist. Und die Asymmetrie ist benannt: eine unnoetige Opus-Phase kostet einmal Geld, eine
ungepruefte Sonnet-Phase kann etwas ausliefern, das nie wieder jemand ansieht.
**Damit die Tabelle ueberhaupt wirksam wird, braucht sie Haltepunkte.** Eine Sitzung kann ihr
eigenes Modell nicht wechseln - das ist `/model` und gehoert dem Nutzer. Eine Empfehlung, die
niemand zum richtigen Zeitpunkt ausspricht, aendert nichts. `instructions/dev/stack-dev/SKILL.md`
bekommt deshalb zwei ausdrueckliche Breaks:
- **Neuer Schritt 3** - "Settle the design before building", mit dem Angebot zum Wechsel nach
unten, sobald der Plan steht und die Arbeit mechanisch wird. Einmal aussprechen, dann so oder
so weiterarbeiten.
- **Schritt 6 (Abschluss) bricht in die Gegenrichtung** - ab dort greift wieder kein Check. Mit
der ausdruecklichen Auflage, die Arbeit **unabhaengig von der Antwort** zu tun: nach dem Publish
auf einen Modellwechsel zu blockieren wuerde genau den Zustand hinterlassen, den Schritt 6
verhindern soll. Lief die Phase auf dem billigeren Modell, gehoert das in die Uebergabe statt
ins Schweigen.
Ein auftauchender Grenzuebertritt ist unter den Decision points ebenfalls als Anlass zum Wechsel
nach oben benannt: `docs verify` prueft, dass ein Uebertritt sich dokumentiert, nie dass die
Stelle richtig gewaehlt war.
Die uebrigen Schritte sind unveraendert und nur umnummeriert (alt 3-5 -> neu 4-6).
---
## 4.3.2 - 2026-09-03 - stack-dev: Issue-Abschluss ist ein nummerierter Schritt, kein Zeiger in einer Routing-Liste
**Author:** Torben Nehmer
+1 -1
View File
@@ -1 +1 @@
4.3.2
4.3.3
+60 -16
View File
@@ -6,10 +6,24 @@ description: Which Claude model and effort level to run a Claude Code session, a
# Pick the Claude model and effort level for the task at hand
Scale the model and effort to how much judgment the task actually needs. Running everything at
the most capable model and highest effort is safe but wasteful: the gates in [gates.md](gates.md)
are enforced in code, not by model judgment, so a weaker model cannot bypass them - it can only
do a worse job of the calls the gates don't cover.
Scale the model and effort to **what catches a mistake in this part of the work** - not to how
important the task feels, and not to its name. Running everything at the most capable model and
highest effort is safe but wasteful: the gates in [gates.md](gates.md) are enforced in code, not
by model judgment, so a weaker model cannot bypass them - it can only do a worse job of the calls
the gates don't cover.
That last clause is the whole rule, turned into a test. Where a check lives in code - `pytest`,
`docs verify`, `instructions verify`, CI, the gates - a weaker model's mistake surfaces and costs
one more round. Where the only enforcement is a session reading prose, the same mistake does not
surface at all: it ships, and it stays until someone happens to notice. The two are not the same
risk, and they should not get the same model. This is the argument
[docs/why-gates-are-code.md](../docs/why-gates-are-code.md) makes about gates, applied to who is
holding the keyboard.
Both directions cost something, which is why the axis matters rather than a blanket answer:
over-provisioning is a standing cost paid every session, while under-provisioning in an unchecked
phase is a silent error with a long tail. A corrective session, its bump, its CI runs and its
release together cost more compute than the model difference they were saving.
Claude-Code-only, and imported by CLAUDE.md rather than linked from AGENTS.md: the model names,
the `/code-review` effort dial and the `Agent` tool's `model:` override have no equivalent in the
@@ -28,17 +42,41 @@ to *make*, not a setting to apply.
## Steps
1. **Recommend the session's model and effort by the skill in use**, when asked or when the
mismatch is worth one sentence. Say it once and continue working either way - a session that
argues about its own model instead of doing the task has already cost more than the model
difference:
1. **Recommend the session's model and effort by what catches a mistake in the phase it is in**,
when asked or when the mismatch is worth one sentence. Say it once and continue working either
way - a session that argues about its own model instead of doing the task has already cost
more than the model difference:
| Skill / task | Model | Effort |
|---|---|---|
| `wiki-status`, simple `wiki-query` lookups | Sonnet | default |
| `wiki-lint` | Sonnet | default |
| `wiki-ingest`, `wiki-manage`, judgment-heavy `wiki-query` | Sonnet | high |
| Stack development: `tools/`, `types/`, `instructions/` as code | Opus | high |
| Phase / task | What catches a mistake here | Model | Effort |
|---|---|---|---|
| `wiki-status`, simple `wiki-query` lookups | the answer is re-checkable against the corpus | Sonnet | default |
| `wiki-lint` | `lint` itself is the check | Sonnet | default |
| `wiki-ingest`, `wiki-manage`, judgment-heavy `wiki-query` | `lint` and `docs verify`, partly - the judgment about a claim is not covered | Sonnet | high |
| Stack dev: design, the version part, a boundary-crossing judgment | nothing - `docs verify` checks that a crossing documents itself, never that the part was right | Opus | high |
| Stack dev: code, tests, mechanical doc sync (command tables, contract rows) | `pytest`, `docs verify`, `instructions verify`, CI | Sonnet | high |
| Stack dev: closing an issue, `docs/` staleness, changelog prose | nothing, by construction - see below | Opus | high |
**Stack development is not one row**, which is the point of splitting it. The middle phase is
where the tokens are and where the checks are, so it is the phase worth running cheaper. The
two around it have no mechanical guard at all - a `docs/` page carries no normative sentence,
so there is nothing for `docs verify` to check ([AGENTS.md](../AGENTS.md) § File naming), and
the same holds for whatever tracker an instance keeps its open work in, which `wikitool`
deliberately knows nothing about. Those two phases are short - minutes, not hours - so keeping
them on the stronger model is cheap, and it protects the only work in the session that fails
silently.
**Effort is the cheaper lever than the model.** Reach for it first: `medium` deliberately does
not appear in this table for stack work, because multi-file consistency is exactly what a
reduced effort level gives up. Sonnet at `high` is the floor for anything touching more than
one file or a contract; `default` is for a single-file mechanical edit with a test behind it.
**A session cannot switch its own model**, so these rows only become real if someone offers the
switch at the moment the phase changes - once, without arguing about it, and never as a reason
to stop work that is already underway.
<!-- dist:strip-start -->
In this repo those moments are named: the `stack-dev` skill breaks for them at its steps 3
(design settled, work turns mechanical) and 6 (publish done, the unchecked tail begins).
<!-- dist:strip-end -->
2. **Pick a spawned subagent's model by what it does**, via the `Agent` tool's `model:`
parameter - the values are `haiku`, `sonnet`, `opus`, `fable`:
@@ -66,8 +104,14 @@ to *make*, not a setting to apply.
mechanical one - `wikitool` carries the mechanical part regardless of which model is
supervising it.
- **Unsure which row applies?** Default to Sonnet at high effort, not the most capable model at
the highest effort. Under-provisioning costs one worse answer in one session; reflexively
over-provisioning is a standing cost paid every session.
the highest effort. Under-provisioning *where a check exists* costs one worse answer in one
session; reflexively over-provisioning is a standing cost paid every session.
- **Unsure whether the phase is checked?** Treat it as unchecked. The asymmetry is not symmetric:
a needless Opus phase costs money once, an unchecked Sonnet phase can ship something nobody
looks at again.
- **Mid-session and the phase changed, but nobody switched?** Do the work anyway - never block a
publish or an issue close on a model the session cannot change itself. Say which phase ran on
which model in the handover, so the gap is visible rather than silent.
## Scope
+42 -6
View File
@@ -46,7 +46,7 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li
package, labelled `area/`, `kind/`, `prio/` and `size/`. There is no `TODO.md`. **The body
of the issue you are working on is this session's plan file:** keep it current as the state
moves, so an interrupted session leaves a body the next one can resume from, *and* rewrite it
to its final state before closing. Both halves bind; the second is step 5 below. Read it
to its final state before closing. Both halves bind; the second is step 6 below. Read it
before filing something for later, before editing or closing an issue, or before deciding
what to pick up next.
[testing-conventions.md](../testing-conventions.md) - the suite runs against a deliberately
@@ -54,14 +54,35 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li
establish itself. Read it before adding or changing a test.
[version-parts.md](../version-parts.md) - which part a change bumps: the drop-in test, the
catalogue of breaks that cross the compatibility boundary with `kb/` untouched, and what to
put in front of the user before a breaking bump. Read it before step 3.
put in front of the user before a breaking bump. Read it before step 4.
[corpus-policy.md](../corpus-policy.md) - what "curated enough" means for the shared
demo/testbed `kb/`, the measurable floors that define it, and what a reactive fix may and may
not do to corpus content. Read it before judging whether the corpus can exercise a change, or
before any fix that would touch `kb/` content.
More instructions are added here incrementally as stack-development needs come up - this
list grows without needing this skill file to change shape.
3. **Raise the version, if the change ships.** A change under `tools/`, `types/`,
3. **Settle the design before building - and break there for the model switch.** These are two
different kinds of work, and the split is not stylistic: design, the version part and any
boundary judgment have **no** mechanical guard, while the code and tests that follow have
`pytest`, `docs verify`, `instructions verify` and CI behind them.
So when the design is settled - the issue body says what will be built, the open questions are
answered - stop and say so, in one sentence:
> Der Plan steht, ab hier ist die Arbeit mechanisch und durch Tests/CI abgedeckt. Wenn du auf
> Opus bist, ist jetzt der Moment für `/model sonnet` bei Effort `high`.
**You cannot make this switch yourself** - the session's model is the user's `/model`, not a
setting an agent applies. Offer it once and keep working either way; a session that argues
about its own model has already cost more than the difference. If the design turns out not to
be settled after all - a boundary crossing surfaces, an assumption breaks - that is a reason to
offer the switch back up, not to decide it alone.
Effort is the cheaper lever than the model, and `high` is the floor for anything touching more
than one file or a contract. Full table and reasoning:
[claude-code-model-selection.md](../../claude-code-model-selection.md).
4. **Raise the version, if the change ships.** A change under `tools/`, `types/`,
`instructions/`, `AGENTS.md` or a `CONTRACT.md` reaches every future instance, so it needs a
version and a changelog entry:
@@ -98,18 +119,30 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li
Prose-only changes (`README.md`, `INSTALL.md`, `EVALS.md`) and the workflows under `.gitea/`
do not need a bump - CI's version gate is scoped to what changes behaviour.
4. **Verify before publishing.** `tools/wikitool docs verify`, `tools/wikitool instructions
5. **Verify before publishing.** `tools/wikitool docs verify`, `tools/wikitool instructions
verify`, and the relevant `pytest` run in `tools/` - the same checks any stack change must
pass, run explicitly rather than assumed. CI (`.gitea/workflows/ci.yml`) runs these plus a
full `setup-instance.md` replay against a fresh `dist export`; a push to `main` that moves
`VERSION` additionally triggers a tagged release. **CI does the tagging** - a session never
creates a tag, which is what keeps AGENTS.md invariant 5 intact.
5. **Close the issue with a body rewrite, not a comment.** The last act of a session that
6. **Close the issue with a body rewrite, not a comment.** The last act of a session that
finished a work package, and the one most easily skipped: by here the change is published and
the issue feels done. It is not. The body is the version everyone reads afterwards and nobody
revisits, so it is the one place the debt comes due at the worst moment.
**Break here too, in the other direction.** Everything left in the session - this rewrite,
whether a `docs/` page's reasoning went stale, the changelog prose - is the unchecked kind of
work again, the mirror of step 3. If the session dropped to Sonnet there, say so now:
> Ab hier greift kein maschineller Check mehr - Issue-Body, `docs/`-Veralterung und
> Changelog-Prosa prüft nichts. Wenn du zurück auf Opus willst, ist jetzt der Moment.
Then **do the work regardless of the answer.** Never block a close on a model switch: the
change is already published, and a session that stops here leaves exactly the state this step
exists to prevent. If it ran on the cheaper model, name that in the handover rather than
leaving it silent.
Rewrite it to its final state *first*, then close. The test is what a reader who opens the
closed issue tomorrow would conclude:
@@ -138,7 +171,10 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li
user decides whether it is worth that: show them what breaks, what an instance has to do about
it, and the alternatives (avoid the break with a shim, defer and batch it with the next one,
or split it behind a deprecation window), then recommend one and wait for a go-ahead.
[version-parts.md](../version-parts.md) step 4 has the full shape.
[version-parts.md](../version-parts.md) step 4 has the full shape. A surfacing boundary crossing
is also a reason to offer the model switch back up (step 3): the judgment it needs has no
mechanical guard, and `docs verify` only checks that a crossing documents itself, never that the
part was chosen correctly.
## Scope