feat: a subtype gets its own page skeleton from types/<type>.<value>.md (#117)
Files changed: - AGENTS.md - CHANGES.md - README.md - VERSION - docs/ownership-and-templates.md - instructions/evolve-subtypes.md - instructions/setup-instance.md - instructions/subtype-templates.md - instructions/upgrade-instance.md - tools/CONTRACT.md - tools/chemenu/commands/dist_cmd.py - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/new_page.py - tools/chemenu/tests/test_dist_cmd.py - tools/chemenu/tests/test_docs_verify.py - tools/chemenu/tests/test_new_page.py - tools/chemenu/tests/test_toc.py - tools/chemenu/tests/test_type_resolver.py - tools/chemenu/toc.py - tools/chemenu/type_resolver.py - types/concept.decision.md - types/entity.guidance.md - types/entity.md - types/entity.person.md - types/type-spec.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
1 parent
c261b8f4ca
commit
d8cb494d58
25 files changed
+747
-51
No files matched your search
+22
-7
@@ -67,7 +67,7 @@ frontmatter before anyone drew it:
|
||||
|
||||
| Type-spec | Describes | Owned by | Ships as |
|
||||
|---|---|---|---|
|
||||
| `root: kb` (`entity`, `concept`, `source`, `comparison`, `project`) | A page **this instance** writes | The instance | `types/<name>.md.template` plus its `.schema.yaml.template`, adopted by a rename |
|
||||
| `root: kb` (`entity`, `concept`, `source`, `comparison`, `project`) | A page **this instance** writes | The instance | `types/<name>.md.template` plus its `.schema.yaml.template` and any subtype template's `types/<name>.<value>.md.template`, adopted by a rename |
|
||||
| `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 frontmatter configuration and its `## Template` body are therefore the
|
||||
@@ -124,13 +124,23 @@ Python. Adding a type must require no code change.
|
||||
|
||||
### Anatomy of a type
|
||||
|
||||
Each type is at least two files, and a `root: kb` type may be three:
|
||||
Each type is at least two files, and a `root: kb` type may have more:
|
||||
|
||||
| File | Owns |
|
||||
|------|------|
|
||||
| `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 |
|
||||
| `types/<name>.<value>.md` (optional, any number, only for a type with `subtype_field:`) | A **subtype template**: the page skeleton for pages whose subtype field holds `<value>`, where that subtype needs a different page shape than the `## Template` block gives - a person is not described by a version and a repository. Plain markdown in the KB language, no frontmatter, no fence: the whole file is the skeleton. Its name is its only declaration - nothing in the type-spec lists it. Owned like the type-spec it sits beside, so a `root: kb` type's subtype templates ship as `.template` too |
|
||||
|
||||
`docs verify` holds a subtype template to three things: `types/<name>.md` beside it is a
|
||||
type-spec declaring `subtype_field:`, `<value>` is one that field's schema enum allows (where it
|
||||
has an enum), and the file carries no frontmatter. A misspelt name would otherwise be a template
|
||||
nothing ever reads, and nobody would notice. **`guidance` is reserved** - `types/<name>.guidance.md`
|
||||
is always the guidance file, so a subtype value `guidance` can have no template of its own. A
|
||||
subtype template never gets a table-of-contents region, whatever its length: it is copied into
|
||||
every page scaffolded from it. When an instance needs one is
|
||||
[instructions/subtype-templates.md](../instructions/subtype-templates.md).
|
||||
|
||||
**A `default:` is materialized by `wikitool new` only for a field the schema also lists in
|
||||
`required:`.** On an optional field, `default:` documents what a reader should assume when the
|
||||
@@ -141,9 +151,9 @@ newly scaffolded instruction regardless.
|
||||
|
||||
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.
|
||||
non-instantiable, contract-only type. `tools/wikitool types describe <name>` composes the type-spec, its schema and its guidance into
|
||||
one answer; an agent asking for a type's contract never needs to know it came from more than one
|
||||
file. Subtype templates are not part of that answer - only `wikitool new` reads them.
|
||||
|
||||
### Placement frontmatter
|
||||
|
||||
@@ -206,13 +216,18 @@ No Python change is needed at any step; `wikitool` discovers types by scanning t
|
||||
|
||||
### Template variables
|
||||
|
||||
The `## Template` block is filled from the page's own frontmatter, plus `{name}` and
|
||||
`wikitool new` picks one skeleton per page: `types/<name>.<value>.md` when the page's subtype
|
||||
field holds `<value>` and that file exists, otherwise the `## Template` block. A subtype template
|
||||
replaces the block whole - nothing is merged - so every subtype without a file of its own, and
|
||||
every type without a `subtype_field:`, scaffolds exactly what the block says.
|
||||
|
||||
Either skeleton is filled from the page's own frontmatter, plus `{name}` and
|
||||
`{today}`. Filters render structured fields: `{entities|bullets}`, `{tags|join}`,
|
||||
`{entity_type|capitalize}`, `{entities|table_header}`, `{entities|table_sep}`,
|
||||
`{entities|table_cells}`. `{field|literal text}` falls back to the literal when the field is
|
||||
absent.
|
||||
|
||||
**A template never contains a tool-owned region.** The links and footnotes regions are generated
|
||||
**A template - block or subtype file - 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`.
|
||||
|
||||
Reference in new issue
Block a user