Skip to content

Curated knowledge is one kind with a class, not a second store

Curated knowledge is one kind with a class, not a second store

majordomus://adr/adr-0010proposed knowledge

it references

  • put_in_force .ai/repo/knowledge/sources.yaml (file)
  • put_in_force share/kinds.yaml (file)
  • put_in_force test/cases/64_knowledge_discovery.sh (test)
  • put_in_force test/cases/73_knowledge_nodes.sh (test)

referenced by

Nothing in the layer names it. Backlinks are derived, so an empty list is an answer rather than an omission.

10. Curated knowledge is one kind with a class, not a second store

Context

The layer already discovers everything it holds the same way: .ai/repo/knowledge/sources.yaml names a source class, a kind and one pathspec, and majordomus knowledge sources reports every tracked file that matches, with the class that claimed it. Policies, scopes, rules, decisions, sessions and use cases all arrive through that one mechanism.

Notes a repository writes about itself — what to read first, a convention somebody settled, a constraint the tooling cannot express, a lesson paid for once — did not fit any existing kind, and they are the kind of thing a project accumulates continuously. The obvious move was a second store: a directory of notes with its own reader, its own front matter and its own discovery, kept beside the layer rather than inside it.

The question this decision answers is not where the notes live. It is whether a new sort of knowledge earns a new mechanism, or whether it is a value in a field of the mechanism that already exists.

Decision

Curated knowledge is the knowledge kind, discovered by the curated source class like every other kind, and the distinction between a fact, a convention, a constraint, a memory and a lesson is carried by a required class field inside the record.

share/kinds.yaml:192 declares the kind: Markdown, front matter required, schema majordomus.knowledge/v1, identity [id]. .ai/repo/knowledge/sources.yaml:108 declares the class: kind: knowledge, discovery: vcs, pathspec :(glob).ai/repo/knowledge/curated/*.md. share/schemas/majordomus/knowledge/knowledge.v1.schema.json:51 makes class required with a closed enum — fact, convention, constraint, memory, lesson — beside the other required header fields, of which status (candidate/verified/superseded) and epistemics (observed/inferred/decided) say how far the statement is to be trusted and where it came from.

Nothing about a curated note is special to the reader. Its node kind comes from the source class that discovered it, not from anything in the file: test/cases/73_knowledge_nodes.sh:91 asserts exactly that, against a fixture whose body talks about rules while its class says otherwise.

Alternatives rejected

A second store with its own reader. A notes/ directory outside the layer's source classes, read by its own code path. It was rejected because every consumer the layer has would have needed a second one. Discovery is one list (knowledge sources), and the graph is built over what that list returns, so a store outside it is invisible to knowledge nodes, knowledge edges, the index the Rust executable builds, the site projections derived from that index, and every gate that reads any of them. The cost is not the reader; it is that each of those grows a special case, and a query that is true of the layer stops being true of the repository.

A kind per sort of note — fact, convention, constraint each a kind of its own. That keeps one discovery mechanism but multiplies the schemas, the allow-lists generated from them and the source classes, and it makes reclassifying a note a rename plus a move rather than an edit of one field. The sorts also share every other field: a lesson and a convention differ in what they claim, not in what they carry.

Leaving the sort implicit, in prose or in tags. Rejected because a reader cannot narrow on it: knowledge nodes --kind selects on kind, and with one kind for all curated notes the class is what remains to select on. A tag would do the same work with no closed set and no schema to refuse a typo.

Consequences

A curated note is subject to the whole of the layer's discovery contract, not a corner of it. It is discovered through the version-control index, so an untracked file is not knowledge, and the :(glob) prefix means * never crosses a directory separator — test/cases/64_knowledge_discovery.sh:73 asserts that no file is discovered by two classes, having been written after dropping that prefix made every handover under .ai/local/ arrive as shared repository knowledge.

The class is a closed enum, so adding a sixth sort of note is a schema change with a regenerated allow-list (share/allow/knowledge.txt, generated from the same schema by majordomus generate), not a new directory. That is the intended friction: the cost of a new sort is one review of whether the five existing ones really fail to hold it.

Every field a curated note carries is one the rest of the layer already understands — provenance.origin and provenance.derived_from with typed references that must resolve, and relations with the layer's own relation types — so a note participates in the knowledge graph rather than sitting beside it, and a note that cites a file which no longer exists is a finding of the same check that judges every other record's references.

What this forecloses is a per-sort schema: a constraint cannot grow a field that a lesson does not have without every knowledge record gaining it as optional. Where a sort needs its own shape, that is evidence it is a different kind, and the question returns to share/kinds.yaml.

One gap is worth stating plainly, because the decision's own contract implies more enforcement than the tree has. The schema declares class required, and the generated allow-list refuses an unknown key — but a record with the key missing is still reported as a node by majordomus knowledge nodes, since the reader takes the node's kind from the source class. So "every curated note declares its class" is today a property of the two records that exist rather than one a gate holds.

Where this comes from

canonical file
.ai/repo/adrs/0010-curated-knowledge-is-one-kind-with-a-class-not-a-second-stor.md
identity
adr-0010
also served as
MCP resource majordomus://adr/adr-0010 · majordomus entity show adr/adr-0010 · GET /api/v1/entity?uri=majordomus://adr/adr-0010
in the Cockpit
/cockpit/objects/adr/adr-0010

This page is generated from the file above by scripts/generate-site-data; editing the page changes nothing, editing the file changes every surface. The relations above are edges of docs/generated/graph.json, which the executable writes from the same index.

Searches the titles and descriptions of every page this site publishes.