feat: Prosa ist kein Identifier - Link-Taxonomie als Enum, generierte Regionen mit Markern (4.0.0)
Files changed: - .gitea/workflows/ci.yml - AGENTS.md - CHANGES.md - VERSION - instructions/CONTRACT.md - instructions/link-taxonomy.md - instructions/migrations/4.0.0-link-taxonomy.md - instructions/setup-instance.md - kb/CONTRACT.md - kb/CONVENTIONS.md - kb/CONVENTIONS.md.template - kb/comparisons/COLLECTION.md - kb/concepts/COLLECTION.md - kb/entities/COLLECTION.md - kb/sources/COLLECTION.md - tools/CONTRACT.md - tools/README.md - tools/chemenu/blocks.py - tools/chemenu/cli.py - tools/chemenu/commands/cite_cmd.py - tools/chemenu/commands/dist_cmd.py - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/doctor.py - tools/chemenu/commands/links_cmd.py - tools/chemenu/commands/migrate_cmd.py - tools/chemenu/commands/new_page.py - tools/chemenu/commands/page_ops.py - tools/chemenu/commands/run_budget.py - tools/chemenu/commands/xref.py - tools/chemenu/conventions.py - tools/chemenu/corpus_diff.py - tools/chemenu/frontmatter_io.py - tools/chemenu/kb_collections.py - tools/chemenu/kb_state.py - tools/chemenu/links.py - tools/chemenu/lint_core.py - tools/chemenu/provenance.py - tools/chemenu/sections.py - tools/chemenu/tests/conftest.py - tools/chemenu/tests/test_blocks.py - tools/chemenu/tests/test_cite_cmd.py - tools/chemenu/tests/test_conventions.py - tools/chemenu/tests/test_dist_cmd.py - tools/chemenu/tests/test_doctor.py - tools/chemenu/tests/test_migrate_cmd.py - tools/chemenu/tests/test_new_page.py - tools/chemenu/tests/test_pipeline_l0.py - tools/chemenu/tests/test_types_cmd.py - tools/chemenu/tests/test_xref.py - types/concept.schema.yaml - types/entity.md - types/entity.schema.yaml - types/instruction.schema.yaml - types/type-spec.md - work/link-taxonomy-migration/README.md - work/link-taxonomy-migration/plan.md
This commit is contained in:
@@ -27,8 +27,21 @@ properties:
|
||||
related:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Related concept and entity titles
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: object
|
||||
minProperties: 1
|
||||
maxProperties: 1
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: >-
|
||||
Declared outbound edges. Each entry is either `<label>: <page title>` - the
|
||||
label drawn from instructions/link-taxonomy.md and authorised per
|
||||
destination by the source collection's `outbound:` block - or a bare page
|
||||
title for an edge whose label has not been declared yet. The bare form is
|
||||
the pre-4.0.0 shape and is what `lint` reports until the migration reaches
|
||||
the page; it is accepted rather than rejected so that a corpus stays
|
||||
readable while it is being converted.
|
||||
sources:
|
||||
type: array
|
||||
items:
|
||||
|
||||
+4
-15
@@ -77,12 +77,6 @@ TODO: 1-2 Absätze dazu, was diese Entity ist und wozu sie dient.
|
||||
- **Verantwortlich:** TODO (falls zutreffend)
|
||||
- **Repository:** TODO (falls zutreffend)
|
||||
|
||||
## {section.relationships}
|
||||
|
||||
- **Hängt ab von:** TODO
|
||||
- **Verwendet von:** TODO
|
||||
- **Verwandt mit:** TODO
|
||||
|
||||
## Details
|
||||
|
||||
TODO: Ausführliche Informationen, nach sinnvollen Abschnitten gegliedert
|
||||
@@ -90,17 +84,12 @@ TODO: Ausführliche Informationen, nach sinnvollen Abschnitten gegliedert
|
||||
## Historie
|
||||
|
||||
- [{today}] - Page created via wikitool
|
||||
|
||||
## {section.see_also}
|
||||
|
||||
- TODO: Verwandte Seiten
|
||||
```
|
||||
|
||||
Die beiden `{section.…}`-Platzhalter sind toolgeführte Abschnitte: `wikitool xref` schreibt in
|
||||
genau sie hinein, und wie sie heißen, entscheidet die Instanz in `kb/CONVENTIONS.md`
|
||||
(`sections:`) - nicht dieser Type-Spec und nicht der Compiler. `wikitool new` setzt den
|
||||
aktuellen Namen ein. Der Wert hinter `**Typ:**` bleibt der englische Enum-Wert - danach filtert
|
||||
`search --field`.
|
||||
Der Beziehungsabschnitt steht bewusst **nicht** im Template: er ist eine generierte Region, die
|
||||
`wikitool xref` beim ersten Kanteneintrag zwischen Markern anlegt und aus `related:` neu
|
||||
rendert. Ein Autor schreibt dort nie hinein. Der Wert hinter `**Typ:**` bleibt der englische
|
||||
Enum-Wert - danach filtert `search --field`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -27,8 +27,21 @@ properties:
|
||||
related:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Related page titles
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: object
|
||||
minProperties: 1
|
||||
maxProperties: 1
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: >-
|
||||
Declared outbound edges. Each entry is either `<label>: <page title>` - the
|
||||
label drawn from instructions/link-taxonomy.md and authorised per
|
||||
destination by the source collection's `outbound:` block - or a bare page
|
||||
title for an edge whose label has not been declared yet. The bare form is
|
||||
the pre-4.0.0 shape and is what `lint` reports until the migration reaches
|
||||
the page; it is accepted rather than rejected so that a corpus stays
|
||||
readable while it is being converted.
|
||||
sources:
|
||||
type: array
|
||||
items:
|
||||
|
||||
@@ -43,6 +43,21 @@ properties:
|
||||
scriptable; `assisted` needs a judgment call per page and is therefore an
|
||||
agent procedure. Today this is a description rather than an execution
|
||||
promise - there is no `migrate run`.
|
||||
obligation:
|
||||
type: string
|
||||
enum: [required, offered]
|
||||
default: required
|
||||
description: >-
|
||||
Whether the migration must run at all - a separate axis from
|
||||
`migration_kind`, which says only how the work is done. `required`
|
||||
(the default) is the original meaning: the content must reach the new
|
||||
shape or it no longer fits the machinery, so `migrate status` counts it
|
||||
as outstanding and `migrate done` advances `kb_version` through it.
|
||||
`offered` is an upgrade the instance may decline: a file it owns still
|
||||
works as it is, and the stack is proposing a better default. An offered
|
||||
migration never blocks, never appears in the outstanding chain, and is
|
||||
not a link in the version chain - it is listed separately so an operator
|
||||
can take it when they want it.
|
||||
required:
|
||||
- type
|
||||
- name
|
||||
|
||||
+28
-5
@@ -40,6 +40,30 @@ under `kb/`. It is deliberately **not a collection** and carries no `COLLECTION.
|
||||
no per-collection type surface, and `tools/wikitool docs verify` fails if a contract appears
|
||||
here.
|
||||
|
||||
### Who owns a type-spec
|
||||
|
||||
`types/` holds two kinds of file, and the line between them is `root:` — already in the
|
||||
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 |
|
||||
|
||||
A page type-spec's prose, its `## Template` body and its language are therefore the instance's
|
||||
to rewrite — an instance writing its pages in another language simply translates the file, 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.
|
||||
|
||||
**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/`
|
||||
provenance path (`sources coverage`, `[^cite-id]` resolution, `kb/provenance.md`) asks
|
||||
`page.kind == "source"`, so without it nothing resolves. `docs verify` checks exactly that and
|
||||
nothing beyond it: not the directory, not the title prefix, not a word of the prose. Which
|
||||
collection is stack-required is *derived* from where that type writes rather than listed
|
||||
separately, so renaming it stays consistent instead of tripping a hardcoded name.
|
||||
|
||||
**Quality goal:** a type-spec is the single source of truth for its type. No structural fact
|
||||
about a page type may be restated anywhere else — not in `AGENTS.md`, not in a skill, not in
|
||||
Python. Adding a type must require no code change.
|
||||
@@ -98,11 +122,10 @@ The `## Template` block is filled from the page's own frontmatter, plus `{name}`
|
||||
`{entities|table_cells}`. `{field|literal text}` falls back to the literal when the field is
|
||||
absent.
|
||||
|
||||
Three further variables come from the instance rather than from the page:
|
||||
`{section.relationships}`, `{section.see_also}` and `{section.footnotes}`, filled from
|
||||
`kb/CONVENTIONS.md`'s `sections:` declaration. A template writes a tool-owned heading through
|
||||
one of those and never as literal text - that is what lets an instance change the KB language
|
||||
without editing anything under `types/`.
|
||||
**A template never contains a tool-owned region.** The links and footnotes regions are generated
|
||||
between markers by `xref` and `cite`, rendered from frontmatter, and re-rendered on every write -
|
||||
so scaffolding them would create a section an author is forbidden to edit and the tool would
|
||||
replace anyway. See `tools/chemenu/blocks.py`.
|
||||
|
||||
### Ownership boundary
|
||||
|
||||
|
||||
Reference in New Issue
Block a user