502971d147
Files changed: - .gitea/workflows/ci.yml - .wikitool-kb.json - AGENTS.md - CHANGES.md - INSTALL.md - README.md - VERSION - instructions/CONTRACT.md - instructions/dev/testing-conventions.md - instructions/german-terminology.md - instructions/kb-profiles.md - instructions/migrations/3.0.0-authoring-conventions.md - instructions/private-instance.md - instructions/setup-instance.md - instructions/wiki-ingest/SKILL.md - instructions/wiki-manage/SKILL.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/commands/dist_cmd.py - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/doctor.py - tools/chemenu/commands/new_page.py - tools/chemenu/conventions.py - tools/chemenu/kb_collections.py - tools/chemenu/kb_scan.py - tools/chemenu/provenance.py - tools/chemenu/sections.py - tools/chemenu/tests/conftest.py - tools/chemenu/tests/test_conventions.py - tools/chemenu/tests/test_dist_cmd.py - tools/chemenu/tests/test_doctor.py - tools/chemenu/tests/test_new_page.py - tools/chemenu/tests/test_types_cmd.py - types/comparison.md - types/concept.md - types/entity.md - types/source.md - types/type-spec.md
242 lines
14 KiB
Markdown
242 lines
14 KiB
Markdown
# kb/ - Knowledge Layer Contract
|
|
|
|
The compiled knowledge layer, and the third stage of the pipeline
|
|
`raw/` -> `kb/` -> `reports/`. Everything here is written and maintained by the LLM from
|
|
material in `raw/`, and is expected to stay correct without being re-derived.
|
|
|
|
**Quality goal:** a page should answer a future question *without* re-reading the source it
|
|
came from. If answering still requires the raw file, the page is incomplete.
|
|
|
|
This file holds the rules that apply in **every** collection **and in every instance**. That
|
|
second half is the cut: what is written here is enforced by `tools/wikitool` or follows from
|
|
how it works, so it is identical everywhere and `dist export` ships it verbatim.
|
|
|
|
**What an instance decides for itself is next door, in
|
|
[kb/CONVENTIONS.md](CONVENTIONS.md)** - the language pages are written in and its three
|
|
tool-owned section headings, the naming forms, the tone, the relationship-label vocabulary, the
|
|
confidence rubric. That file binds exactly as this one does; it is simply owned by the instance
|
|
rather than by the stack, so the distribution ships only its `.template` and the instance writes
|
|
the real one. Read both, plus the target collection's `kb/<name>/COLLECTION.md` (also
|
|
instance-owned), before writing or editing a page.
|
|
|
|
The split is by **who may change the sentence**, not by what it is about. Language, tone and
|
|
naming used to sit here, which meant every instance that answered "not German" to
|
|
`setup-instance.md` was locally editing a file the stack also ships - and a merge from upstream
|
|
would quietly hand it back.
|
|
|
|
Structural facts (which frontmatter fields exist, which are required, what the body skeleton
|
|
looks like) are in neither - they belong to the type-specs and are printed by
|
|
`tools/wikitool types describe <type>`. Never hand-write frontmatter; scaffold with
|
|
`tools/wikitool new <type> --name "<Name>" --set field=value ...`.
|
|
|
|
## Collections
|
|
|
|
`kb/` is a **namespace, not a collection**. It carries no `COLLECTION.md` of its own.
|
|
|
|
A directory under `kb/` is a **collection** exactly when it contains a `COLLECTION.md`. That
|
|
file is the local authoring contract for every page in the subtree, and it belongs to the
|
|
instance: it declares in its frontmatter which profile from
|
|
[instructions/kb-profiles.md](../instructions/kb-profiles.md) it adopted, and whether the stack
|
|
resolves against it by name.
|
|
|
|
| Field | Means |
|
|
|---|---|
|
|
| `profile:` | Which catalogue entry this contract started from, or `none`. Free text - the catalogue is a palette, not an enum, and a collection an instance invented has no entry to name |
|
|
| `required_by_stack:` | Whether `wikitool` itself depends on this collection *by name*. Not the instance's to choose: `docs verify` checks it against the stack's own list. `kb/sources/` is `true` - `sources coverage`, `[^cite-id]` resolution and `kb/provenance.md` all resolve against that name - and everything else is `false` |
|
|
|
|
- A subdirectory *inside* a collection is an **area**. It inherits the enclosing contract and
|
|
must not carry a `COLLECTION.md` of its own - `kb/entities/systems/` is an area of
|
|
`kb/entities/`.
|
|
- A `COLLECTION.md` nested inside another collection is invalid.
|
|
- `COLLECTION.md` appears **nowhere outside `kb/`**. `raw/`, `types/`, `tools/`, `reports/`
|
|
and `instructions/` are not collections and carry a `CONTRACT.md` or a root type-spec
|
|
instead.
|
|
|
|
`tools/wikitool docs verify` enforces all three.
|
|
|
|
| Collection | Holds | Contract |
|
|
|------------|-------|----------|
|
|
| `kb/entities/` | Concrete things: projects, deployed systems, tools, technologies, people | [entities/COLLECTION.md](entities/COLLECTION.md) |
|
|
| `kb/concepts/` | Architectures, patterns, protocols, workflows, decisions, recurring problems | [concepts/COLLECTION.md](concepts/COLLECTION.md) |
|
|
| `kb/sources/` | One summary page per ingested source, carrying its `raw_files:` provenance | [sources/COLLECTION.md](sources/COLLECTION.md) |
|
|
| `kb/comparisons/` | Structured comparisons of two or more existing pages | [comparisons/COLLECTION.md](comparisons/COLLECTION.md) |
|
|
|
|
The four rows above are this instance's collections, not a fixed set. **Adding one:**
|
|
`mkdir kb/<name>` and write a `kb/<name>/COLLECTION.md` with the two fields above. Collections
|
|
are discovered by contract presence, so no code change is needed. A collection only becomes
|
|
*writable* once some type-spec declares a matching `base_dir:`. Renaming or dropping one is the
|
|
instance's call too - except where `required_by_stack: true` says otherwise.
|
|
|
|
**Where a page goes** is decided by its type-spec, never by hand - see
|
|
[types/type-spec.md](../types/type-spec.md).
|
|
|
|
## Generated files
|
|
|
|
Never hand-edit these; they are produced by `tools/wikitool`:
|
|
|
|
| File | Produced by |
|
|
|------|-------------|
|
|
| `kb/index.md` | `wikitool index rebuild` - the catalog **map**: statistics, counts, links |
|
|
| `kb/<collection>/INDEX.md` and `kb/<collection>/<area>/INDEX.md` | `wikitool index rebuild` - the page tables |
|
|
| `kb/log.md` | `wikitool log append` |
|
|
| `kb/provenance.md` | `wikitool sources rebuild-index` |
|
|
|
|
To *find* a page, search rather than read the catalog: `tools/wikitool search "<text>"`, or
|
|
`tools/wikitool search --field <predicate>` for a structured query over frontmatter.
|
|
|
|
## Titles are identifiers
|
|
|
|
**The filename stem *is* the page title, and `[[wikilinks]]` must match it exactly.** That is
|
|
not a naming preference; it is the wiki's only way to address a page. `wikitool lint` reports an
|
|
H1 that stops matching its title, `rename`/`rm` rewrite every reference to a stem, and a
|
|
`[^cite-id]` resolves through one.
|
|
|
|
Which *form* those titles take - spaces or kebab-case, singular or plural, what prefixes a
|
|
decision record - is the instance's, in
|
|
[kb/CONVENTIONS.md § Naming](CONVENTIONS.md#naming).
|
|
|
|
## Every page should
|
|
|
|
- [ ] Carry a clear, descriptive title and a summary near the top
|
|
- [ ] Use consistent terminology with the rest of the wiki
|
|
- [ ] Link to every entity and concept it mentions, and be linked to in return
|
|
- [ ] Cite its hard facts (see [Provenance and citation](#provenance-and-citation))
|
|
- [ ] Duplicate no existing page
|
|
- [ ] Appear in the catalog (guaranteed by `wikitool index rebuild`)
|
|
|
|
## Quotation cap
|
|
|
|
At most 2 blockquoted lines per page. `wikitool lint` reports overages as advisory, since
|
|
exceeding the cap can be a legitimate judgment call - but the page should carry the knowledge
|
|
itself, not delegate it to quotations. The cap is about how much of the page you let quotes
|
|
carry; it does not apply to text you are citing verbatim from a source.
|
|
|
|
The register those lines are written in - what counts as a buzzword, what filler is refused -
|
|
is the instance's, in [kb/CONVENTIONS.md § Tone](CONVENTIONS.md#tone).
|
|
|
|
## Language and identifiers
|
|
|
|
*Which* language pages are written in is [kb/CONVENTIONS.md](CONVENTIONS.md)'s to say. What
|
|
follows here is the part that is not a choice, because the tool resolves against it.
|
|
|
|
Every line of a page is either **prose** or an **identifier**. Only prose is translated.
|
|
|
|
**Prose:** descriptions and definitions, `## Key Information` values, `## Details` body text, a
|
|
source page's Summary / Key Takeaways / Action Items / Not Extracted, and `summary:`.
|
|
|
|
**Identifiers - never translated, in any language:**
|
|
|
|
| Identifier | Why |
|
|
|---|---|
|
|
| Page titles, and the H1 that repeats one | A title is the wiki's only identifier for a page and follows the subject's own established name - see [Titles are identifiers](#titles-are-identifiers). `wikitool lint` reports an H1 that stops matching its title |
|
|
| The subtype value on the generated `**Typ:**` line | It renders a schema enum value (`technology`, `workflow`), which `search --field` filters on. The label is prose; the value is not |
|
|
| `tags:` | Search keys, not prose |
|
|
| Commands, paths, config keys, hostnames, code | They are what they are |
|
|
| Quotations | Quoted verbatim in the source's own language |
|
|
|
|
Which foreign technical terms stay untranslated inside that prose is a judgment call the
|
|
instance records - see [kb/CONVENTIONS.md § Language](CONVENTIONS.md#language).
|
|
|
|
**A source in another language** is still summarized in the KB language: a source page is
|
|
evidence *about* a source, not a substitute for it. Quote verbatim in the original language and
|
|
record the raw file's language in `source_language:`.
|
|
|
|
### Section headings
|
|
|
|
Three headings are a vocabulary the tool owns rather than prose an author picks: `xref add`
|
|
writes into Relationships and See Also, and `cite add` owns the trailing Footnotes block. They
|
|
follow the KB language like everything else, so **the instance names them**, in
|
|
`kb/CONVENTIONS.md`'s `sections:` frontmatter. `tools/chemenu/conventions.py` reads that
|
|
declaration and `tools/chemenu/sections.py` is what the rest of the compiler asks - there is no
|
|
heading text in the compiler itself.
|
|
|
|
Each has aliases the tool still *recognizes* but no longer writes, which is what lets the corpus
|
|
be translated page by page: a page still carrying `## Relationships` is found and appended to
|
|
correctly, and `cite sync` leaves an untranslated `## Footnotes` heading alone rather than
|
|
retitling it. The recognized set is the canonical name, any `section_aliases:` the instance
|
|
declared, and the names this stack wrote before the declaration existed. Renaming a heading is
|
|
the translation pass's job, never a side effect of another command. Any *other* heading an
|
|
author adds is ordinary prose and is translated with the rest.
|
|
|
|
## Linking
|
|
|
|
Every page links to what it mentions, in both directions. Cross-references are created with
|
|
`tools/wikitool xref add --a "<A>" --b "<B>" --rel-a "<label>" --rel-b "<label>"`, never by
|
|
hand-editing the `related:` array or the Relationships/See Also bullets.
|
|
|
|
Use a typed relationship label rather than a generic one. The label is free text as far as the
|
|
tool is concerned - it is written into a `- **label:** [[Title]]` bullet and no code matches on
|
|
it - so which vocabulary this instance uses is
|
|
[kb/CONVENTIONS.md § Relationship labels](CONVENTIONS.md#relationship-labels)'s to list.
|
|
|
|
A page is expected to have at least one inbound link; `wikitool lint` reports orphans.
|
|
Comparison pages are exempt - they are reached through the catalog.
|
|
|
|
Renaming a page, deleting one, or dropping a single reference are tool operations with their
|
|
own procedure: see [instructions/page-lifecycle.md](../instructions/page-lifecycle.md).
|
|
|
|
## Provenance and citation
|
|
|
|
Every claim is either traceable to a raw file or explicitly marked as not.
|
|
|
|
- **`provenance:`** on every entity/concept page - `sourced` (every substantive claim traces
|
|
to a raw file), `general` (LLM general knowledge, no raw backing), or `mixed` (both; put the
|
|
unsourced part under a `## General Guidance (unsourced)` heading).
|
|
- **`raw_files:`** on every source page - concrete existing file paths under `raw/`, never a
|
|
directory and never a bare URL. For an external article also set `source_url:`, but
|
|
`raw_files:` must still point at the local copy under `raw/articles/`.
|
|
- **One source page may cover many raw files.** A folder of related documents becomes a single
|
|
page listing all of them, not one page per file.
|
|
- **A `[^cite-id]` footnote** appended to any *specific hard fact*: an IP, port, version, path,
|
|
command, or config value. `tools/wikitool cite add --page "<Title>" --source "Source - X"
|
|
[--file <qualifier>]` mints the id, upserts its `[[Source - X]]` (or
|
|
`[[Source - X|storage-model.md]]` for a multi-file source) definition in the page's trailing
|
|
Footnotes block (named per [Section headings](#section-headings)), and adds `Source - X` to
|
|
`sources:` - it prints the marker to paste at
|
|
the fact; placing it is still manual. Never hand-type a cite-id (AGENTS.md invariant 1). This
|
|
differs from a plain `[[Source - X]]` link, which only means "related to".
|
|
- **Notation inside code is notation, not a reference.** A `[^cite-id]` or a `[[wikilink]]`
|
|
written in backticks or a fenced block is read as an example: the citation does not count and
|
|
the link does not exist. That is what lets a page document this stack's own syntax. It also
|
|
means a marker appended to a line *inside* a fence cites nothing - put it on a source line
|
|
under the block (`<source-word>: [^cite-id]`, in the KB language), where it renders as a
|
|
footnote instead of travelling with the command when someone copies it.
|
|
- A source cited inline must also appear in the page's frontmatter `sources:` list;
|
|
`wikitool lint` checks this in both directions, and hard-errors on a leftover pre-migration
|
|
`^[[...]]` marker, an undefined `[^cite-id]` reference, or an orphaned Footnotes definition.
|
|
`tools/wikitool cite sync` reconciles a page's block after a prose edit changes which ids are
|
|
actually referenced.
|
|
- `tools/wikitool xref link-source --source "Source - X" --entities A,B,C` adds a new source
|
|
to every page it backs in one pass.
|
|
- Every raw file is expected to be claimed by some source page;
|
|
`tools/wikitool sources coverage` lists the ones that are not.
|
|
|
|
If no raw file or existing page backs an answer, say so explicitly rather than synthesizing
|
|
one - and never file the synthesized version back into the wiki.
|
|
|
|
## Confidence
|
|
|
|
`confidence_base` is the undecayed score set when a page's content is last confirmed;
|
|
`confidence` is *derived* from it by `tools/wikitool confidence decay` and must never be
|
|
edited directly.
|
|
|
|
Re-assess a page with `tools/wikitool touch --page "<Title>" --confidence-base <value>`.
|
|
|
|
What the number *means* - the base score, what raises it and by how much, and how to hedge in
|
|
prose below a threshold - is a rubric rather than a mechanism, so it is
|
|
[kb/CONVENTIONS.md § Confidence rubric](CONVENTIONS.md#confidence-rubric)'s.
|
|
|
|
## What does not belong here
|
|
|
|
- Raw source material - it stays immutable under `raw/`.
|
|
- Type definitions, frontmatter contracts, or templates - those live in `types/`.
|
|
- Procedures for operating the tooling - those live in `instructions/`.
|
|
- **Anything an instance would have to rewrite for itself** - language, naming forms, tone,
|
|
relationship labels, the confidence rubric. Those are `kb/CONVENTIONS.md`'s, and a sentence
|
|
of that kind here is a sentence the stack ships over the instance's own answer.
|
|
- Rules that apply to only one collection - those belong in that collection's
|
|
`COLLECTION.md`.
|
|
- Hand-edited generated files - see [Generated files](#generated-files).
|
|
- Generated lint reports - they are written to `reports/` and are not pages.
|
|
- Answers with no source behind them.
|