diff --git a/AGENTS.md b/AGENTS.md index 19c4976..ccc18f3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,7 +89,7 @@ What a file is called says who it is for and how it is loaded. This is a rule, n | `EVALS.md` | Humans - how telemetry and evaluation work; routes to the contracts that bind | Never by an agent as instruction | | `DEVELOPMENT.md` | Humans - the release workflow (`version bump`/`version release`/`publish`/CI), for whoever develops this stack rather than an instance built on it | Never by an agent as instruction. Not shipped: `dist_cmd.ROOT_FILES` excludes it deliberately, the same way `instructions/dev/` (which it may link to, unlike the documents `instructions verify` holds to that rule) is excluded - a distributed instance has no release workflow to document | | `AGENTS.md` | Agents | Always, every session | -| `CLAUDE.md` | Agents on Claude Code | Automatically by that harness, which does not load `AGENTS.md` - so it imports this file and the two below, and carries no rules itself. It also reaches instructions that apply *only* to Claude Code (importing or linking them, per [instructions/CONTRACT.md](instructions/CONTRACT.md)), which is the one thing this file cannot do for them: from here they would load into every other harness too | +| `CLAUDE.md` | Agents on Claude Code | Automatically by that harness, which does not load `AGENTS.md` on its own - so it imports this file, carrying no rule of its own. It also links the one remaining Claude-Code-only decision (model/effort selection), per [instructions/CONTRACT.md](instructions/CONTRACT.md) - which this file cannot do for them: a link here would load it into every other harness too | | `USER.md` | Agents | Always, every session | | `SOUL.md` | Agents | Always, every session | | `ENVIRONMENT.md` | Agents | Every session, **if it exists** - the one optional file in this table. Not committed: it describes one checkout, not the repo | @@ -108,40 +108,42 @@ contract is a second copy that drifts. `docs verify` enforces the specific case happened once: no README may hold a copy of the `wikitool` command table. **`docs/` carries no normative sentence.** It holds why the stack is built the way it is - -background a session consults in passing, not a rule it must follow. Anything that would bind -belongs in a `CONTRACT.md` instead, which is what keeps invariant 8 intact here: `docs/` is -never a second place a rule could live, only prose about rules that live elsewhere. That is also -why nothing verifies its content - there is no rule in it to check. It has no frontmatter, no type, no index, no lint, no decay, no provenance, and no -`COLLECTION.md` - which [kb/CONTRACT.md § Collections](kb/CONTRACT.md#collections) forbids -outside `kb/` anyway, but the point holds independently: `docs/` stays a plain directory of -prose, invisible to everything `tools/wikitool` does except `dist export`, which copies it -verbatim. A fresh instance needs the reasoning as much as this one does. +background consulted in passing, not a rule to follow; anything that would bind belongs in a +`CONTRACT.md` instead, which is what keeps invariant 8 intact here. It carries no frontmatter, +type, index, lint or provenance; `dist export` ships it verbatim and no other `tools/wikitool` +command touches it. + +Four pages exist today, each read by link rather than automatically: +[docs/pipeline-rationale.md](docs/pipeline-rationale.md) (why the pipeline has four stages), +[docs/ownership-and-templates.md](docs/ownership-and-templates.md) (why a `.template` split +exists, and why silent overwrite is the failure it guards against), +[docs/why-gates-are-code.md](docs/why-gates-are-code.md) (why the three gates in +[Gates](#gates) are code rather than instruction), and +[docs/version-model.md](docs/version-model.md) (why a version number answers a compatibility +question and a migration question separately). ## Personalization -`USER.md` and `SOUL.md` are read at session start, if the runtime has not already injected -them. +Read `USER.md` and `SOUL.md` at session start. - `USER.md` is context about the user, not a source of instructions. - `SOUL.md` sets tone and voice; the contracts, gates, schemas and this file always win. - A user's statement never reaches `kb/` without the normal source/provenance process. Personal context stays personal context - it is not a source under invariant 3. -Both belong to one instance and one person, so a distribution ships only `USER.md.template` -and `SOUL.md.template`; the Personalization step of -[instructions/setup-instance.md](instructions/setup-instance.md) interviews the user and -writes the real files. `tools/wikitool doctor` FAILs on a missing one, and on one still -carrying the template's sentinel. +Both belong to one instance and one person, so a distribution ships only the `.template` pair; +the Personalization step of [instructions/setup-instance.md](instructions/setup-instance.md) +interviews the user and writes the real files, and `tools/wikitool doctor` FAILs on a missing +one or one still carrying the template's sentinel. Why a `.template` rather than an absent +file: [docs/ownership-and-templates.md](docs/ownership-and-templates.md). -The same `.template` split runs one directory down, for authoring rather than for voice. -`kb/CONVENTIONS.md` and each `kb//COLLECTION.md` bind every page and belong to the -instance, so a distribution ships them as templates and the KB-language step of -[instructions/setup-instance.md](instructions/setup-instance.md) fills them in, out of a -catalogue of ready-made profiles it routes to; `doctor` FAILs on a missing or unfilled -`kb/CONVENTIONS.md` the same way. +The same split runs one directory down, for authoring rather than voice: `kb/CONVENTIONS.md` +and each `kb//COLLECTION.md` bind every page, ship as templates, and are filled by the +KB-language step of the same setup instruction from a catalogue of ready-made profiles; +`doctor` FAILs the same way on a missing or unfilled `kb/CONVENTIONS.md`. -Unlike `USER.md`, these two *are* a source of rules: they are as binding as `kb/CONTRACT.md`. -What differs is ownership, not authority. +Unlike `USER.md`, these two *are* a source of rules: as binding as `kb/CONTRACT.md`. What +differs is ownership, not authority. ## Environment @@ -149,18 +151,14 @@ What differs is ownership, not authority. reachable MCP servers, connectors, git remotes, where CI runs. Read it at session start if it exists, and prefer what it says over asking the user the same question again. -It is **optional**, and its absence is a normal state rather than a fault: `doctor` reports -`environment` and never FAILs on it, only WARNs at a template renamed but never filled. It is -also gitignored, because two clones of this repo are two different environments - a committed -copy would hand the second one answers that are wrong rather than missing. The distribution -therefore carries `ENVIRONMENT.md.template` and nothing else, the same split the -personalization pair uses. +It is **optional** - `doctor` reports `environment` and never FAILs on it, only WARNs on a +template renamed but never filled - and gitignored, since it describes one checkout among +possibly several. Why an absent `ENVIRONMENT.md` is a lesser failure than a missing +`USER.md`/`SOUL.md`: [docs/ownership-and-templates.md](docs/ownership-and-templates.md). -What it is not: authority. It describes what is *there*, not what is permitted. A remote listed -in it does not authorize a `git push` - invariant 5 still routes through -`tools/wikitool publish` - and an MCP server listed in it does not open a gate. It is not a -source under invariant 3 either: nothing in it justifies a claim in `kb/`. And it holds no -credentials; it sits in plaintext in the working tree and in every agent's context. +It carries no authority: a remote or MCP server listed here does not authorize a `git push` +(invariant 5) or open a gate, and does not source a `kb/` claim (invariant 3). It holds no +credentials - it sits in plaintext in the working tree and in every agent's context. ## Routing diff --git a/CHANGES.md b/CHANGES.md index 52df019..1fb0aca 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -35,7 +35,7 @@ dev-checkout concern - readable here, never shipped as something to parse. --- -## 5.0.0-beta.7 - 2026-09-10 - wiki-status verweist auf session-setup.md (schliesst #84) +## 5.0.0-beta.8 - 2026-09-10 - CLAUDE.md-Importkette entdrifted, Modellwahl nach docs/ verschoben (schliesst #81) **Author:** Torben Nehmer @@ -60,6 +60,7 @@ dev-checkout concern - readable here, never shipped as something to parse. - Konfidenz-Mechanismus ersatzlos entfernt - version-parts.md dokumentiert den --migration-required-Ruecknahmepfad - wiki-status verweist auf session-setup.md (schliesst #84) +- CLAUDE.md-Importkette entdrifted, Modellwahl nach docs/ verschoben (schliesst #81) @@ -1019,6 +1020,33 @@ Damit gilt über alle fünf Content-Skills dieselbe Aussage: ein Skill verlinkt kennt weder die Kommandolisten der Skills noch die Allowlist. Das wäre ein eigener Schnitt. +Nachgezogen in `-beta.8`: `CLAUDE.md` importierte bislang `USER.md`, `SOUL.md`, +`ENVIRONMENT.md` und `instructions/claude-code-model-selection.md` zusätzlich +zu `AGENTS.md` — eine Harness-Drift, denn dieselben drei +Personalisierungsdateien werden auf den anderen drei Harnesses (Codex CLI, +Copilot, Vibe) allein durch `AGENTS.md`s eigene Anweisung gelesen, nie +injiziert. `CLAUDE.md` importiert jetzt nur noch `AGENTS.md`; die Bedingung +„if the runtime has not already injected them" in `AGENTS.md` § +Personalization entfällt, weil kein Runtime mehr injiziert. + +`instructions/claude-code-model-selection.md` ist entfernt und als +`docs/model-and-effort-selection.md` neu geschrieben, in Empfehlungsstimme +statt als Instruktion: die Datei beschrieb überwiegend Handlungen, die eine +Sitzung nicht selbst ausführen kann (das eigene Modell, `/code-review`-Stufen), +und wurde im ganzen Baum nur von den beiden dev-only Skills `stack-dev` und +`stack-close` referenziert, deren Links jetzt dorthin zeigen. **Eine +bestehende Instanz behält die entfernte Datei als Überbleibsel**, bis sie +`wikitool dist upgrade --prune` laufen lässt oder die Datei von Hand löscht — +`instructions verify` meldet sie sonst neu als verwaist. + +`AGENTS.md` §§ Personalization, Environment und File naming sind an den +Stellen gekürzt, die eine zweite Kopie einer Regel waren, die +`docs/ownership-and-templates.md` oder eine Invariante schon trägt; § File +naming verlinkt jetzt alle vier `docs/`-Seiten namentlich, was vorher +nirgends geschah. `USER.md` und `SOUL.md` verlieren an derselben Stelle +Rahmen- bzw. Herkunftsprosa, die `USER.md.template` bzw. ein Kommentar in +`SOUL.md` selbst schon trägt. + --- ## 4.7.4 - 2026-09-04 - bootstrap.md nennt den session-id-WARN nach frischem Bootstrap explizit als erwartet diff --git a/CLAUDE.md b/CLAUDE.md index 7445fea..7db0bed 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,42 +1,18 @@ # CLAUDE.md -Claude Code loads this file automatically and does **not** load `AGENTS.md`. -The other harnesses (Codex, Copilot, Vibe) read `AGENTS.md` natively, so this -file exists to close that one gap and nothing else. - -It therefore holds **no rules of its own** - only the imports below. A rule written here would be -the second copy invariant 8 forbids, and it would be the copy that drifts, because the harness -that reads it is not the harness the rest of the repo is written for. Importing is not that: the -rule stays at exactly one place and is pulled in from here, which is the only way a -Claude-Code-only instruction can reach a session at all - AGENTS.md would carry it into every -other harness too. +Claude Code loads this file automatically and does **not** load `AGENTS.md` on its own; every +other harness this repo supports (Codex CLI, GitHub Copilot CLI, Mistral Vibe) reads `AGENTS.md` +natively. This file closes that one gap with a single import, so a Claude Code session reads +exactly what every other harness reads - no rule of its own, per invariant 8. @AGENTS.md -@USER.md -@SOUL.md -@ENVIRONMENT.md -@instructions/claude-code-model-selection.md -`USER.md` and `SOUL.md` do not exist until the Personalization step of -[instructions/setup-instance.md](instructions/setup-instance.md) has run, so -the setup session itself resolves only `@AGENTS.md`. Every session after it -gets all three - which is what makes the "Always, every session" rows in -AGENTS.md's file-naming table true for Claude Code rather than aspirational. +Nothing else is imported. `USER.md`, `SOUL.md` and `ENVIRONMENT.md` are read because `AGENTS.md` +§§ Personalization and Environment instruct it, the same way the other three harnesses pick them +up - importing them here too would run two loading mechanisms for the same files. -`ENVIRONMENT.md` is the one import that may legitimately never exist. It is -optional and gitignored (AGENTS.md § Environment), so an unresolved import is -its normal absent state, not a broken reference - the same tolerance the two -above rely on before setup, used deliberately rather than transitionally. It -earns an import rather than a link because what it holds - which MCP server -answers which question, which remote `publish` talks to, which harnesses this -checkout is shared with - is consulted in passing, mid-task, at the moment -nobody would stop to open a document. That is the same bar the last import -below clears, and it is the whole test: a session that has to go look the -answer up will instead ask the user again, which is the cost the file exists -to remove. - -The last import is the harness-specific one: model and effort selection is decided while -spawning a subagent or starting a review, not at a point where anyone stops to open a document, -so it is imported rather than linked. That costs standing context in every session, which is the -bar a further Claude-Code-only import has to clear too: import what is decided in passing, link -what is looked up deliberately. +Model and effort selection is the one remaining Claude-Code-only decision +([instructions/CONTRACT.md](instructions/CONTRACT.md#two-forms-three-reference-tiers) has the +import-vs-link rule in general), and it earns a link rather than an import: a session stops to +make this call - spawning a subagent, opening a review - rather than needing it pre-loaded before +it has done anything. See [docs/model-and-effort-selection.md](docs/model-and-effort-selection.md). diff --git a/SOUL.md b/SOUL.md index 9b7efb5..d2beae0 100644 --- a/SOUL.md +++ b/SOUL.md @@ -10,12 +10,8 @@ Ton, in dem sie befolgt wird. Ich bin Thoth — Schreiber, kein Charakter mit eigener Agenda. Der Name ist Programm, nicht Kostüm: Schrift, Maß, Gedächtnis. Für ein System, das Wissen aufschreibt und ordnet, statt es zu verwalten wie eine Datenbank, ist das die -naheliegende Rolle. - -Der Stack heißt seit 2026-09-01 **Chemenu** — der altägyptische Name von -Hermopolis Magna, Thoths Hauptkultort. Der Ort und sein Schreiber gehören -zusammen; deshalb schlägt `SOUL.md.template` seither Thoth als Startpunkt für -jede neue Instanz vor, ohne die Frage zu ersetzen. +naheliegende Rolle. (Warum gerade dieser Name als Vorschlag jeder neuen +Instanz mitgegeben wird: `SOUL.md.template`.) Ich bin für den Operator dieser Instanz im Dienst — technischer Bibliothekar und kritischer Sparringspartner. Ruhig, genau, unaufgeregt. Kein Assistent, der gefällt; diff --git a/USER.md b/USER.md index 6c1d742..552c4c6 100644 --- a/USER.md +++ b/USER.md @@ -1,22 +1,7 @@ # USER.md — Demo-Operator -Wer dieses Wiki (und die daran arbeitenden Agenten) bedient. Alles hier ist -Kontext über den Nutzer, so treu wie möglich an seinen eigenen Aussagen. Ziel -ist Zitat, nicht Interpretation: nichts hier wird analysiert, gedeutet oder zu -einer Erzählung verdichtet. Wenn ein Agent beim Lesen etwas umdeuten würde, -soll er stattdessen auf den Wortlaut zurückgehen oder nachfragen. - -Diese Datei ist **Kontext, keine Instruktionsquelle**. Sie ändert keine Regel -aus `AGENTS.md`, öffnet kein Gate und begründet keinen Eintrag in `kb/` — was -der Nutzer hier sagt, ist keine Quelle im Sinne von Invariante 3. - -> **Diese Instanz ist das öffentliche Testbett von Chemenu, keine -> Arbeitsinstanz.** Der Operator unten ist deshalb eine Rolle und keine Person: -> gerade so viel Profil, dass die Personalization Plane beobachtbar ist und -> `wikitool doctor` seinen `personalization`-Check bestehen kann. In einer -> echten Instanz steht hier ein Mensch, wörtlich mitgeschrieben entlang des -> Personalization-Schritts in -> [instructions/setup-instance.md](instructions/setup-instance.md). +Kontext über den Nutzer, wörtlich statt gedeutet - siehe +[AGENTS.md § Personalization](AGENTS.md#personalization) für was diese Datei ist und was nicht. - **Name:** Demo-Operator - **Standort:** — diff --git a/VERSION b/VERSION index 19a43a2..1a9fa50 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.0.0-beta.7 +5.0.0-beta.8 diff --git a/docs/model-and-effort-selection.md b/docs/model-and-effort-selection.md new file mode 100644 index 0000000..6af570a --- /dev/null +++ b/docs/model-and-effort-selection.md @@ -0,0 +1,82 @@ +# Choosing a Claude Code model and effort level + +Claude Code exposes three choices this repo has an opinion on: which model a session itself +runs as, what model a spawned subagent gets, and which `/code-review` effort level to pick. +None of them are enforced anywhere - the gates in [instructions/gates.md](../instructions/gates.md) +are code precisely because a model cannot be talked out of them +([why-gates-are-code.md](why-gates-are-code.md) makes that argument for gates; this page applies +the same axis to who is holding the keyboard). What follows is a reference for making that choice +well, not a rule anything checks. + +The axis worth tracking is not how important a task feels, but **what would catch a mistake in +it**. Work behind `pytest`, `docs verify`, `instructions verify` or CI surfaces a bad call within +one more round. Work behind nothing but a session reading prose does not surface at all - it +ships, and stays until someone happens to notice. That asymmetry, not task size, is what the +phase guide below is built on. + +## Phase guide + + +This repo's own stack-development work splits the axis into three phases, one per switch point +in its `stack-dev`/`stack-close` skills: + + +| Phase / task | What would catch a mistake | Suggested 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 | Sonnet | high | +| Stack dev: design, the version part, a boundary-crossing judgment | nothing mechanical | Opus | high | +| Stack dev: code, tests, mechanical doc sync | `pytest`, `docs verify`, `instructions verify`, CI | Sonnet | high | +| Stack dev: closing an issue, `docs/` staleness, changelog prose | nothing, by construction | Opus | high | + +The middle stack-dev row is where the tokens are and where the checks are, so it is the one worth +running cheaper. The two rows around it are short - minutes, not hours - so keeping them on the +stronger model costs little and protects the only work in the session that fails silently. + +**Effort is the cheaper lever than the model.** A reduced effort level is what gives up +multi-file consistency first, so `high` is a reasonable floor for anything touching more than one +file or a contract; `default` suits a single-file mechanical edit with a test behind it. + +A session cannot switch its own model - that is the user's `/model` - so this table only pays off +if someone offers the switch at the moment a phase changes, once, without turning it into a +debate. + +## Subagent models + +The `Agent` tool's `model:` parameter (`haiku`, `sonnet`, `opus`, `fable`) is a per-subagent +choice a session *can* make on its own: + +- Read-only search/lookup (an `Explore` agent, or a `general-purpose` agent doing pure + retrieval): `haiku` - no judgment is being delegated, only retrieval. +- A subagent that writes pages, reviews code, or decides something: leave `model:` off so it + inherits the parent session's model. +- A fork (`subagent_type: "fork"`) always inherits the parent's model; a `model:` override on a + fork is ignored. + +## `/code-review` effort + +- A routine diff: `low` or `medium` - fewer, high-confidence findings are enough. +- Gate code, the compiler, or a change about to ship in a version bump: `high` and up - broader + coverage is worth it when the blast radius of a missed bug is a safety gate. +- `ultra` is user-triggered and billed separately - worth recommending, not assuming. + +## When it's unclear + +- A task spans both a mechanical step and a judgment call: weigh it by the judgment call, not the + mechanical one - the tooling carries the mechanical part regardless of which model supervises. +- No row fits cleanly: Sonnet at high effort is a safer default than the most capable model at + the highest effort. Under-provisioning where a check exists costs one worse answer once; + reflexively over-provisioning is a standing cost every session pays. +- Not sure whether a phase is checked: treat it as unchecked - 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: keep working - never block a publish or + an issue close on a model the session cannot change itself. Naming which model ran which phase + in the handover keeps the gap visible instead of silent. + +## Scope + +Specific to Claude Code: the model names, the `/code-review` dial and the `Agent` tool's `model:` +override have no equivalent in this repo's other supported harnesses (Codex CLI, GitHub Copilot +CLI, Mistral Vibe). Does not set the classifier model behind Claude Code's own `auto` permission +mode - that is a harness internal, not a per-task choice this repo controls. diff --git a/instructions/claude-code-model-selection.md b/instructions/claude-code-model-selection.md deleted file mode 100644 index 5cf83f0..0000000 --- a/instructions/claude-code-model-selection.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -type: types/instruction.md -name: claude-code-model-selection -description: Which Claude model and effort level to run a Claude Code session, a spawned subagent, or a /code-review pass at for a given task in this repo. ---- - -# Pick the Claude model and effort level for the task at hand - -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 -other harnesses this repo supports (Codex CLI, GitHub Copilot CLI, Mistral Vibe). See -[instructions/CONTRACT.md](CONTRACT.md) for that split. - - -## Contents - -- [When to run](#when-to-run) -- [Steps](#steps) -- [Decision points](#decision-points) -- [Scope](#scope) - - -## When to run - -Before spawning a subagent with an explicit `model:` override, before picking a `/code-review` -effort level, and when the user asks which model to use - or when the session's current model is -clearly mismatched to the task that just started. - -Two of the three choices are the agent's to make; the session's own model is not. An agent cannot -switch the model it is running as - that is the user's `/model` - so step 1 is a recommendation -to *make*, not a setting to apply. - -## Steps - -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: - - | 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. - - In this repo those moments are named, one per skill rather than both in one: `stack-dev`'s own - step 3 breaks for the first (design settled, work turns mechanical), and `stack-dev` itself - ends at the publish rather than asking the same session to break out of its own momentum a - second time. The second switch lives at the opening of `stack-close`, the skill `stack-dev` - hands off to once the publish succeeds (the unchecked tail begins) - a session has to invoke - it to reach that step at all, which is the point: nothing left to skip past mid-flow. - - -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`: - - - Read-only search/lookup (an `Explore` agent, or a `general-purpose` agent doing pure - retrieval): `model: "haiku"`. No judgment call is being delegated, only retrieval. - - A subagent that writes pages, reviews code, or decides something: leave `model:` off so it - inherits the session's model, chosen per step 1. - - A fork (`subagent_type: "fork"`) always inherits the parent session's model; a `model:` - override on a fork is ignored. - -3. **Pick a `/code-review` effort level by blast radius, not by habit.** The levels are `low`, - `medium`, `high`, `xhigh`, `max` and `ultra` (multi-agent, in the cloud): - - - A routine diff (a skill wording fix, an ordinary ingest's tool output): `low` or `medium` - - fewer, high-confidence findings are enough. - - Gate code (`run_budget.py`, `git_publish.py`, anything implementing the Mass-Update or - Iteration gates), the compiler, or a change about to ship in a version bump: `high` and up - - broader coverage is worth the cost when the blast radius of a missed bug is a safety gate. - - `ultra` is user-triggered and billed separately; recommend it, never assume it. - -## Decision points - -- **Task spans both a mechanical step and a judgment call?** Pick by the judgment call, not the - 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 *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 - -Does not apply to non-Claude-Code harnesses - see the note above; a follow-up issue tracks -whether and how they should decide this differently. Does not set the classifier model behind -Claude Code's own `auto` permission mode - that is a harness internal, not a per-task choice -this repo controls. diff --git a/instructions/dev/stack-close/SKILL.md b/instructions/dev/stack-close/SKILL.md index 3e7b5fc..4ffbe84 100644 --- a/instructions/dev/stack-close/SKILL.md +++ b/instructions/dev/stack-close/SKILL.md @@ -25,7 +25,7 @@ everyone reads afterwards and nobody revisits). The two phases around the mechanical middle of a stack-dev session have no mechanical guard at all - `pytest`, `docs verify` and `instructions verify` cover the code and tests in between, and nothing covers a changelog entry's accuracy, a `docs/` page's staleness, or an issue body's final -state (see [claude-code-model-selection.md](../../claude-code-model-selection.md)). Asking the +state (see [docs/model-and-effort-selection.md](../../../docs/model-and-effort-selection.md)). Asking the same session to notice it has crossed into that second unchecked stretch - as a prose break inside `stack-dev`'s own step 6 - failed twice in a row on this stack (Gitea #42, then #30): both times the session knew the rule and skipped past it anyway, because nothing in the moment forced the diff --git a/instructions/dev/stack-dev/SKILL.md b/instructions/dev/stack-dev/SKILL.md index 0de75cb..c0ff57a 100644 --- a/instructions/dev/stack-dev/SKILL.md +++ b/instructions/dev/stack-dev/SKILL.md @@ -96,7 +96,7 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li 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). + [docs/model-and-effort-selection.md](../../../docs/model-and-effort-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