Repository navigation
Release v0.1.0 - #206
Merged
Merged
Release v0.1.0#206
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Adds CONTEXT.md with the terms settled while resolving the one-core shape question: Operation, Catalogue, Core, Door, Parity, Credential, Immediate Operation, Job, Import, Export. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
…sue #8) Guards the MCP/web parity guarantee: the RPC-shaped web API is deliberate, and hand-writing REST routes would silently destroy it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
The written Ingredient Line is the truth; structure is an optional Reading over it. Adds the recipe vocabulary to CONTEXT.md and records the ingredient decision as ADR 0002. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
The database is the truth; the Markdown vault is an optional, per-user, write-only published copy. Inverts Hatchdoor's ADR-01, which does not transfer to a multi-user app holding accounts and cooking history. Adds ADR 0003 and the Vault and Backup terms. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
…sue #16) A recipe's identity is a Lineage: one id minted at creation, carried by every copy anywhere, never changed and never joined. Editing a shared recipe makes a new Version on your Branch of its Lineage. A Version is one saved state named by a fingerprint of its own content, so the Branch Point between two Branches is computed rather than declared. Kamosu holds divergence and never merges. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Adds ADR 0005 and the Attempt / As Cooked / Promotion vocabulary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Same Lineage, carrying a Language — translation as the most natural case of never-merge rather than an exception to it. Each Version on a translation records which Version of the source it translates, so staleness is computed and travels. ADR 0006; Language, Translation and Reading Language added to CONTEXT.md; Branch, Food and Tag amended. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
ADR 0008 settles both kinds of link between recipes. Composition is an ordinary Ingredient whose Reading names a Recipe instead of a Food, so ADR 0002's polite degradation covers it for free and no feature learns about a third list. It names a Lineage rather than a Version, keeping the outer recipe's fingerprint stable; how much is computed from the inner recipe's Yield and stored nowhere; it unfolds in place and never splices its Steps into the outer method; it travels as a passenger without changing its own Visibility; cycles are stopped at unfold time rather than refused at save time. Association is a Related Recipe: untyped, two-way, held against the Lineage, and never travelling. CONTEXT.md: Reading amended to target a Food or a Recipe; Component and Related Recipe added. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Cooking mode is an Attempt being lived rather than a thing of its own. Held on the server so a cook survives phone to iPad; real from the moment it starts, so never finishing it still counts as a cooking, with deleting as the counterweight for a false start. Holds the Step, the ticked Ingredients and the Yield being cooked to — a fact about one afternoon, not an As Cooked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
The mirror doc told agents to create a token; one already existed at ~/.config/forgejo/kamosu.env, so a fresh session would mint a duplicate or stall on a missing variable. Point AGENTS.local.md, the tracker doc and the mirror doc at that path, with the sourcing line that keeps the secret out of the transcript. Also commits the mirror itself — the script and its doc were still untracked, which would have left the tracker doc linking to a file not in the repo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
) Settles the frontend stack and the offline posture. Svelte 5 + SvelteKit (adapter-static) + TypeScript + Tailwind 4 + Paraglide, chosen against the benchmark evidence: Web-Bench favours React five models of six, but the gap is a capability gap that closes with reasoning, SvelteBench is saturated at frontier, and the stale- knowledge failure it measures is closable because Svelte ships docs written for models. Every layer picked so the build fails rather than the kitchen does. Offline, the line is Promotion: write your own history, never the recipe's. An offline edit queue is a merge, which ADR 0004 refuses; the permitted writes were already last-one-wins under ADR 0010; and fingerprint pinning plus append-only Versions mean offline Attempts cannot conflict at all. New term: Display Copy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
There is no difference screen. Holding two Branches of a Lineage shows two recipes, whole and cookable, with a switch between them — because everything else in Kamosu already says a recipe is a thing you stand in, and because you can cook what you are looking at. The claim that this shape cannot show a deletion was wrong. A Ghost puts the line on the page struck through, where it sits in the recipe that really has it. A removal seen from one side and an addition seen from the other are the same object, so one mechanism makes the page symmetric. Also settled: one card per Lineage; carrying a change across is a gesture that leaves an unsaved edit and has no "take all"; history is the Thread, from which any Version can be read and cooked; a Version's name is the one thing about it that can change later. Adds ADR 0014, the terms Thread and Ghost, and amends Version. Generated #30 — whether an Ingredient Line has an identity of its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Attribution across instances is a courtesy, not a proof. A Version records the Hand of the Person who wrote it — a name plus a permanent id minted with the account — and a Branch has an id of its own recording the Kitchen's Hand. Both travel in a share bundle; neither is ever verified, and Kamosu says so rather than implying a check it does not make. Forces a structural finding not previously written down: the fingerprint covers the recipe state alone, so the what-changed line is frozen metadata rather than identity. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Records ADR 0016 and adds Unit, Cup Weight and Reading Measures to CONTEXT.md; amends Reading and Step. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Truncation refused: a share always carries the complete chain of Versions back to the first, commentary included, and no Version may be withheld or removed by anyone holding it — author or recipient. A missing Version now has one meaning only, so #17 inherits a rule instead of a marker, and the Branch Point is always computable. The Share Link page shows the Thread beneath the recipe, making the promise self-evidencing, and the share screen carries a standing line in the same words every time. Records ADR 0018; closes ADR 0004's open question; amends Version, Share Link and Branch Point in CONTEXT.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Resolves the share bundle format: one format, not two. A Bundle is a readable folder — a Markdown note per recipe with the Thread beneath it, plus a .kamosu/ sidecar of complete past Versions — handed over as a plain zip. The deferred Vault is the same folder with every recipe a subject, written to a directory instead of zipped. Also settles receiving (a Branch has one Kitchen writing it, so a Copy happens at the moment of change, not of receipt) and the damaged case (refuse the history, offer the words, drop the Lineage id). A second decision fell out and sharpens ADR 0004: a Reading is Kamosu's reading, not the recipe. The fingerprint covers the words and the Photographs alone, so a parser disagreement can never report two people as diverged. That freed what #20 was waiting on — a Food travels as its names, all of them, no id. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SD2qPHMD8sc8AZG4Cp4ABx
Records ADR 0022 and the glossary terms for how an arriving Food meets the instance's own Food list: silent conservative matching by name in the same Language, a collision landing as a new Food plus a Merge Suggestion, accretion of unknown names on a clean match, one rule at every door, and an irreversible Operator Merge that states its blast radius first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CqVogK756vrRwwYXPAjGB7
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011oCKRCZGjWsjHUuUZTBy1Z
…ssue #25) Splits the feature at the line ADR 0009 cares about: the choosing is stored, the rows are computed. A Person's list, not a Kitchen's — the recommendation was vetoed and the veto was right, since the way out is a Shortcut into one person's Notes. Adds ADR 0024 and the Shopping List, Shopping Row and Loose Item terms. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LefyPutHzGcRrRuCKsned
An import leaves nothing on the recipe — no foreign id on the Branch, no mark on a line Kamosu had to assemble. What it remembers it keeps itself, in a ledger of foreign id against Lineage, so re-importing matches instead of doubling the library and the whole thing is deletable the day Crouton is gone. Three of the ticket's questions dissolved rather than resolving: with no mark there is nothing to un-mark and nothing to carry in a Bundle. Adds ADR 0025 and the Import Report term; amends Import and Passenger. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LefyPutHzGcRrRuCKsned
…29) Answering "which library" required collapsing Visibility a level up: a recipe is seen by its Kitchen, or by anyone with its Share Link. Everyone here and Chosen are removed, retiring the term Visibility and finishing the collapse #11 claimed to have made. Recipes is then one merged shelf of what your Kitchens hold, alphabetical, one card per Lineage, with filters that never stick. Search blends words and meaning, reaches your own Attempts alone, quotes what matched, and offers a way out when nothing is close. A recipe with no photograph is led by a Cover generated from its Lineage id. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LefyPutHzGcRrRuCKsned
Deployment, packaging and upgrades. The image is one executable with the frontend compiled in, one /data mount, and no model at all — Meaning Search is optional and conditioned on the Operator accepting Gemma's terms, which dissolves the licence problem rather than modelling around it. Upgrades go forward only: SQLite rolls schema and data back together, so a failed migration means nothing happened, and the pre-upgrade Snapshot is the database alone because a Photograph cannot change. ADR 0028, ADR 0029, ADR 0030. Meaning Search and Snapshot added to CONTEXT.md; Backup amended with where it goes and that Kamosu never sends it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019LefyPutHzGcRrRuCKsned
An Ingredient Line with a standalone or / ou / o (or and/or, et/ou, y/o) offers the cook two things to buy. It now keeps its amount and Unit and names no Food, at any length. Before, a short one became an invented Food such as "butter or oil", and a long one fell past the six-word limit. The first alternative alone is no better, because the two usually share their last word: "soft or silken tofu" is not tofu called "soft". An "or" after an elided article is French for gold and stays in the name. "Thick bellota steak burgers from the market" stays unread on purpose, since nothing marks "from the market" as an aside. The comment on LONGEST_FOOD_NAME and ADR 0036 now name both exceptions instead of calling everything past six words prose. The corpus test scores the named share over lines offering no choice, and fails if any choice line names a Food. 21 of 863 corpus lines changed, each from an "X or Y" Food to none. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Before a new instance is set up, a hostile web page opened on the same network can do the setup itself through DNS rebinding. Aurélien chose to accept that and say so rather than add a setup code: the page cannot sign in with what it made, the owner sees "Welcome back" instead of "Set up Kamosu", and emptying /data undoes it. The line goes into ADR 0034, the README and the Settings list in en, fr and es, since the honest-list test requires every item in all of them. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
A Backup reported "0 of 1" when it started and never again, so get_job went on saying 0 of 1 after it had finished. I took the general route rather than patching take_backup: when a Job completes having declared a total, finish() now sets done to that total and the message to "finished". No Job can forget it that way. Reading the ingredient lines had the same slip, stopping at N-1 of N, and is fixed by the same rule. A failed Job keeps its count, since how far it got is worth knowing. A Job that never gave a total (the web link importer) is not handed one. Imports and Sheets already ended on total of total with "finished", so they read the same as before. probe_job, the test-only demonstration Job, gains stop_after and without_total so the tests can reach both of those cases. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
…app (#156) On the share screen, "Save it" pointed the page at /api/bundles/<id>. In the app installed on an iPhone that address stays inside the app's own window, which has no Share or Save to Files. It is the trap #149 fixed for the Sheet, and the fix is the same (option A, Aurélien): there the first tap fetches the zip ("Getting the file…"), the button then reads "Share the file", and the second tap hands it to the share sheet. Closing the share sheet keeps the file for another try, and leaving the screen drops it. A Safari tab, a computer, Android, and an iPhone that will not share a zip keep the plain navigation. #149's pieces are shared rather than copied. sheet.ts becomes files.ts: one fetcher for a PDF or a zip, sharesFiles for the installed-on-Apple check, and shareFile for the share call. The Sheet uses all three. Tried on Aurélien's iPhone from the dev URL. canShare said yes to a zip, and Save to Files kept it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
) A Kitchen is a group of people cooking from each other's Cookbooks, so "this kitchen's Operator" taught the wrong meaning of the word in the first sentence an Operator reads. Aurélien chose "this Kamosu's Operator" (de ce Kamosu, de este Kamosu). The same line now also writes Opérateur with a capital and Operador in the masculine, as every other French and Spanish message already does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
The reader named Foods like "to taste sea salt" and "boneless". Now: - "To taste" (and au goût, selon le goût, à volonté, al gusto, a gusto) is dropped from either end of a line before anything is read, so a line reads exactly as it would without it. "salt and pepper to taste" names salt and pepper, the choice made on the ticket. - A Food made only of describing words (minced, divided, boneless, haché, picado, ...) is no Food. Where a comma cut such a run off from its food, the name carries on past it into a clause that opens with another describing word: "boneless, skinless chicken thighs". "4 cloves, minced" and "1 lb boneless, cut into pieces" name nothing. - The corpus check #160 added now also lists any Food that is only describing words or still holds a to-taste phrase. Existing Readings do not re-read themselves (#166). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
A re-save inside the collapse window used to write the call's name and change_note straight over the Version being shaped, so a quick second save that sent neither erased both. The collapse now keeps what the row already holds unless the call sends a replacement. An edit that changes nothing but brings a new name or change note writes them onto the Version still being shaped, under the same conditions a collapse uses. Past that point it is refused with a sentence saying why, instead of being dropped. Sending what is already there stays a no-op. The variation screen saved its draft and note in one call onto a head it inherited, which the Core now refuses. It saves the draft first and sends the note only when the draft made a Version for it to describe. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
) A save carries an unchanged line's Reading forward, so a fix to the reader never reached a line it had already misread. The Operator can now have the whole library read again, as a Job. - A Reading remembers whether a person set it (`by_hand`). set_reading sets it and a save carries it. Migration 41 guesses it for what is already there: a Component, or a Reading changed more than a second after its Version, plus such a correction carried onto later Versions. - reread_ingredient_lines covers every Version a Branch holds, history too, so a misread Food can end up with nothing pointing at it and be deleted. It leaves hand-set Readings and Components alone and reports each changed line once per recipe, before and after, the Foods it emptied, and how many hand-set lines it kept. - On the Operator page, "Read every line again" replaces "Read the unread lines" and shows the report (Aurélien's option B). - ADR 0021: a re-read someone asks for, which reports its changes, is not a silent recomputation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
The reader named Foods like *petits poireaux* and *beurre froid*, worse than the Readings already in the library, so a re-read (#166) would have made them worse. - SIZES lists every plural a French or Spanish size takes. - SIZES_AFTER drops a size written after the food (*tomates moyennes*), leaving *entier* and *gros* alone: whole-wheat flour and coarse salt are products of their own. - WARMTH drops how warm a food is at either end of its name, with a *very* in front of it (Aurélien's choice on #185). *hot* stays, as does every strength word such as *corsé*. - A few names that open with such a word keep it: *petits pois*, *cold cuts*. - A Step's amount names its Food the same way, so it still joins its line. - The corpus test now fails on a Food that keeps a size or a temperature. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
`2-3 basil leaves` used to read as a Food called "2-3 basil leaves", and `2 to 3 cloves garlic` as two of a Food called "to 3 cloves garlic". The reader now takes a range as the amount, kept as written: two amounts joined by a hyphen, a dash, or to/or/ou/o/a/à with nothing between them. The Unit and Food after it read as they do after any other amount. A range is worth nothing, as Aurélien chose: it is never scaled, converted or added up, so its shopping row names the Food with no number. ADR 0016 now says so, and ADR 0036 notes that `1 or 2 onions` is a range rather than a #148 choice. The Crouton corpus's three range lines now read back their Unit, so that test demands all 351. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
…it (#177) Every entry from search_recipes, home_shelves and the Tag filter now carries cookbook, writes and mine, computed the way get_recipe computes them. A caller can read the shelf once and know which recipes it may change, instead of opening each one or collecting refusals. writes alone is not enough: a recipe that arrived in your own Cookbook has writes false (an edit starts your own copy) but mine true (tagging is allowed). The Catalogue's descriptions say which question each answers, and that the entry's mine is not the search_recipes mine filter, which stays a history. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Claude Code shows a model a tool's name, description and inputs, and drops any outputSchema. So the MCP listing now writes each Operation's answer-field meanings, taken from the Catalogue's output schema, into the tool's description. Each distinct meaning appears once, beside the shortest path to a field that carries it. Claude Code also cuts a description at 2,048 characters. A tool that would pass that lists what fits and says how many meanings it left out. Only the four import Jobs need to. The listing grows from 85 KB to 114 KB. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
#183) A save whose words match the Branch head used to drop the translates_version_id it named, so a Translation whose words needed no change after a source fix stayed "1 version behind" for good. The identical-content shortcut now moves the head row's pointer to the named source Version. It writes no Version and appends no history row, and the fingerprint does not change. The pointer moves at any time, being shaped or not, but only on a Branch the caller's Cookbook writes. A name or change note that #165 refuses in the same call refuses the whole call. The name, the note and the pointer go in one UPDATE. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
… it (#184) A Step linked an Ingredient Line only when its text held the Reading's whole target, so "the syrup" missed maple syrup, "le cacao" missed cacao en poudre, and "ginger and garlic" missed lines read as "fresh ginger" and "garlic clove". Any run of the name's words now counts, provided it holds a word a cook would call the food by: never only "the", "fresh", "crispy", a unit or a form word like "paste" or "cubes". Aurélien's three choices on #184 settle the rest: - a short word two different foods share links both; - one food on two lines links the first no earlier Step used; - a mention after until / jusqu'à / hasta, to the next comma or full stop, is not linked, unless an amount follows ("jusqu'à 100 ml"). A match on the whole name always stands, so every link the old rule made survives except those two exceptions. Over the 90-recipe dev library links went from 541 to 1008; the 21 dropped are 15 duplicated foods and 6 mentions after "until". The #150 in-Step amount join is untouched. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
"1 good pinch salt" was read as one of a Food called "good pinch salt", because the reader skipped sizes before a Unit but not words like "good", "heaping", "bonne" or "buena". A new PRAISE list is skipped straight before a Unit, and at the start of a Food that follows a measure, so "200 g good dark chocolate" is dark chocolate. Anywhere else the word stays, which was Aurélien's choice: "poulet à la bonne femme" keeps its name. "glug" is now a Unit. The Unit search is one helper, unit_at, called with and without the praise. On the 86-recipe corpus only the two "good-quality" lines read differently. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
…them (#188) Recipe.svelte was 2,542 lines with a 1,130-line script. Each concern that stands on its own now lives beside it: the Sheet, deleting, the phone's kept copy, Components unfolding, correcting a Reading, the Divergence's marks, and the smaller rows. State that must outlive the page being swapped out for writing sits in .svelte.ts modules made once by the screen; the rest is in child components. Nothing a person sees or does changes, and no screen spec's assertions moved. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
#189) src/core/sharing.rs held three features in 2,494 lines. It is now share_links.rs, sheets.rs and carrying_bundles.rs, one area per file like the rest of the Core. carrying_bundles takes a verb because crate::bundles is already the zip format. A pure move: no function body changed. person_name, called by all three, moved to shared.rs as pub(super). ensure_link_live went with the Sheet, its only caller. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Hermes lists a tool it has not loaded as its name plus the first sentence of its description, cut at 60 characters. 83 of the 120 Operations opened with a longer sentence, so the line an agent picks tools from ended mid-thought. Each of those summaries now opens with a sentence of at most 60 characters that says what the Operation does. Whatever the old opening said moves into the sentences after it, so no summary loses anything. The test-only probe_job gets the same treatment. every_tools_first_sentence_fits_a_short_listing applies Hermes's own sentence rule (from _short_desc in tools/tool_search_catalog.py) to the MCP door's tools/list and fails the build on any line it would cut. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Kamosu goes public under the AGPL-3.0, with a ready-made image on Docker Hub. This adds what a stranger meets first: - LICENSE (AGPL-3.0 only), named in Cargo.toml and ui/package.json, whose version moves from 0.0.1 to 0.1.0 to match the server. - A rewritten README: what Kamosu is and is not, installing from the published image, why HTTPS is required to sign in, connecting an agent, where the data lives, and troubleshooting from the symptom. Four screenshots from the dev library sit under the introduction. - SECURITY.md: supported versions, how to report a vulnerability, and the list of what Kamosu does and does not defend, moved out of the README. tests/defences.rs now reads it there, and ADR 0034 records the move. - CHANGELOG.md with the v0.1.0 entry, dated when the tag is made. - THIRD_PARTY_NOTICES.md: the two bundled Zen fonts, and EmbeddingGemma as downloaded on request and never shipped. - docker-compose.yml for the one-folder, one-port install. - A GitHub check that refuses a pull request into main from any branch but dev. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Review of the first rewrite: - The wordmark (the seal beside "Kamosu" in Zen Old Mincho, light and dark) and a row of badges open the page, as Hatchdoor's does. - Kitchens and Cookbooks get a section of their own, and the pitch leads with them: who sees a recipe, who changes it, and what happens on leaving. - Meaning Search is among the highlights. - The screenshots sit in a captioned table, and move to docs/readme/. - Docker and Podman are shown side by side rather than Podman as an aside. - Connecting an agent covers Claude Code, Codex (which needs its 2026-07-28 switch, kept to a profile) and Hermes. - The ingredient-line highlight is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
The dev hostname vite allows moves out of vite.config.ts into KAMOSU_DEV_HOST in the gitignored repo-root .env; unset, vite accepts only its defaults. ADR 0037 stops naming the dev URL. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
…not shown Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
…e place in the list (#191) Opening a result destroyed the shelf, and going back built a new one from nothing. The route now exports SvelteKit's `snapshot`: the words, the Kitchen or Mine filter, the Tag and the scroll are kept as the reader leaves and restored only on back and forward, so the tab bar and a Tag chip still start the whole shelf. The shelf scrolls itself once the restored answer and the chip rows have drawn, since SvelteKit's own scroll lands on a page one "Loading…" tall. A failed search cancels that scroll, a Kitchen filter with no chip left to turn it off falls back to All, and a kept value that is not a shelf is ignored. ADR 0027 carries a note: going back is not leaving. Closes #191 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016QVfUHRQ2wJoKPWTS6SzaV
… role ADR 0044 records the grilling behind #192: one PWA on tablets and computers, a wide layout that needs both width and height, device roles deciding which screens get real design, a sidebar, tidying screens side by side, sheets as centred windows, and a back arrow for the iPad. The glossary now says tablet where it said iPad. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011aJcQGaXqh6r8L9zZ3ddo8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release v0.1.0,
devintomain.The first release.
mainholds only the "Initial commit", so this PR is the whole project. Full detail is inCHANGELOG.md.Pre-merge checklist
Cargo.toml,Cargo.lock,ui/package.jsonandui/package-lock.jsonall say 0.1.0.:latest, so there is no tag to bump. It says how to get a health check with the Podman images.Already published
The four Docker Hub tags are live, built from this branch's tree at
b49d126:0.1.0,latest,podman-0.1.0andpodman-latest, each amd64 and arm64. The Docker tags point atsha256:9e810b38a61b…and the Podman tags atsha256:ccecbee7eb84….They replace an earlier build from
3401e97, which predates #191. The only shipped code that differs between the two trees is #191's change to the Recipes screen. The rest isdocker-compose.yml,CONTEXT.md, the README and docs. Searching each binary for the keys the shelf keeps when you leave it finds them in the new image and not in the old one.Both images started on an empty data folder, served the first-run page with a 200 and passed their health check. The Docker image was tested straight from Docker Hub, the Podman image from the same digest just before it was copied there.
The GitHub release for
v0.1.0is a draft and nothing is tagged yet. Its target is currentlydev. It should point atmainbefore it is published, so the tag lands on the merge commit.Merge
Merge commit, not a squash.
mainis an ancestor ofdev, so the merge commit's second parent is thedevtip and the two branches share history afterwards. A squash would put a commit onmainthatdevhas never seen, and it would collapse 253 commits, with their(#NNN)ticket links, into one.Verification
just checkexits 0. That covers fmt, clippy, Prettier, ESLint, svelte-check, the freshness gates and the copy guard.just testexits 0. It ran 707 Rust tests and 794 screen tests, none failing.Release statistics
main@0397541dev@b49d126After merge
mainwith thedevtip as its second parent. Pushmainso every remote carries it.v0.1.0release atmainand publish it, which creates the tag.🤖 Generated with Claude Code
https://claude.ai/code/session_011aJcQGaXqh6r8L9zZ3ddo8