instructions: the agent speaks the KB language in chat - AGENTS.md § Conversation language, and instructions sync compiles the language tag into every published SKILL.md (#116); 10.0.0-beta.9
CI / verify (push) Successful in 8m6s
CI / pwsh (push) Successful in 2m50s
Release / release (push) Successful in 33s
Release / wiki-mirror (push) Skipped

Files changed:
- AGENTS.md
- CHANGES.md
- VERSION
- docs/explanation/language-boundaries.md
- docs/reference/commands/types-instructions-and-docs.md
- instructions/CONTRACT.md
- instructions/dev/stack-build/SKILL.md
- instructions/dev/stack-close/SKILL.md
- instructions/dev/stack-dev/SKILL.md
- kb/CONVENTIONS.md
- kb/CONVENTIONS.md.template
- tools/CONTRACT.md
- tools/chemenu/commands/doctor.py
- tools/chemenu/commands/instructions_cmd.py
- tools/chemenu/tests/test_doctor.py
- tools/chemenu/tests/test_instructions_cmd.py

Co-Authored-By: Claude Code <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
torbenandClaude Code committed 2026-10-12 06:57:51 +02:00
1 parent c06bde2e95
commit 0f0a5799fd
16 files changed
+385 -54

No files matched your search

+29 -1
View File
@@ -7,7 +7,9 @@ tells an agent what to do - [AGENTS.md](../../AGENTS.md), every `CONTRACT.md`, e
is the stack's own documentation for humans, for a different reason (§ "The stack's human
documentation").
The rule itself is in [AGENTS.md § File naming](../../AGENTS.md#file-naming). This page holds the
The rules themselves are in [AGENTS.md § File naming](../../AGENTS.md#file-naming) (the language
of a file) and [AGENTS.md § Conversation language](../../AGENTS.md#conversation-language) (the
language of what an agent says). This page holds the
part that is not a rule: why the line runs where it does, why the English half is not a setting,
and which argument for it turned out to be wrong.
@@ -18,6 +20,7 @@ and which argument for it turned out to be wrong.
- [Why the control plane's language is English](#why-the-control-planes-language-is-english)
- [Why it is not a parameter](#why-it-is-not-a-parameter)
- [What the KB language still decides](#what-the-kb-language-still-decides)
- [Why a rule alone did not hold](#why-a-rule-alone-did-not-hold)
- [Where the line runs around a page type](#where-the-line-runs-around-a-page-type)
- [The stack's human documentation](#the-stacks-human-documentation)
- [What would put this back on the table](#what-would-put-this-back-on-the-table)
@@ -105,6 +108,31 @@ So an operator who reads no English gets German pages and German answers from an
English instructions. The English is what the machinery is written in, not what it says back -
with one exception, the stack's documentation for humans (§ "The stack's human documentation").
### Why a rule alone did not hold
For a while the conversation rule was a sentence about files' languages in `AGENTS.md`, and an
instance on German pages still saw an agent that wrote its pages in German and everything else in
English: progress notes between tool calls, the closing report. Pages were right because the
step that writes a page reads `kb/CONVENTIONS.md` first; the chat was wrong because nothing had
put the value in front of the agent by then. Three things stacked up:
- **The rule sat in the wrong section.** A paragraph about the language of files does not read as
a rule about speaking, and it was phrased as a statement of fact rather than an instruction.
It now has a section of its own.
- **The value was one hop away.** `AGENTS.md` ships verbatim to every instance and so cannot
carry the instance's language; it names the file that does. A short ingest has written several
English messages before it opens that file.
- **The context is English.** Instructions, tool output and error text all are, and one short
message from the operator is outweighed by them - the more so for a weaker model.
So the value is also compiled into the published copy of each skill, as a one-line block under
its frontmatter that `wikitool instructions sync` writes: the language tag and a pointer to the
rule, nothing else. The rule stays in `AGENTS.md` and the value in `kb/CONVENTIONS.md`; the block
holds neither as text of its own, only puts the one in front of the task that needs it. It is a
tag, not a language name, because a table of names would be the compiler's opinion about
languages, which `conventions.py` deliberately has none of. A session with no skill is covered by
the `AGENTS.md` section alone.
## Where the line runs around a page type
A page type's contract is where the two languages meet most closely, and it is worth knowing
@@ -138,6 +138,7 @@ tools/wikitool instructions sync
**Behaviour**
- Publishes every `instructions/<name>/SKILL.md` into `.agents/skills/` and `.claude/skills/` as **copies**, and deletes published skills whose source is gone.
- Each published `SKILL.md` is its source plus one generated line directly under the frontmatter: the `language:` of `kb/CONVENTIONS.md` and a pointer to `AGENTS.md` § Conversation language, so the agent has the value in context when the task begins. The frontmatter and every other file are copied unchanged. With no language declared, the `SKILL.md` is copied unchanged too, and the success message says so.
- Both targets are gitignored, so a fresh clone runs this once.
- Re-running repairs a drifted copy: the source always wins.
- `--force` is required only to replace a target directory that is not a published skill at all (no `SKILL.md` in it).
@@ -186,7 +187,7 @@ tools/wikitool instructions verify
- Flat instructions validate against `types/instruction.schema.yaml`, and each `SKILL.md` carries the frontmatter its harness reads.
- No `SKILL.md` carries a relative markdown link: `sync` copies it to a different depth than the source, so a `SKILL.md` references a target as a repo-root-relative plain path instead (`instructions/CONTRACT.md` § "A skill's outbound reference is a plain path, not a link").
- Every published copy is byte-identical to its source. Missing *every* copy is reported as "run sync", not as drift - that is a clean checkout.
- Every published copy is what `sync` would write from its source: byte-identical, except for the generated language line in `SKILL.md` that the current `language:` of `kb/CONVENTIONS.md` calls for. Missing *every* copy is reported as "run sync", not as drift - that is a clean checkout.
- No instruction is left that nothing references; one marked `manual: true` must instead not be linked from AGENTS.md, CLAUDE.md or a skill.
- Nothing under `instructions/dev/` is referenced from outside it; a `<!-- dist:strip-start/end -->` block is exempt (`instructions/CONTRACT.md`).
- Read-only.
@@ -204,7 +205,7 @@ tools/wikitool instructions verify
- `0` - success
- `1` - Nothing found under `instructions/` at all, or a malformed instruction or `SKILL.md`
- `1` - A `SKILL.md` carries a relative markdown link
- `1` - A published copy drifted from its source
- `1` - A published copy drifted from its source - including a language line that belongs to an earlier `language:` (the message names it as such)
- `1` - An instruction nothing references, or a `manual: true` one that IS linked from AGENTS.md, CLAUDE.md or a skill and so risks running implicitly
- `1` - Something under `instructions/dev/` is referenced from outside it and outside a `dist:strip` block