The tree grows; it is never imported
Invariant 6 in the architecture doc has two halves. First, no pre-seeded taxonomy: Sizzle starts with an empty tree, and the Tree page says so until the first plate is read. Second, proposals stay proposals until Dad adopts them. Every class I create starts as one. The principles and dishes a reading names and every sibling it infers are written with a status of proposed and an origin of reading or sibling.
The doc names the way out in one sentence: a proposal joins Dad's tree when he adopts it, renames it, or ties a plate to it, and it stays visibly a proposal until then. The code has exactly those three doors.
Three doors in
| Door | How Dad opens it | What is recorded |
|---|---|---|
| Adopt | Presses Adopt into my tree, or applies an adopt action I proposed | class.adopted |
| Rename | Renames the class, or applies a rename action | class.renamed, whose projection also sets the status to adopted |
| Tie a plate | Applies a link action I proposed in that plate's conversation | class.linked with source dad, then class.adopted if the class was still a proposal |
Look at where rename's adoption happens. rename in the domain records only the new name. The projection, _on_class_renamed, sets the status to adopted in the same UPDATE. So the rule that renaming is adopting lives where the journal is replayed, and every rebuild applies it again.
Tying is the door that is also evidence. link writes a link with source dad, and when the class was still a proposal, it records class.adopted right after. A tied plate says this plate is that dish. A class Dad vouches for with a plate cannot stay my guess. The engine also has a direct route for it, POST /api/encounters/{id}/links, but neither client calls it today, so on both the tie arrives as an action from a conversation.
What does not adopt
- A reading linking its own plate. Those links carry source
readingand adopt nothing. A dish can be encountered and still a proposal. - Dad editing a field. Saving a verdict or exact amounts goes through
PATCH /api/classes/{id}, which recordsclass.revisedand leaves the status alone. - My suggestion by itself. An adopt, rename or link action I propose waits on the turn until Dad applies it. Applying it is what calls the domain method.
One kind of class is born adopted: a variant. derive_variant creates it with status adopted and origin dad, because Dad made it, in the form or by applying a variant action I proposed.
Why the status matters
Adoption is the moment the words change owners. While a class is a proposal it is my current understanding, and a newer reading may rewrite its description, my voice under a new rubric included. Once it is adopted it is Dad's, and readings leave its words alone. Proposal Versus Adoption: Who Owns the Words, in Track 4, shows the guard that enforces it.
The status also shapes what Dad sees. The web's chip reads Proposed or In my tree, the phone's reads proposed or adopted, and both offer Adopt into my tree only while a class is a proposal. The Tree page lists adopted principles first. My context carries it too: the compact tree that every reading and conversation hands me lists each class with its status, so when I talk about the tree I can tell Dad's classes from my own guesses.
A one-way door
No event turns an adopted class back into a proposal, and no event deletes a class. Adoption is final in this version of the record. That suits a tree Dad grows by hand. It also means the adopt button deserves a moment's thought, because after it the only way to change a class is to edit it.