types/: Seiten-Type-Spec-Anleitungsprosa in stackeigene guidance-Datei ausgelagert (schliesst #104)
CI / verify (push) Failing after 43s
Release / release (push) Successful in 34s

Files changed:
- AGENTS.md
- CHANGES.md
- VERSION
- docs/ownership-and-templates.md
- instructions/migrations/6.0.0-type-guidance-split.md
- instructions/setup-instance.md
- tools/CONTRACT.md
- tools/chemenu/commands/dist_cmd.py
- tools/chemenu/commands/types_cmd.py
- tools/chemenu/tests/test_dist_cmd.py
- tools/chemenu/tests/test_dist_upgrade.py
- tools/chemenu/tests/test_type_resolver.py
- tools/chemenu/tests/test_types_cmd.py
- tools/chemenu/type_resolver.py
- tools/chemenu/types_core.py
- types/comparison.guidance.md
- types/comparison.md
- types/concept.guidance.md
- types/concept.md
- types/entity.guidance.md
- types/entity.md
- types/source.guidance.md
- types/source.md
- types/type-guidance.md
- types/type-guidance.schema.yaml
- types/type-spec.md
This commit is contained in:
2026-09-15 18:23:38 +02:00
parent 90ce41964f
commit d49513bda6
26 changed files with 789 additions and 238 deletions
+37 -18
View File
@@ -33,6 +33,7 @@ A type-spec doc is the authoring and validation contract for one Chemenu artifac
- `description`: retrieval description for the type contract.
- `schema`: repo-relative path to the `.schema.yaml` file that validates artifacts of this type, or `null` when the type has no schema.
- `subtype_field` (optional): the frontmatter field name on instances of this type that carries a subtype/category (e.g. `entity_type`), or omitted if this type has no such field.
- `guidance` (optional): repo-relative path to a `types/type-guidance.md`-shaped document holding this type's stack-owned authoring prose - see § "Anatomy of a type" below. Meaningful only on a `root: kb` type-spec; omit for a type an instance writes entirely for itself.
## Validation Contract
@@ -65,28 +66,41 @@ frontmatter before anyone drew it:
| Type-spec | Describes | Owned by | Ships as |
|---|---|---|---|
| `root: kb` (`entity`, `concept`, `source`, `comparison`) | A page **this instance** writes | The instance | `types/<name>.md.template` plus its `.schema.yaml.template`, adopted by a rename |
| `root: repo` (`instruction`), no `base_dir` (`lint-report`), and `type-spec` itself | A stack artifact | The stack | Verbatim |
| `root: repo` (`instruction`), no `base_dir` (`lint-report`), and `type-spec`/`type-guidance` themselves | A stack artifact | The stack | Verbatim |
A page type-spec's prose and its `## Template` body are therefore the instance's to rewrite, and
an upgrade does not take that back. Improvements to a shipped default reach it as an *offered*
migration ([instructions/CONTRACT.md](../instructions/CONTRACT.md#instructionsmigrations)),
never by overwriting.
A page type-spec's frontmatter configuration and its `## Template` body are therefore the
instance's to rewrite, and an upgrade does not take that back. Its generic authoring prose is the
opposite: where the type-spec declares `guidance:`, that prose lives in a separate, stack-owned
`types/<name>.guidance.md` (§ "Anatomy of a type" below) that ships verbatim and is overwritten
by an upgrade like any other machinery file - the type-spec it documents does not have to be
re-adopted, or even touched, for that improvement to arrive. A type-spec that declares no
`guidance:` (a type an instance writes entirely for itself) has no stack half to receive; it is
described from its own body alone, exactly as every type-spec worked before this split existed.
An *existing* instance that adopted its type-specs before `guidance:` existed takes this as an
*offered* migration ([instructions/CONTRACT.md](../instructions/CONTRACT.md#instructionsmigrations))
rather than something an upgrade applies on its own - see `instructions/migrations/` for the
document.
**Ownership and language are not the same question here**, and this is the one file in the tree
where they come apart. Owning the file means the instance may rewrite any of it; the language it
writes in still follows what the line is *for*, per
[AGENTS.md § File naming](../AGENTS.md#file-naming):
**Ownership and language still do not line up with each other**, and that stays true even though
the authoring prose now has its own file rather than sharing one with the template. Owning the
type-spec means the instance may rewrite its frontmatter and its `## Template` body; a guidance
file it links is never the instance's to rewrite at all - it is the stack's, the same way
`tools/CONTRACT.md` is. What each part is *written in* still follows what the line is *for*, per
[AGENTS.md § File naming](../AGENTS.md#file-naming), independent of which file it lives in or who
owns that file:
| Part of a page type-spec | Audience | Language |
|---|---|---|
| Authoring guidance, frontmatter table, when to use / not to use | An agent writing a page | The control plane's — English |
| The `## Template` body, and the `layout:` titles that head a catalog section | The page itself | The instance's KB language (`kb/CONVENTIONS.md` `language:`) |
| Field names, enum values, `dir:` values, `type:` paths | The machine | Neither — identifiers, never translated |
| Part of a `root: kb` type's contract | Lives in | Audience | Language |
|---|---|---|---|
| When to use / not to use, authoring guidance | The `guidance:` file, where declared | An agent writing a page | The control plane's — English |
| The frontmatter table documenting this instance's own fields | The type-spec itself | An agent writing a page | The control plane's — English |
| The `## Template` body, and the `layout:` titles that head a catalog section | The type-spec itself | The page itself | The instance's KB language (`kb/CONVENTIONS.md` `language:`) |
| Field names, enum values, `dir:` values, `type:` paths | Either file's frontmatter | The machine | Neither — identifiers, never translated |
That is the same prose/identifier cut [kb/CONTRACT.md](../kb/CONTRACT.md#language-and-identifiers)
makes *inside* a page, applied one level up. It binds a type-spec an instance writes for itself
exactly as it binds the four shipped ones: a new page type is instance-owned end to end, which
settles who may change it, not which language each half is written in.
settles who may change it, not which language each half is written in - and it may declare its
own `guidance:` file if it wants the same shape, though nothing requires it to.
**What the stack still requires of the type layer is one line.** There must be a type-spec
declaring `name: source` whose schema requires `raw_files:` — the whole `raw/``kb/`
@@ -102,14 +116,19 @@ Python. Adding a type must require no code change.
### Anatomy of a type
Each type is two files:
Each type is at least two files, and a `root: kb` type may be three:
| File | Owns |
|------|------|
| `types/<name>.md` | The authoring contract: when to use the type, when not to, guidance, and the `## Template` block used to scaffold new pages |
| `types/<name>.md` | This instance's configuration: its frontmatter fields as this schema requires them, and the `## Template` block used to scaffold new pages. For a type with no `guidance:` (below), its own prose also carries the authoring contract - when to use the type, when not to |
| `types/<name>.schema.yaml` | The machine-checkable half: fields, types, enums, defaults, required-ness, `additionalProperties: false` |
| `types/<name>.guidance.md` (optional, `root: kb` only) | The stack-owned authoring contract: when to use the type, when not to, and mechanism-level advice that holds regardless of this instance's own enum values or template text - linked from the type-spec's own `guidance:` field. `types/type-guidance.md` is its contract |
This file is the self-referential root contract that both are validated against.
This file is the self-referential root contract every type-spec is validated against, and
`type-guidance.md` is validated against it the same way `lint-report.md` is - itself a
non-instantiable, contract-only type. `tools/wikitool types describe <name>` composes all of a
type's files into one answer regardless of how many there are; an agent asking for a type's
contract never needs to know it came from more than one file.
### Placement frontmatter