The router: what kind of sentence, and about what
1. What kind of sentence, and about what?
Every sentence is one of four kinds: an answer to something we asked, a correction of something we did, a query (asking us something), or an action (asking us to do something). The kind is decided first, from the words. The subject is decided second. The module receives both.
- Before the four kinds, the router discards what is not aimed at the app at all: background conversation, or nonsense that fits no kind and no subject. That is where "I didn't understand that" lives. A food-shaped sentence with an unfamiliar food is not nonsense; it goes to food, which searches for it (part 2).
- The order is deliberate. An answer is checked first because we know exactly what we asked and what an answer to it can look like. A correction second, because "no, it was Dave's" is not a new food even when nothing is waiting. Then query or action, then the subject.
- A sentence that names new foods and has no "yes", "no", or "number 2" in it is never an answer. That one rule would have kept "two bananas and a quarter cup of cottage cheese" out of the Chobani question.
- Only the subject decision may involve a model, and only when the words alone can't say what the sentence is about. The three kind decisions are settled by rules.
1b. The same thing as a case table
Kind down the side, "nothing waiting" and "waiting for an answer" across the top, an outcome in every cell. The diagram is only right if no cell is empty or wrong. This is the check a reviewer should run on the code too.
| Kind | What the person said | Nothing is waiting | We are waiting for an answer |
|---|---|---|---|
| Noise | Nonsense, or background talk not aimed at the app ("three flibjopolis", two people chatting) | Disregard it if it reads as background; otherwise say "I didn't understand that" and stop. Never logged, never routed. | Same; the waiting question stays and is asked again once. |
| Answer | A tap on one of the choices | Cannot happen; no choices are on screen. | That choice is the answer; to the module that asked. |
| Answer | "Yes", "no", "number 2", "the second one", one of the names offered | Nothing to answer. Try the rows below; if none fits, say "I wasn't asking anything" and stop. | The answer; to the module that asked. |
| Answer | "I don't know", "not sure", "just estimate it" | Nothing to answer; treated as the rows below. | The answer; the module ends its question honestly (an estimate said plainly, or the assumed amount), never a dead end. |
| Answer | "Cancel", "never mind", "forget it" | Nothing to cancel; say so. | Close the question. Nothing is written. |
| Answer | "Um", "hmm", a half word | Ignore it. | Ask the same question again, once. |
| Correction | "No, it was Dave's", "change that to 3/4 cup", "delete the eggs", "no, faster" | To the module that owns what is being corrected (food, or the app for a setting). | If it is about the thing the question is about, it replaces the question. Otherwise the question is set aside, the correction runs, then the question is asked again if it still matters. |
| Query | About a module's data: "how much protein today", "what did I bench last time" | To that module as a query; answered from the log; nothing written. | Same; the waiting question is set aside the same way. |
| Query | About the app: "what voice speed is set", "what model are you using" | To the app module; answered; nothing written. | Same; set aside. |
| Query | Across modules: "what did I do today" | A small reporting job of its own, reading every module; nothing written. | Same; set aside. |
| Query | About nothing we track: "weather tomorrow" | Declined, or handed to a model, by policy; never logged. | Same; the waiting question stays and is asked again. |
| Action | Log something: new foods with no yes/no/number in it, "log a to-do", "start my workout" | To that module as an action. | Same; the waiting question is set aside, asked again after, or dropped if the new sentence covers the same thing. |
| Action | A module's own setting: "stop telling me protein", "always assume Dave's" | To that module as a setting change; confirmed in one sentence. | Same; set aside. |
| Action | The app's own setting, state, or screen: "speak slower", "mute", "go to the food screen" | To the app module. | Same; "mute" also closes the waiting question, like cancel. |
| Action | Nothing we can do: "order a pizza" | Declined by policy. | Same; the question stays and is asked again. |
| ? | The rules find nothing above | One short question, never a chat reply. | One short question: "Is that for the yogurt, or something new?" |
- The rows are tried in this order. A sentence that fits an earlier row never reaches a later one.
- "Set aside" always means the same thing: the question is no longer open while the new sentence is handled, so nothing said next can accidentally answer it. It is re-asked in one sentence afterwards, or dropped.
- Two of this morning's failures are two cells here. The bananas were the first Action row, right column, and today's code has no rule there. The Chobani "Yes" was the second Answer row, applied to a question that should already have been set aside.
Inside the food module
2. Inside the food module
Five doors in, matching the five kinds the router can send: a new food to log, an answer to a question we asked, a correction or an edit, a question about food, a food setting. One central lookup that every path uses. Two tracks that never trade places: which food it is, and how much. One hand-off out, to the part of the app that saves, shows the card and speaks.
Connectors: L the central lookup · J judging the candidates · C that food, chosen · A the amount step · F fit an interpreted measure to the row · M ask a model why the question is stuck (part 3) · U estimate the amount (the person said they don't know) · W the web search · E the estimate-or-enter step · D the hand-off to the app.
- Back to the router. The router decides from words and never looks anything up; the food module does. So the module gets the first say on "is this food at all", and hands the sentence back marked "not food" when it is not. The router then tries the other subjects, and if none takes it, the "none of ours" cell applies.
- Correction versus edit. Same door, same machinery after the first box; the difference is only in finding the entry. A correction is about the thing we just did ("no, it was Dave's"); an edit is about an earlier entry ("change yesterday's lunch"). Correcting a confirmation while its question is still open is not a correction at all: it is an answer, caught at the top level. Once the entry is found, a change of food goes to the same central lookup as a new food, a change of amount goes to the same amount step, and a deletion removes the entry.
- One lookup (F11), one judgement (F12). Every source is searched at the same time, not one after another. The order of sources (your saved foods, then makers and restaurants, then USDA, then Open Food Facts) is how the results are ranked, not how they are fetched. There is one lookup box because there must be one lookup in the code. The judgement states the precision setting's meaning: rows that agree within it are one food, logged at the person's words with the range across them ("Quest bar", flavours as alternatives on the card); rows that differ beyond it are asked about.
- "Nothing usable" searches first (F16), then decides (F17), and it is never "gibberish". A food-shaped sentence whose food we cannot find, even on the web, is an unfamiliar food, not nonsense. The web search (the maker's or restaurant's own nutrition pages) runs first. If it finds nothing either: when we at least know the kind of food ("a plain bagel"), the app offers an estimate from the kind or to let them enter it; when we don't (a brand we have never seen), it says it can't find it and offers manual entry, by typing the numbers or scanning the nutrition label, with the barcode as a long shot since the name may have been misheard. Whole-sentence nonsense and background talk never reach this module; the router handles them (part 1).
- Cancel and "I don't know" are answers (F7, F7a, F7b), so they come in through the answer door whenever a question is open. Cancel closes the question and removes the entry from the log, and the app says so. "I don't know" is read by which kind of question was asked: to a which-food question, the offered rows are logged as a range at the person's words, or an estimate is made; to a how-much question, the amount is estimated as a range. The precision setting already decided that we should ask, so it is not consulted again. Neither is ever a dead end.
- "The same question is never asked twice" means exactly that: a second, different clarification may follow ("which one", then "how much"). When the rules would repeat one, something else is going on, and the rules cannot tell what. That is a model's job: see part 3. One case never reaches it: an answer that names something we did not offer ("strawberry" to a chocolate-oatmeal-mint question) is read by the rules as a new lookup of that product, with the brand kept, before any repeat could happen.
- Quantity and unit are two things, and an amount can be precise, imprecise, or missing (F6, F20). "3" and "ounces" are read separately. A precise amount is matched to the row's own measures (F23): the row's measure of the same kind the person used, weight or volume; a unit change within a kind (ounces to grams, cups to millilitres) is arithmetic; density is used only when the row gives one kind and the person gave the other. "A big bowl of oatmeal", "half a plate of spaghetti", "a handful", "a heaping teaspoon" are stated amounts, not missing ones: they are interpreted (F24) into a range for that food, always a range, and the detail card shows the words said and how they were read ("a handful of nuts", read as 1 to 2 tablespoons, 100 to 200 calories). Only a truly missing amount goes to "ask or assume" (F21).
- The entry is in the log from the moment it is said (F4). Each food is written as the person said it, marked as being worked out, while the module resolves it or asks about it. It leaves the log only by cancel (F7b) or delete (F8b). If it cannot be resolved, it stays: with a best estimate, or marked as unresolved, so the person can fix it later (a misheard name, a slip). Nothing said is ever forgotten.
- A question or a statement, never both (F25). When the module asks, nothing is finished. When it logs, it says what it logged and may add a statement, such as an assumption it made, which invites a correction but is not a question and does not wait for an answer.
- The hand-off. The module ends by preparing a result: what to save, what the card shows, what to say, and what question stays open. Saving, checking the save, showing the card and speaking are done by the app outside the module, the same way for every module. This is how the code is built today: the module returns write intents and a reply, and the shell applies, verifies, renders and speaks.
2b. The flowcharts behind the dots
One per dotted box, keyed by the box number, each to be drawn on the details page with its own diagram and case table. The one-line scope is what each must cover.
| Box | Sub-flow | What it must cover |
|---|---|---|
| F1 | Is this about food at all | What makes a sentence food (food words, amounts, brands, "I had"); what sends it back to the router; a mixed sentence ("log a to-do and I had an apple"). |
| F2 | One food, several, or a dish | A list joined by "and" or commas; a dish named with parts ("omelette with…"); a dish named alone ("a sandwich"); implied parts; which words belong to which food. |
| F3 | Splitting into foods | Each food keeps its words as said, its amount words, its brand words, its preparation words ("toast", "fried") set apart from the name; a dish gets a parent entry; when a model may reformat, returning the same shape. |
| F4 | Putting the entry in the log now | The provisional entry: written as said, marked as being worked out, shown in the log at once; updated as the module learns; removed only by cancel or delete; left marked if unresolved, with what was tried. |
| F5 | Classifying the food | Basic (an apple), packaged with a brand (Chobani), restaurant (a Chipotle bowl), prepared or homemade; whether a brand or restaurant is named; what each class means for which sources matter and what a serving looks like. |
| F6 | Reading the quantity and the unit | The quantity ("3", "a", "two", "half"), the unit (ounces, cups, grams, slices, a bar, a bottle), a size word ("large"), a range; precise versus imprecise versus missing; fractions and spoken numbers. |
| F7 | Reading an answer | A tap; a number or ordinal within the count offered; a name that is one of the offered names, whole or in part; a name not offered (a new lookup, brand kept); yes and no and what a bare yes means on each kind of question; "none of these"; "look it up"; "I don't know" by kind of question; cancel; an amount given along with a pick. |
| F8 | Finding the entry to correct or edit, and what changes | The thing we just did; the last entry; a named entry; an entry from an earlier day; when several fit; when none does. Then: the food (through F11, replacing the entry), the amount (through F20), delete, add a part to a dish; never a duplicate. |
| F9 | Answering a food question | Totals for today, a nutrient in one entry, what was logged when; answered from the log, shown on a card; nothing changes. |
| F10 | Changing a food setting | What the app says after a log, a default for a food, the precision profile; changed, saved, confirmed. |
| F11 | Looking the food up | Every source at once: saved foods, the catalogs; how the query is built and normalised (apostrophes, case, preparation words removed); ranking by source; a plausibility check on every row (serving size for the kind of food, calories per gram, a named source); never renaming a row. |
| F12 | Judging the candidates | Rejected rows dropped; a word-for-word match wins and variants become alternatives; rows that carry every spoken word; extra words that change the food (pepper, baked); agree within the precision setting → one food at the person's words with the range, alternatives kept; differ beyond it → several; one uncertain row → a confirmation that names what distinguishes it; nothing usable. |
| F13 | The clarification ladder | A numbered list within the cap; varieties named past it; a narrowing question inside a variety; a confirmation of one; the step after a rejection; the offer to search the web; the estimate step; each question asked at most once; how a "which one" question also carries "how much" when both are open. |
| F16 | The web search | The maker's or restaurant's own nutrition pages, once; how results are checked before they become rows; counting truthfully what is new; never random pages. |
| F17 | Do we at least know the kind of food | A known kind of food with no row, versus a name we cannot place at all; what "the kind" means (a bagel, a protein bar, a yogurt) and where it comes from. |
| F18 | Offer an estimate from the kind, or to enter it | An estimate from the kind of food, at the person's words, with their amount, as a range; the offer to type the numbers, scan the label, or scan the barcode; what happens with what they enter; rejected rows never return. |
| F20 | Precise, imprecise, or missing | Precise (a number and a unit the row can take), imprecise (a vessel, a hand, a size word), or missing; what is unusable and why. |
| F21 | Ask how much, or assume | The one choice the precision setting governs here: assume the usual serving with a plain note, or ask "how much?"; the shape of that question; an amount answer that arrives with a which-one answer. |
| F22 | Estimating the amount | The usual serving for this food, as a range; said plainly as an assumption, never as doubt; how "I don't know" lands here. |
| F23 | Matching the amount to the row's measures | The row's measures (often both weight and volume); pick the one of the same kind the person used; unit arithmetic within a kind; density only when the row has one kind and the person gave the other; count × serving; cooked versus dry; per-100 g rows; a range over several rows scaled to one basis first. |
| F24 | Interpreting an imprecise measure | Vessels (a bowl, a plate, a glass, a mug), hands (a handful, a pinch), spoons with modifiers (a heaping teaspoon), fractions of vessels (half a plate), size words (big, small, large); each becomes a range for that food, using the food's density and usual form; the card shows the words and the reading; what happens when the vessel makes no sense for the food. |
| F25 | Preparing the result | Either the finished entry with its statement (what was logged; any assumption, which invites a correction), or a question with what it offered recorded; what the card shows; what is said by voice versus shown in chat; the wording ladder; never explaining the app's doubts. |
| F26 | How the app delivers it | Outside the module: the entry updated in the log and the save checked; the card built; the sentence spoken; an open question held for the answer; what "unresolved" looks like in the log. |
| P | The precision setting | The three profiles; the one comparison it governs in judging (how far rows may differ and still be one food); the one choice it governs for a missing amount (assume or ask); what it never does: change an amount's value or override a stated one. |
- Where these come from: the requirements document (sources in section 5, amounts in 6, the precision setting in 6.3, the ladder in 10, corrections in 11, rejection in 12) and the code as it stands, used as a record of the thinking, not as the truth.
- The clarification ladder is one box on purpose. Today it is spread across several places that disagree; the box is the statement that it should be one thing.
When a model is consulted
3. When a model is consulted
One rule everywhere: the rules run first; a model is asked only at the marked points; it is given the node's own rules and the words as said; it answers in a fixed JSON shape that the rules then apply; it never speaks to the person; and if its answer does not fit the shape, the node takes its own safe outcome. Every model call is recorded in the trace like any other decision.
3b. Every point where a model may be consulted
Anything not on this list runs on rules alone. Each row says why the rules are not enough there, what the model is given, what it must return, and the safe outcome if it fails.
| Where | Why rules alone are not enough | Given | Must return (JSON) | If unusable |
|---|---|---|---|---|
| Part 1 · noise | Whether a sentence is aimed at the app at all can't always be read from words. | The words; whether a question is waiting. | aimed-at-app: yes / no. | Treat as aimed at the app. |
| Part 1 · the kind | Answer / correction / query / action is decided by rules; a model is asked only when the rules find no row of the case table. | The words; the waiting question and what it offered; the rules for the four kinds. | kind, and the part of the sentence that shows it. | One short question to the person ("Is that for the yogurt, or something new?"). |
| Part 1 · the subject | Food, workout, to-dos, the app: usually plain from the words; not always ("log 20 minutes"). | The words; the list of subjects. | subject, confidence. | One short question to the person. |
| Part 2 · splitting the sentence | Grammar handles most sentences; a long or oddly worded one may not split cleanly. | The words; the shape the rules use (foods, each with amount, brand, preparation words). | The same shape, with the words as said kept per food. | Treat the whole sentence as one food and let the lookup say what it finds. |
| Part 2 · the web search | A maker's nutrition page is prose and tables; a model turns it into a row. | The page text; the row shape; the food's words. | Rows, each with serving, calories, macros, and the sentence on the page it came from. | Discard the page; the search found nothing there. |
| Part 2 · a question would repeat | The rules can see the repeat but not the reason (part 3 above). | The question, its offered choices, what the person said, the turn so far, the five reasons. | One of the five reasons, with its payload. | Log with the best honest estimate and say so, or close the question. |
| Part 1 · none of ours | An outside question ("weather tomorrow") is answered by a model or declined, by policy. | The words; the policy. | An answer, or a decline. | Decline. |
- What a model is never asked: which food the person meant, whether two rows are the same food, what the amount is, whether to log or ask. Those are the rules' decisions from facts, and a model's guess there is how we got the "meal or snack?" reply.
- Two model points exist in the code today that are not on this list and should go: the ownership check that decides answer-or-new for anything outside a short list (it is a coin flip), and the general chat reply that answers a food sentence when the food route rejects it.
F1 · Is this about food at all
Given: the sentence the router sent, as said; its kind (an action to log) and subject (food) from the router
Outputs: continue as food; or back to the router as "not food"; or the food part kept and the rest handed back
| The person said | What this box does | Why |
|---|---|---|
| "I had two eggs" | Food; continue. | A food word and an amount. |
| "Chobani" | Food; continue. | A bare product word is a food said without an amount. |
| "I ate at Chipotle" | Food; continue (F5 will class it as restaurant). | A venue with "ate" is a food sentence even with no item named. |
| "Log a to-do to buy Chobani" | Back to the router as "not food". | The sentence is a to-do; the food word is its object. |
| "I had a great workout" | Back to the router as "not food". | No food word; "had" alone is not enough. |
| "I had an apple and remind me to buy milk" | Keep "I had an apple"; the rest goes back to the router. | Two sentences in one; each to its own module. |
| "Three flibjopolis" | Food; continue to the lookup. | A food-shaped sentence with an unknown word is an unfamiliar food, never nonsense (F16, F17). |
- This box exists because the router decides from words and never looks anything up. The module knows food better, so it gets the first say on "is this food". Handing back is normal, not an error.
- Nothing here reads a list of food names. "Something eaten" is recognised by shape: a noun after "had / ate / drank", an amount with a unit, a brand or product word, a venue.
F2 · One food, several, or a dish
Given: the food sentence as said
Outputs: one food; several foods; a dish with a parent and parts (stated or implied); a saved meal
| The person said | What this box does | Why |
|---|---|---|
| "two eggs" | One food. | One noun, one amount. |
| "eggs and toast" | Several: eggs; toast. | A list, no dish word. |
| "an omelette with three eggs, a quarter cup of cheddar and a sliced tomato" | A dish: parent "omelette"; parts eggs (3), cheddar (1/4 cup), tomato (1). | A dish word with parts. |
| "a sandwich" | A dish with implied parts. | A dish word alone; bread and a filling are implied; the filling is a core part → asked (§7). |
| "oatmeal with blueberries" | Several: oatmeal; blueberries. | "with" on a plain food joins two foods; no dish word, so no parent. |
| "a bowl of oatmeal with berries" | Several: oatmeal (a bowl — imprecise, F6); berries. | The vessel belongs to the amount of the first food, not to a dish. |
| "my Breakfast A" | Several, from the saved meal. | A saved meal is a named list. |
| "a turkey sandwich on Dave's Killer Bread with 3 ounces of turkey and romaine" | A dish: parent "turkey sandwich"; parts bread (Dave's), turkey (3 oz), romaine. | "on" and "with" after a dish word give its parts. |
- Which words are dish words is data (the rule pack's dish forms), never a list in decision code, and it is a class rule: it must handle omelette, sandwich, salad, wrap, bowl, burrito, smoothie alike.
- A dish counts once in the day's total: the parent shows the sum of its parts (§7).
F3 · Splitting into foods
Given: the sentence and its shape (one, several, a dish)
Outputs: one part per food: words as said, amount words, brand and variant words, preparation words; a dish's parent
| The person said | What this box does | Why |
|---|---|---|
| "two sunny side up eggs and one slice of Dave's killer bread toast" | Part 1: words "sunny side up eggs", amount "two", preparation "sunny side up". Part 2: words "Dave's killer bread", brand "Dave's killer bread", amount "one slice", preparation "toast". | "toast" is how the bread was prepared; it never goes into the product's name — that is what sent the lookup to the web for 41 seconds this morning. |
| "an omelette with three eggs a quarter cup of Cheddar cheese and one sliced tomato" | Parent "omelette". Parts: eggs (3); Cheddar cheese (1/4 cup); tomato (1, preparation "sliced"). | The dish word heads the sentence; "with" opens its parts. |
| "a half a cup of strawberries and a half a cup of fair life fat free milk" | Two parts, each with its own amount; part 2 brand "fair life", variant "fat free". | Each amount stays with its own food. |
| "I had a Chobani cherry yogurt" | One part: words "Chobani cherry yogurt", brand "Chobani", amount: none (a count of one is implied by "a" — F6). | The words as said become the entry's name if the lookup ends in a cluster (§5.2). |
| "I had a Quest cookies and cream protein bar" | One part; the "and" inside a product name does not cut. | A cut is made only where both sides are foods; "cookies and cream" is a flavour of one bar (a model reformat may be needed here — F3.6). |
- The words as said are the one thing every later box must preserve. Renaming a row to these words, or these words to a row, is the fault the assessor found behind the Chobani tube.
- A model may be used only at F3.6, only to produce the same shape, and never to decide what a food is.
F4 · Putting the entry in the log now
Given: the parts from F3, with their words and amounts as said
Outputs: one provisional entry per part, visible at once, updated in place; removed only by cancel or delete
| The person said | What this box does | Why |
|---|---|---|
| "I had a cup of Chobani yogurt" and the app asks which one | The entry "Chobani yogurt, 1 cup" is in the log at once, marked "waiting for your answer". | Nothing said is ever invisible while it is being worked on. |
| The person answers and it is logged | The same entry is updated with the food, numbers and range; the mark is cleared. | Never a second entry. |
| The person says "cancel" | The entry is removed. | Cancel is one of the two exits. |
| The app cannot find it and the person does not enter it | The entry stays, marked "unresolved", with "couldn't find; you can add the numbers or scan the label". | It can be fixed later; a misheard name is not a lost meal. |
| The app was closed mid-question | The entry is still there next time, marked; the question is not re-asked out of the blue — the card offers it. | The log is the record; the conversation is not. |
| An amount was assumed | The entry shows the assumption on its card ("assumed 1 medium"). | A stated assumption invites a correction; it is not a question. |
- This is the policy Howard set on 2026-09-23: it appears in the log as soon as the person says it, and nothing is lost unless they cancel or delete it.
- What the app was closed mid-question should do (re-offer the question on next launch, or just leave the mark) is a choice to confirm with Howard; the row above shows the safer reading.
F5 · Classifying the food
Given: one part: its words as said, brand, venue and variant words
Outputs: one of: restaurant, packaged, prepared, basic — and the class rules that apply
| The person said | What this box does | Why |
|---|---|---|
| "a Chipotle chicken bowl" | Restaurant. | A venue name with an item. |
| "a Quest bar" | Packaged. | A brand and a product form; the bar is the amount. |
| "an apple" | Basic. | Single ingredient, no brand. |
| "my mom's lasagna" | Prepared. | Home-made; no catalog product. |
| "chicken breast" | Basic; raw-vs-cooked is a class question (§6.8) answered later. | The class does not decide identity, only which rows matter. |
| "cottage cheese" | Basic; dairy fat level is identity when stated (§8). | A class rule shapes the candidates; the setting still decides whether to ask. |
| "Dave's killer bread" | Packaged. | A brand. |
| "a protein shake" | Packaged (form only, no brand). | The form says which sources matter even without a brand. |
- The class never decides what the food is. It decides which sources are worth searching first, what a serving looks like (a bar, a bottle, a menu portion), and which class rules of §8 apply.
- Today's code has a packaged-food class list (protein shake, yogurt cup, protein bar, snack bar, bread slice, packaged food). That is a data table of forms, which is allowed; a rule about one product is not.
F6 · Reading the quantity and the unit
Given: one part's amount words, size words and modifiers
Outputs: quantity; unit; size; and one of: precise, imprecise, not-an-amount, missing
| The person said | What this box does | Why |
|---|---|---|
| "3 ounces of turkey" | Precise: 3, weight (oz). | A number and a weight unit. |
| "a cup of blueberries" | Precise: 1, volume (cup). | "a" is one when a unit follows. |
| "two eggs" | Precise: 2, count (eggs). | A count of the food itself. |
| "a Quest bar" | Precise: 1, package (bar). | A bar is a known quantity for a packaged food (§6.2). |
| "one and a half cups" | Precise: 1.5, volume. | A spoken mixed number. |
| "a big bowl of oatmeal" | Imprecise: vessel "bowl", size "big". | A vessel is quantity evidence, not a measure; read as a range in F24. |
| "some peanuts" | Imprecise: vague. | "Some" gives a configurable range (§6.6), never zero information. |
| "a handful of nuts" | Imprecise: hand measure. | Read as a range for this food. |
| "half a plate of spaghetti" | Imprecise: fraction of a vessel. | A plate has no defensible food volume; the vague-serving range applies (§6.7). |
| "chicken" | Missing. | No amount words; F21 decides ask or assume. |
| "a 42 g protein shake" | Precise: 1 package; "42 g protein" is identity, not an amount. | A nutrient figure describes the product. |
| "a scoop of protein powder" | Precise only once the product is known; otherwise treated as missing. | A scoop has no universal size (§6.2). |
| "two slices of Dave's killer bread" | Precise: 2, count (slices) — usable only against a per-slice row (F23). | A stated unit whose size no source established keeps its question (§6.2). |
- Quantity and unit are read as two things because the unit is what F23 matches to the row's measures and the quantity is what multiplies it.
- The last, most explicit amount in one sentence wins when two are said (§6.6). An amount said later, in an answer, beats one said now (§11).
F7 · Reading an answer
Given: the answer as said; the open question's record (kind, offered names and count, what a bare yes means, the rejected list)
Outputs: a choice; a hold; a cancel; a rejection; a wider search; an I-don't-know by kind; a new lookup; a choice with an amount; or the stuck-question consult
| The person said | What this box does | Why |
|---|---|---|
| Tap "Good Seed" | That choice. | A tap is exact. |
| "number 2" to a list of three | The second offered choice. | Within the count. |
| "number 5" to a list of three | Nothing picked; the question stands. | Past the count; not an amount. |
| "the seedy one" to Good Seed / Whole Wheat / Powerseed | Rules cannot read it → M1 (part 3); the model may map it to "Good Seed". | Not one of the recorded names. |
| "yes" to "I think you mean X. Is that right?" | X taken; logged. | The record says a bare yes confirms X. |
| "yes" to "Which one — 1, 2, or should I log an estimate?" | The estimate. | The record says the sentence's last offer was the estimate. |
| "no" to "Is that right?" | X rejected; the ladder continues. | A bare no on a confirmation rejects the one product named. |
| "none of these" to a list | Rejection; those rows and their varieties' rows join the rejected list. | What the sentence offered decides. |
| "never mind" to "Which one?" | Cancel; the entry leaves the log. | Cancel words end the turn. |
| "look it up" to "Which Dave's Killer Bread?" | Search wider (F16), no model. | The lookup command on a which-food rung. |
| "look it up" to "How much did you have?" | Not a lookup reply; read as an unrecognised answer → M1. | Only which-food rungs take the lookup command. |
| "I don't know" to "Which one?" | The offered rows logged as a range at the person's words. | I-don't-know on a which-food question. |
| "I don't know" to "How much?" | The amount estimated as a range (F22). | I-don't-know on a how-much question; the setting is not consulted again. |
| "strawberry" to chocolate / oatmeal / mint | A new lookup: Quest strawberry. | A name not offered is a product to find. |
| "number 1, two slices" | The first choice, with the amount 2 slices. | An amount given with a pick. |
| "um" | The question is said again, once. | Thinking sounds hold. |
- Every decision here reads the question's record — its kind, the names and count it offered, what a bare yes means — never the question's sentence. That record is written by F25 when the question is asked.
- A model is consulted only at the end (F7.12), and only to say which of five things happened (part 3). It never picks a food.
F8 · Finding the entry to correct or edit, and what changes
Given: the correction as said; the log; the entry we just did
Outputs: the entry; and one of: a food change (to F11), an amount change (to F20), a deletion, a dish-part change; or a which-entry question
| The person said | What this box does | Why |
|---|---|---|
| "No, it was Dave's killer bread" right after "Logged toast" | The toast entry; the food changes → F11 with "Dave's killer bread"; replaces the entry, keeps one slice. | A correction of the thing just done. |
| "Change that to 3/4 of a cup" | The last entry; the amount changes → F20 with 0.75 cup. | Amount only; no lookup; never "which exact … should replace". |
| "Delete the eggs" | The eggs entry removed. | Named entry; delete. |
| "Change the half a cup of fairlife milk to a half a cup of Friendly's cottage cheese" | The milk entry found by its words; the food changes → F11 with "Friendly's cottage cheese", amount ½ cup kept. | An edit of a named entry. |
| "Make yesterday's lunch two bowls" | The lunch entry from yesterday; amount changes. | Found by day. |
| "Change the eggs" when two egg entries exist | "Which eggs — 1. the two at breakfast, 2. the omelette's?" | Ambiguous reference asks; never guesses. |
| "Change the milk" when no milk entry exists | "I don't have a milk entry today. Did you mean one of these: …?" | No dead end. |
| "Add cheese to the omelette" | A part is added beneath the omelette parent. | A dish part. |
| "No, it was X" while a question about it is still open | Not this door: it is an answer (R1, F7). | Correcting an open question is answering it. |
- A correction never creates a second entry (§11). A food change goes through the same lookup and judgement as a new food, and the result replaces the entry, carrying the amount, the estimate status and any rejection.
- A correction also seeds the person's default for those words, so the same question is not asked next time (§11).
F9 · Answering a food question
Given: the question as said; the log
Outputs: a number or a list, on a card and in one sentence; nothing written
| The person said | What this box does | Why |
|---|---|---|
| "How much protein have I had today" | "About 34 grams of protein today." | A total over today's entries. |
| "What were the carbs on the last thing I logged" | "The Quest bar: 22 grams of carbs." | A nutrient of one entry. |
| "What did I eat yesterday" | A list card; one sentence naming the count and the total. | A list scope. |
| "How much protein was in the cottage cheese I ate earlier" | "The cottage cheese: 12 grams." | A named entry. |
| A question while an entry is being worked out | The known total, with the pending entry named. | Nothing invented for a pending entry. |
- Today's code turned "what were the carbohydrates on the last thing I logged" into a food lookup and said it could not complete the nutrition lookup for that sentence. This door exists so a question is never a lookup.
F10 · Changing a food setting
Given: the setting as said
Outputs: the setting saved by the app and confirmed; or one question for the missing value
| The person said | What this box does | Why |
|---|---|---|
| "From now on just tell me the calories when I log a food" | Saved; "From now on I'll just say the calories." | A readback setting. |
| "Tell me protein too" | Saved; confirmed. | Adds a figure to the readback. |
| "Always assume Dave's Killer Bread Good Seed when I say bread" | Saved as the default for "bread"; confirmed. | A default for words (§3 step 2). |
| "Always assume Dave's when I say bread" | "Which Dave's Killer Bread should be your default?" | The value needs a product. |
| "Set my precision to loose" | Saved; confirmed. | A profile name. |
- On 09-20 "from now on just tell me the calories" was answered with "I understood the nutrition question, but I could not find a solid number for that food yet". This door exists so a setting is never a lookup or a question.
F11 · Looking the food up
Given: one food's identity words, brand and class; the rejected list
Outputs: the candidate rows, each with its own name, source and a plausibility flag
| The person said | What this box does | Why |
|---|---|---|
| "Chobani cherry yogurt" | Rows carrying chobani + cherry + yogurt from every source; the tube rows flagged implausible for a yogurt cup (43 g); the Greek cup rows kept. | The check at F11.4 is what was missing this morning: two tube rows agreed and nothing said a tube is not a cup. |
| "one banana" | Banana rows; "Peppers, Banana, Raw" dropped (an extra word that changes the food); "Banana, Baked" dropped (a preparation that changes it). | F11.3 is the rule the 09-21 fix loosened. |
| "Dave's killer bread toast" | Query "dave's killer bread" (toast is preparation); the Dave's rows from the catalog, ranked; the maker's page only if F16 asks. | Preparation words never enter the query. |
| "my saved Quest bar" (a saved alias) | The saved food, word for word → the single candidate. | A saved food matches only word for word (§3 step 2). |
| "quest blueberry protein bar" | Quest blueberry rows from the catalog; the saved "Quest cookies and cream" does NOT match (different words). | Precedence never overrides matching. |
| A row with 1,455 calories per 100 g | Quarantined; never a candidate. | §12 plausibility. |
- Every source is searched at once. The source order is how ties are broken among the same product, never the order of fetching (Howard, 09-23).
- Nothing here renames a row to the person's words, and nothing downstream renames the person's words to a row. That is the fault behind the Chobani tube.
F12 · Judging the candidates
Given: the candidate rows with their names and sources; the words as said; the precision setting; the rejected list
Outputs: one food (a match, a default, or a cluster with alternatives); several (to F13); a confirmation of one; nothing usable (to F16)
| The person said | What this box does | Why |
|---|---|---|
| "two eggs" with rows Egg; Sunny side egg; Scrambled eggs (seeded) | Word-for-word "Egg" wins; the others are alternatives. | Exact match is the answer; variants are alternatives (09-22). |
| "a Quest bar" with five flavours within the setting | One food: "Quest bar", 190 (170–210), five flavours as alternatives. | Agreeing rows are one cluster; logged at the person's words. |
| "a Chobani cherry Greek yogurt" with three rows that differ | Ask: "Which one — 1 …, 2 …, 3 …?" | They differ beyond the setting. |
| "an apple" with 25 varieties, all within the setting | One food: "apple", the cluster's range; the generic apple row if one exists. | The apple rule (§5.2). |
| "Chobani cherry yogurt" with two tube rows and (after F11.4) the cup rows | The tube rows are flagged; the cups differ from the tubes → ask, naming tube vs cup. | Never confirm a flagged row as if it were the cup. |
| "cottage cheese" with 1% and 4% rows | They differ beyond the setting → ask "1% or 4%?"; a stated level would have been honoured at F11. | Dairy fat level is identity (§8). |
| One uncertain row | Confirm it, naming what distinguishes it. | A confirmation offers one choice. |
| Rows all on the rejected list | Nothing usable → F16. | Rejected rows never return. |
- This is the box the decision core already implements from facts. Its two faults this morning were upstream: a renamed row (F11.7 forbids it) and no plausibility check (F11.4 adds it).
- The precision setting is read here for exactly one thing: how far rows may differ and still be one food (P).
F13 · The clarification ladder
Given: the clusters that differ; the words as said; the record of what has already been asked about this food
Outputs: one question, with its facts recorded (kind, names and count offered, what a bare yes means); or the estimate; never a repeat
| The person said | What this box does | Why |
|---|---|---|
| "a Chobani cherry Greek yogurt" → three rows that differ | Rung B: "Which one — 1 Simply 100 black cherry, 2 black cherry on the bottom, 3 …?" | Few, honest choices. |
| "soup" | Rung A: "What kind of soup?" | A huge flat field; a list would be absurd. |
| "Dave's killer bread" → twelve rows | Rung C: "Which Dave's Killer Bread — Good Seed, 21 Whole Grains, Powerseed, or another?" | Many rows that group by variety. |
| "Good Seed" to Rung C → two Good Seed rows that differ | F12 again over that variety: "I found two Good Seeds. Which one?" (a new question, not a repeat) | The variety's rows are a cluster run through the ordinary rules (§11). |
| "none of these" to Rung B | The three rows are rejected; nothing remains → Rung E: "None of those, then. I can look it up online — say look it up, or cancel." | After a rejection, re-select over what remains. |
| "look it up" to Rung E → the web finds two new products | Rung B over the two new products; the rejected ones never return. | Anything new is offered, even one. |
| "look it up" while products are still offered | Search wider for the same food; new rows join the list; the offered ones stay. | §5.4: a lookup on an offered list widens it. |
| "I don't know" to any rung | The estimate rung: one entry at the person's words with the offered rows' range; said in one sentence; correction invited. | I-don't-know ends the funnel honestly. |
| The rules would ask Rung B again | Not asked → F14 → the model consult (part 3). | The same question is never asked twice. |
| A "which one" question while "how much" is also open | One question that asks both, or the which-one first and the how-much next; never two open questions. | Never two open questions at once (part 1). |
- The rungs are ordered by how much the evidence concentrates the answer (§5.4). The estimate is the last offer on every list, so a "yes" or an "I don't know" always has somewhere honest to land.
- Wording rules for any question (§5.4): it adds information and says why; short enough to answer by voice; never makes the person repeat their own words; never exposes a wrong guess; options are real rows, never invented. Wording lives in F25, not here.
- Today this ladder is spread over several places that disagree (the correction path, the fresh-log path, the wider-search path). This box is the statement that it is one thing.
F16 · The web search
Given: the food's words and brand; what was offered; the rejected list
Outputs: new rows for F12, with their evidence; or "nothing new" with what was searched
| The person said | What this box does | Why |
|---|---|---|
| "look it up" on the Dave's list | The maker's page; new varieties offered; "found three more" | Authoritative page; truthful count. |
| "Giovanni strawberries and cream protein drink" (nothing in the catalogs) | The search runs; a maker's page may match "Chobani strawberries and cream protein drink" → offered as "I think you mean…" | A misheard brand can still be found by the rest of the words. |
| A blog post with the food's calories | Not a source; ignored. | Random pages are never a source (§12). |
| A page whose numbers contradict its own passage | Row dropped. | A contradiction, not a format the checker cannot read. |
| The same food, second "look it up" in one turn | No second search; the same choices and the estimate offered. | Once per food per turn. |
- The model here reads pages into rows; it does not decide what the food is. The rows it returns go through the same checks as catalog rows and are offered by the same ladder.
- What the search retains (product, serving basis, passage, URL, uncertainty) is the evidence a trace shows (§10.1).
F17 · Do we at least know the kind of food
Given: the words as said; the class
Outputs: the kind is known (to F18) or unknown (to F19)
| The person said | What this box does | Why |
|---|---|---|
| "a plain bagel" not in any source | Kind known: bagel → F18 (an estimate from bagels, as a range, or enter it). | A class word. |
| "a Zorbly bar" | Kind known: bar → F18. | "bar" is a kind even if "Zorbly" is unknown. |
| "three flibjopolis" | Kind unknown → F19: "I couldn't find flibjopolis. You can type the numbers or scan the label." | No word we can place; not nonsense — an unfamiliar food. |
| "a Chipotle thing" | Kind from the class: restaurant → F18 with a wide range and the offer to name the item. | The class supplies a kind. |
F18 · Offer an estimate from the kind, or to enter it
Given: the words as said; the amount; the kind
Outputs: a class estimate logged as a range with a caution; or the person's own entered food, checked and saved; or an unresolved entry kept
| The person said | What this box does | Why |
|---|---|---|
| "a plain bagel" → "yes" | "Logged bagel: 250-350 calories, an estimate for bagels." The card offers the ways to narrow it. | The estimate taken. |
| "…or scan the label" → a scanned label | The numbers checked, saved as the person's own food, logged exactly. | Entered by scan; a point, not a range (§9.3). |
| Typed "25 calories, 20 g protein" | "That can't be right — 20 g of protein is at least 80 calories. Check the label?" | Physical possibility check (§10). |
| "cancel" | The question closes; the entry stays marked unresolved (F4) — or is removed if they say to delete it. | Cancel on this rung closes the question; the log policy keeps the entry. |
| A packaged phrase with no grounding, e.g. "a Zorbly bar" | Never logged with invented macros: the estimate offered is the class (bars), said as such, or enter it. | §10: a branded phrase with no grounding is never written with invented numbers. |
- The estimate here is from the kind, as a range, and it is always said to be one. The card is where the person sees what was said, why it is a range, and how to narrow it (§9.4).
- The barcode is offered honestly as a long shot (Howard, 09-23).
F20 · Precise, imprecise, or missing
Given: the chosen food and its measures; the amount read at F6
Outputs: precise (to F23), imprecise (to F24), or missing / unusable (to F21)
| The person said | What this box does | Why |
|---|---|---|
| "a Quest bar" on a per-bar row | Precise: one bar. | A known package. |
| "3 ounces of turkey" on a per-100 g row | Precise: weight → F23 converts ounces to grams. | Same kind of measure. |
| "a cup of milk" on a row that lists 240 ml | Precise: volume → F23. | Same kind. |
| "a cup of oatmeal" on a per-100 g row with a density | Precise → F23 uses the density. | Different kind, convertible. |
| "two slices of Dave's" on a per-slice row | Precise: 2 × slice. | A count the row takes. |
| "two slices" on a per-100 g row with no slice weight | Unusable → F21 (assume or ask how much); never "which one". | A stated unit whose size no source established (§6.2). |
| "a big bowl of oatmeal" | Imprecise → F24. | A vessel with a size word. |
| "some peanuts" | Imprecise → F24. | A vague word gives a range (§6.6). |
| "chicken" | Missing → F21. | No amount words. |
F21 · Ask how much, or assume
Given: a food with no usable amount; history; defaults; the precision setting
Outputs: a question ("How much?"), or the assumed range logged and said
| The person said | What this box does | Why |
|---|---|---|
| "chicken" with no history | Plausible 3 to 8 oz → 140 to 370 calories → exceeds → "How much chicken did you have?" | Job 2 of the setting asks. |
| "romaine lettuce" on a sandwich | Plausible range 8 to 16 calories → within → logged as a range, no question. | A range is the first move when it does not matter (§9.2). |
| "Fairlife fat free milk" with a default of one cup | One cup assumed and said. | A saved default with an amount (§6.2). |
| "Quest bar" logged three times as one bar | One bar assumed and said. | History. |
| "an omelette" with no egg count | The eggs are a core part with a wide plausible range → ask "how many eggs?" (§7) | The threshold decides which part is asked about, never the part's name. |
| Same, at the loosest profile | Assume 3 eggs from the typical-count reference; said as an assumption. | §6.5: the loosest template logs a visible estimate. |
- The precision setting is read here once (P, job 2). The VALUE of the amount always comes from data: the row's serving, history, the typical-size reference. There is no flat default for anything (§6.1).
F22 · Estimating the amount
Given: the food; the plausible amount range from data
Outputs: a logged range with the assumption recorded and said plainly
| The person said | What this box does | Why |
|---|---|---|
| "I don't know" to "How much chicken?" | The plausible range (3 to 8 oz) logged: "Logged chicken breast: 140-370 calories; I estimated the amount." | I-don't-know estimates; the setting is not read again. |
| "chicken" at the loosest profile | The same range, logged without asking, said as an assumption. | §6.5. |
| "a large banana" with no row for large | The class's large weight, if the reference has it; else ask the person the size in their words (§6.2). | A stated size is the size logged, never the medium. |
| An estimate said with "the nutrition range reflects serving-size uncertainty" | Never said. | Howard, 09-23: a range is fine; no sentence about the app's doubts. |
- An assumption on how much is stated, on the entry and in the sentence, and is one correction away. That is the difference between this box and a question: nothing waits.
F23 · Matching the amount to the row's measures
Given: a precise amount; the row's measures (weight, volume, count, size); the food's density and form
Outputs: the quantity fitted to the row: macros and range, the person's unit kept
| The person said | What this box does | Why |
|---|---|---|
| "3 ounces of turkey" on a row per 100 g | 85 g; arithmetic. | Same kind (weight). |
| "a cup of milk" on a row listing 240 ml and 244 g | The volume measure: 1 cup = 240 ml → that serving. | The row's measure of the same kind; no density needed. |
| "a cup of oatmeal (dry)" on a row per 100 g only | Density of dry oats → about 80 g. | Only the other kind: density. |
| "two eggs" on a per-egg row | 2 × the row's serving. | A count of the row's unit. |
| "two large eggs" on a row "1 large (50 g)" | 2 × 50 g; "assumed two large eggs" said. | A sized row. |
| "two slices" on a per-slice row at 70 and a two-slice row at 200 (a cluster) | Both scaled to per-slice before the range: 70 and 100 → "two slices: 140-200". | One basis first; this is the 90-calorie bug from this morning. |
| "half a cup of rice" with history "cooked" | The cooked row, half a cup by its volume; "as you logged before". | The cooked-or-dry flag from history. |
| "a chicken breast, grilled" against a raw row only | Never the raw row; a cooked row or a question. | Raw and cooked are different foods. |
- Density is the exception, not the rule: it is used only when the row gives one kind of measure and the person gave the other (Howard, 09-23).
- The person's unit stays on the entry; the conversion is visible in the trace, never silent.
F24 · Interpreting an imprecise measure
Given: an imprecise amount; the chosen food; the typical-size reference; the vague-serving multipliers
Outputs: a range in the food's unit, marked imprecise, with the words and the reading recorded
| The person said | What this box does | Why |
|---|---|---|
| "a big bowl of oatmeal" | Large-bowl capacity × cooked oatmeal density → e.g. 300-450 g → logged as a range. | A vessel with a capacity reference. |
| "half a plate of spaghetti" | Half of the vague-serving range for spaghetti → a range. | A plate has no food volume. |
| "a handful of nuts" | 1 to 2 tablespoons → 100-200 calories; the card says: you said "a handful of nuts"; read as 1-2 tbsp. | The card shows the words and the reading (Howard, 09-23). |
| "a heaping teaspoon of chocolate sauce" | The teaspoon reference scaled up → a range. | A spoon with a modifier. |
| "some peanuts" | 0.75 to 2 × the serving → a range. | A vague word. |
| "a glass of water" | A range whose macros are zero → logged, no question. | Low impact is decided by the numbers, never by the word (§6.3). |
| "a bowl of soup" at the balanced setting | The range exceeds the setting → F21 asks how much; "I don't know" → the range is logged. | P job 2 still applies to an imprecise amount. |
- Imprecise measures are always logged as ranges (Howard, 09-23). "A glass", "a bowl", "a plate" are not special cases with rules of their own; they are amounts whose value is a range, and the setting decides whether that range matters (Howard, 08-27).
- No size lives in decision code: bowl capacities, spoon sizes and the vague-serving multipliers are data with provenance (§6.7).
F25 · Preparing the result
Given: the decisions and facts for this food, or a question
Outputs: either a finished entry with its card and one sentence, or a question with its record and the waiting entry
| The person said | What this box does | Why |
|---|---|---|
| A Quest bar logged from a cluster | Entry "Quest bar", 190 (170-210), five flavours as alternatives; card shows them; "Logged Quest bar: 170-210 calories." | A statement, no question. |
| An assumed amount | "Logged banana: 90-135 calories; I assumed one medium." | The assumption is a statement that invites correction; nothing waits. |
| A which-one question | "Which one — 1 …, 2 …, 3 …?" with the record (kind: which food; names; count 3; a bare yes means nothing here); the entry waits. | A question; nothing finished. |
| A correction answered | The toast entry replaced by the Dave's entry with the amount carried; "Updated toast to Dave's Killer Bread Good Seed: 140 calories." | Replace, never duplicate (§11). |
| Options shown as buttons | The chat shows the buttons; the sentence does not list them; the voice reads them only when nothing is on screen. | Howard, 09-23: not both. |
| The old "The nutrition range reflects serving-size uncertainty." | Never. | Howard, 09-23. |
- Question or statement, never both (Howard, 09-23). A statement may state an assumption and invite a correction; that is not a question and nothing waits on it.
- All wording lives here. No other box composes a sentence, and no decision anywhere reads one.
F26 · How the app delivers it
Given: the module's result: an entry or a question
Outputs: the database updated and checked; the card shown; the sentence spoken; an open question held
| The person said | What this box does | Why |
|---|---|---|
| A finished entry | Written, checked, shown, spoken; the total updated. | The normal case. |
| A question | The waiting entry shown with its mark; the question spoken; held open. | One open question. |
| The save cannot be confirmed | "I couldn't confirm that was saved; it's still marked as being worked out." — the entry stays provisional. | Truthful about the save, silent about nothing else. |
| "I could not confirm that the change was saved" after "look it up" | Never: nothing was asked to be saved. | This morning's false sentence came from this box being reached with no write. |
| A log by voice | The food screen is shown. | Howard, 09-23: it did not navigate. |
- Today this is the shell's result applier, write repositories, card model and speaker: the module returns intents and a reply, the app applies, verifies, renders and speaks. The box is drawn so the module never does any of that itself.
P · The precision setting
Given: the active profile's numbers
Outputs: a yes/no to two questions: do these candidates differ enough to ask? does this unknown amount matter enough to ask?
| The person said | What this box does | Why |
|---|---|---|
| A cup of grapes: rows at 40 and 60 calories | Percent exceeded, absolute (25) not → agree → logged with the range. | Both must be exceeded (§4). |
| Two protein bars at 190 and 260 calories | Both exceeded → differ → ask. | A 70-calorie gap, 31 percent. |
| Lettuce on a sandwich, amount unstated: 8 to 16 calories plausible | Within the setting → logged as 8-16, no question. | Job 2; a range is the first move only when the setting says it does not matter (§9.2). |
| A bowl of spaghetti, amount unstated: 200 to 600 plausible | Exceeds → "How much?" | Job 2 asks. |
| "I don't know" to "How much?" | Estimate the amount (F22); the setting is not read again. | Consulted once per question. |
| "three small bananas" | The stated size and count are logged; the setting is never consulted. | A stated amount always wins (§6.2). |
- The setting's only two jobs (Howard, 09-22): decide whether asking which is worth it, and whether asking how much is worth it. It is not a source of numbers.
- A range that straddles the threshold is surfaced as a range, not turned into a question (§4).
Requirements behind the boxes
Every box carries a small label above its top-right corner saying where its rule comes from. Click a label, here or on any diagram, to read the wording and leave a note on it.
Notes
Every sticky note on every page, newest first. A note is pinned to a box: press the small + in any box's corner. The round button at the bottom right adds a note about a whole page. Each note is a thread: reply under it, and Claude answers there too (its replies arrive with the next version of this page). When Claude says a change is done, check it and delete the note.