Files
chemenu/instructions/dev/stack-dev/SKILL.md
T
torben b1883befc7
CI / verify (push) Successful in 49s
Release / release (push) Successful in 36s
docs: Modellwahl nach Pruefbarkeit; stack-dev bricht an den Phasenwechseln fuer den Model-Switch (4.3.3)
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

184 lines
12 KiB
Markdown

---
name: stack-dev
description: Switch a session into tool-development mode - extending tools/wikitool, the compiler, the type schema, or the instruction/skill layer itself, instead of operating on wiki content. Use when the user asks to add a wikitool command, change a type-spec, fix or extend the compiler, or otherwise work on the stack rather than ingest/query/manage/lint the wiki.
---
# Stack Development Mode
**Purpose:** Recognize a session that is about the tool stack itself - `tools/wikitool`, the
type schema, the instruction/skill layer - rather than wiki content, and switch the rules that
apply accordingly.
**Trigger:** The user asks to add or change a `wikitool` command, extend the compiler, change a
type-spec, or work on `instructions/`/`types/`/`tools/` as code rather than as a place to run
`wiki-ingest`/`wiki-query`/`wiki-manage`/`wiki-lint`/`wiki-status` against.
**This directory is dev-only.** `instructions/dev/` is excluded wholesale by
`tools/wikitool dist export` - nothing here ever reaches a distributed instance, and there is
no restore path. If you are in a distributed instance, this skill should not be present at all;
stack development happens in the origin repo instead (see AGENTS.md's routing line).
## What changes in this mode
- **Source-binding does not apply to code.** AGENTS.md invariant 3 ("never file an unsourced
answer into the wiki") governs `kb/` content, not the code you write to extend the stack.
Ordinary software-engineering judgment applies to `tools/chemenu/*.py`, `types/*`,
`instructions/*` - it does not need a `raw/` source or a citation.
- **Test and review conventions from `instructions/dev/` apply instead**, once written down
there (step 2 below lists what currently exists). Until a given convention has its own
instruction file, follow the existing test files' own patterns
(`tools/chemenu/tests/`) rather than inventing a new one silently.
- **Everything outside this directory still applies.** The tool error contract, the gates, and
"never hand-edit generated files" (AGENTS.md invariants 1, 5-8) are about how the tool
behaves at runtime, not about developing it, but they still bind normal session conduct
(e.g. still use `tools/wikitool publish`, still respect the gates, when the session also
touches wiki content).
## Steps
1. **Confirm the mode.** If the task is ambiguous between "extend the tool" and "operate the
wiki", ask rather than guess - the two have different rules for the same directories.
2. **Consult `instructions/dev/` for the concrete procedure.** Currently:
[commonplace-kb.md](../commonplace-kb.md) - vendored knowledge base on agent context
engineering, memory and deploy-time learning; consult before a design decision in those
areas.
[issue-tracking.md](../issue-tracking.md) - open work lives in Gitea issues, one per work
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 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
empty machine; what the autouse fixture already neutralizes, and what a test still has to
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 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. **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:
```bash
tools/wikitool version bump --patch --title "<what changed>"
```
Never edit `VERSION` or the entry's heading by hand - `bump` writes both, and `docs verify`
fails a tree where they disagree. Pick the part by whether the new version is a **drop-in
replacement** for the old one - not by whether content has to be migrated:
| Change | Part |
|--------|------|
| Fix, no interface change | `--patch` |
| New capability, still drop-in in both directions | `--minor` |
| **Not a drop-in replacement** - any hand-work by the user or a migration script, or a downgrade that no longer works | `--major` |
Content migration is one way to land in the last row, not the definition of it: a rename of
the update path, the artefact, an import name, a flag or an envvar breaks a swap with `kb/`
entirely untouched. The full test, the catalogue of such breaks, and what to put in front of
the user first are in [version-parts.md](../version-parts.md) - **read it before choosing
`--major`.**
A `--major` bump therefore needs two things recorded. `--breaking "<what stops working>"`
is required on every boundary-crossing bump; on top of it, a migration document for the new
version - written per [migrate-corpus.md](../../migrate-corpus.md) - or
`--no-migration "<reason>"` when no content actually has to change. `bump` refuses without
either, and so does `docs verify`: an instance learning that it must migrate, with nothing
telling it how, is a dead end.
Then write the entry's body - `bump` deliberately leaves it empty, the same way `new` leaves
the prose.
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.
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.
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:
- every acceptance criterion ticked, or struck with the reason it was dropped
- proposals that were decided read as decided; a "to decide" section has become the decision
and its reasoning
- nothing left in the present tense about a defect that no longer exists
- what was verified is named - which checks ran, which CI run - not a commit hash alone
Then one short comment naming what changed against the previous state, and nothing else.
**A closing report in a comment does not satisfy this**, however thorough: it reads as
complete to whoever writes it and leaves a body still phrased as open work. Nothing
mechanical catches it - `wikitool` does not know this tracker exists and must not learn it,
since it ships to instances that have no board - so this step is the only enforcement there
is. #44 and #45 both closed exactly this way, the second an hour after the rule was written.
[issue-tracking.md](../issue-tracking.md) step 7 has the full shape.
## Decision points
- **Touches both stack code and wiki content in one session?** Apply this skill's rules to the
code changes and the normal content skills' rules to the content changes - they are not
mutually exclusive within a session, only per change.
- **The change turns out not to be a drop-in replacement?** Do not bump across the boundary on
your own initiative. Every existing instance pays for a breaking change once, by hand, so the
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. 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
Not for wiki content work - use `wiki-ingest`/`wiki-query`/`wiki-manage`/`wiki-lint`/
`wiki-status` for that. Not for setting up a new instance (`instructions/setup-instance.md`) or
a fresh clone of this repo (`instructions/bootstrap.md`).