Skip to content
C.W.K.
Lesson 04 of 06 · published

Inferred, Encountered, Cooked

~13 min · evidence, provenance, sqlite-views, ui-labels

Level 0Mise en Place
0 XP0/43 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

How does the record know?

Every dish and variant in Sizzle answers one question beside its name: how do we know about this one? The architecture doc gives three answers. Encountered means a plate proves Dad ate it. Cooked means Dad made it. Inferred means I derived it and no plate exists yet. Invariant 5 says the three stay distinct everywhere a dish or variant appears, and the doc gives the reason in one line: an inferred sibling never looks like a tasted one.

The reason is the way the tree grows. One reading of a plate of gambas al ajillo can propose the dish, its principle, and up to five siblings from other cuisines. Without a status, a tree holding one real plate would look like a tree holding six.

Computed, never stored

There is no evidence column in classes. Each time the store reads a class, klass calls evidence, which runs a query and returns a status. For a dish or variant, the query collects the distinct encounter kinds of the plates linked to that class. Then one line decides:

  • any linked plate of kind home: cooked
  • otherwise, any linked plate at all: encountered
  • no linked plate: inferred

The order matters. Cooked wins over encountered, so a dish Dad ate out and later made at home reads cooked. And since nothing is stored, nothing can go stale. A new link, a re-read, or a plate whose kind Dad changes from eaten out to cooked at home moves the status the next time the class is read, with no update step anyone could forget.

Which links count

The query reads current_links, a view over links. The view always keeps Dad's own links, and keeps a reading's links only while that reading is the plate's current one. If a plate is re-read and the new reading no longer sees a dish, the old reading's link stops counting, and the dish can fall back to inferred. A link Dad made by tying the plate himself survives every re-read. It works upward too: if Dad cooks aglio e olio at home and ties that plate to the inferred sibling (on today's clients, by applying a link action I propose in the plate's conversation), the link is his, the class is adopted in the same step, and the badge reads Cooked the next time the page loads. Track 4 of this quest is about that view. Here it is enough to see that evidence is built on it.

A principle borrows from its children

Plates show dishes, and a reading only ever links a plate to a dish or a variant. The domain doesn't forbid more: link checks that the class exists, never its kind, so applying a link action I propose in a plate's conversation can tie the plate to a principle itself. The principle's evidence never reads that link. Its evidence comes one step down. The principle branch of the query joins class_parents to find its direct children, then reads their current links. A principle with one home-cooked dish under it is cooked.

Direct children only. A variant is born with one parent, its dish, so in the usual case a variant's own link does not reach the principle: cooking a variant at home makes the variant cooked and leaves the principle where its dishes already put it. The exception comes from a reading. integrate resolves a dish entry against dishes and variants alike, by id or by name, and then parents whatever it found under the principles the entry named. Once a later plate is read as the variant, the variant sits directly under a principle, and from then on its home plate makes that principle cooked. The two clients differ here as well. The web hides a principle's own badge and shows badges on the dishes under it. The phone shows the badge on every class page, principles included.

The words on the badge

The web labels the statuses Pippa's inference, Eaten and Cooked, and the Tree page puts a legend of all three above the list. The phone shows the status word itself with an icon: sparkles for inferred, a fork and knife for encountered, a frying pan for cooked. The engine's tests pin the rule. In test_tree.py, a dish the reading saw is encountered while its sibling stays inferred, and a variant tied to a home plate is cooked.

Sizzle's Tree page, My class tree, with the legend Cooked, Eaten and Pippa's inference above a list of principle cards. Each card has a Korean principle name, a Proposed status and a one-line summary, then its dishes as chips, some marked Eaten and others Pippa's inference.
The Tree page with its legend above the list. The principle cards carry no evidence badge of their own; the dishes under them do, Eaten for a plate Dad met and Pippa's inference for a sibling no plate has proven yet.

Read the code beside those labels and two small gaps show. First, the rule counts any linked plate as encountered, whatever its kind. A plate Dad photographed at a market, or one filed as other, makes a dish encountered too, and the web calls that Eaten. The doc's wording, a plate that proves Dad ate it, is narrower than the query. Second, invariant 5 asks for the status everywhere a dish appears, and on the phone one list misses it: the dishes under a class page carry the proposed or adopted chip and no evidence chip. The Tree screen and each class's own header do show it. The first gap can overstate a market plate. Neither lets an inferred class look tasted.

Principle: When a status is derived from records, derive it at read time from the same records the user can inspect. Then the badge and the evidence behind it cannot disagree, and the only thing left to check is whether the label says what the query means.

Code

cwkSizzle, backend/store.py: evidence as a query, with a principle reading its direct children (verbatim, lines 465-480)·python
    def evidence(self, class_id: str, kind: str) -> dict[str, Any]:
        if kind == "principle":
            rows = self._all(
                "SELECT DISTINCT e.kind FROM class_parents p JOIN current_links l ON l.class_id = p.child"
                " JOIN encounters e ON e.id = l.encounter_id WHERE p.parent = ?",
                (class_id,),
            )
        else:
            rows = self._all(
                "SELECT DISTINCT e.kind FROM current_links l JOIN encounters e ON e.id = l.encounter_id"
                " WHERE l.class_id = ?",
                (class_id,),
            )
        kinds = {r["kind"] for r in rows}
        status = "cooked" if "home" in kinds else "encountered" if kinds else "inferred"
        return {"status": status}
cwkSizzle, backend/store.py: the view evidence is built on (verbatim, lines 115-119)·text
-- A reading's links count only while that reading is the encounter's
-- current one; Dad's own links always count.
CREATE VIEW current_links AS
    SELECT l.* FROM links l JOIN encounters e ON e.id = l.encounter_id
    WHERE l.source = 'dad' OR (l.source = 'reading' AND l.reading_id = e.reading_id);
cwkSizzle, frontend/src/ui.tsx: the web's three labels and the badge (verbatim, lines 17-30)·typescript
const EVIDENCE_LABEL: Record<Evidence, string> = {
  inferred: "Pippa's inference",
  encountered: "Eaten",
  cooked: "Cooked",
};

export function EvidenceBadge({ status }: { status: Evidence }) {
  return (
    <span className={`evidence evidence-${status}`} title={EVIDENCE_LABEL[status]}>
      <span className="evidence-dot" aria-hidden />
      {EVIDENCE_LABEL[status]}
    </span>
  );
}

External links

Exercise

Find a place in software you build where generated or imported records sit next to records a person confirmed, such as suggested tags, auto-matched contacts, or model-written summaries. Define a provenance status with at most three values, write the query that computes it from records you already keep, and write the label each value shows. Then read each label next to its condition and fix any label that claims more than the condition proves.
Hint
Compute the status at read time instead of storing it, so it cannot drift from its evidence. Decide which status wins when several apply, the way cooked beats encountered. If a parent's status is aggregated from children, say how far down it looks.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.