Trim tool-schema copy; merge recipe upsert; unique recipe titles - #545
Merged
Merged
Conversation
recipe_update folds into recipe_save as the id-optional edit form - the same upsert pattern as wiki_save (one shared fields superset, binary id decision, rating veto enforced pre-route on both forms). The edit form's RPC contract is unchanged (p_set_* pairs, photos carried forward, topics dropped from the echo); the create form keeps its change_message default. Wire: 56 -> 55 tools, 65414 chars. Copy trim on the tools that stay separate: the photo quartet and record file/link schemas drop their cross-reference tails and the redundant 'change_message REQUIRED' prose (required is already in the wire schema), and the change_message 'Examples:' tails (the convention + cap is what matters). ~540 tokens saved. QA vs glm-5-3-flash on the local stack: create-then-update in one turn with the id passed from the first call's return; version rows show 'Initial version' then 'Correct cook time from 3 to 4 minutes per side'; rating stayed unset.
Adds recipes_user_title_unique - a unique index on (user_id, lower(btrim(title))). Duplicate titles read as bugs (two cards that drift apart as one gets edited), and the uniqueness key is what the recipe upsert's dedup heuristic needs to do what wiki_save does: a create whose title exactly matches an existing recipe routes to that recipe's update, a near-match is refused with candidates named. Two implementation notes QA forced: - Enforced as a unique INDEX, not a table constraint: Postgres only accepts expressions in index form. - The RPC 23505 handlers are attached to nested BEGIN..END blocks. A bare clause mid-body parses but silently swallows every statement after it - empirically caught when a fresh-title create produced a recipe row with no version row. - When the heuristic matches, the edit form's required change_message defaults to 'Matched existing "<title>"' - the model had no reason to provide it (the schema calls it optional on create). Constraint verified collision-free against prod (50 recipes, 0 ci-collisions) before landing. End-to-end QA vs glm-5-3-flash: create form, then a lowercase-variant create surfaced matched_existing: true to the model, which read and explained the flag correctly.
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.
SYNOPSIS
Copy trims on tools staying separate,
recipe_updatefolded intorecipe_saveas an id-optional edit form, and recipe titles made unique with a dedup heuristic.PURPOSE
Continues the tool-consolidation work from #544. The photo quartet and record file/link pairs deliberately STAY separate (disjoint param sets - a merged schema would show every form's params at once and required cannot be conditional), so their token cost comes from copy trim instead. The recipe pair is a true upsert (shared fields superset) and merges. Title uniqueness gives the merged tool the same natural-key dedup wiki_save has.
DESCRIPTION
recipes_user_title_uniqueindex on (user_id, lower(btrim(title))), verified collision-free against prod before landing. Natural-key dedup in recipe_save: exact-title create routes to update (matched_existing: truein the result), near-match refused with candidates named. RPC 23505 handlers attached to nested BEGIN..END blocks (a bare mid-body exception clause parses but silently swallows subsequent statements - caught by QA).NOTES