Repository navigation
docs(lechef): add beyond-chat spec with machine-checked contracts - #147
Conversation
Five local-first jobs (plan, substitute, coach, adapt, remember) with dedicated surfaces, chat as fallback, and a phone-authoritative proposal/receipt model adopting PR #102's wire contract verbatim. Substitutions derive role-scoped reviewed swaps from PR #114's pairs.json with fail-closed rechecks; planning merges #52/#141/#142 over one stock pool; privacy adopts #26's frame-cache and session-expiry findings. contracts/: six JSON Schemas, eight fixtures, check.py (20 checks green: schema validation, 300s TTL, payload-hash round-trip over real SHA-256 digests, plan pool conservation, nine-class allergen gate). Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Independent review (Obvious, Autobuild + Max) Verdict: changes needed — small schema/prose edits only; the spec's research claims check out almost everywhere, but the proposal envelope schema cannot validate a proposal produced by the wire contract it says it adopts verbatim, and it drops the field its own revision-binding rule needs. Findings (by severity)1. HIGH — proposal envelope schema is not the #102 wire it claims to adopt, and omits
|
…enforced hash round-trip Finding 1 (HIGH): proposal.schema.json now carries snapshotRevision (required, integer >= 1) so §8.1's revision-binding rule has a wire field; rationale and requiredApproval become optional (absent from #102's wire and its frozen fixture); schema title/description state the §8.1 rename map instead of claiming verbatim adoption. SPEC §8 intro/§8.1/§8.3/§14 reworded from 'adopted verbatim' to 'adopted and re-cut', listing #102's actual camelCase payload kinds (timerStart..note) with the map (top-level snake_case, note->save_note, id->prop_-prefixed proposalID, sha256:-prefixed hash). The re-cut is kept rather than reverting to #102's raw envelope because PR #156 is already cut to these contracts. Finding 2 (LOW): §8.3's corpus-naming claim replaced — the three application kinds are named by this spec's registry; #102's corpus and ProposalTool union contain no plan/swap/adaptation kind strings. Finding 3 (LOW): check.py now recomputes payloadHash = sha256 over the compact canonical payload for every proposal fixture (was set-membership only), matches receipts to proposals by proposalID, fails loudly on an unknown $defs ref, and fires the shoppingList error only when short lines exist. New cross-check: #102's frozen action-proposal.json fixture (added verbatim) is mapped through the §8.1 rename map and must validate against proposal.schema.json. Fail-before-fix evidence in PR body; check.py 23/23 green. Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
LeChef beyond chat: spec (five jobs, cook mode, contracts, mocks)
Draft for review — do not merge. Adds
docs/spec/lechef/underalpha: the full LeChef spec (SPEC.md, assembled from SPEC-part1–5) plus a machine-checked contract pack underdocs/spec/lechef/contracts/.Human author: Sam Gu (sgu07966@gmail.com)
What changed and why
SPEC.md (17 sections) turns LeChef from a transcript with a camera into the cooking companion PR #86 §4 defines: five local-first jobs (plan, substitute, coach, adapt, remember), dedicated surfaces with chat as a fallback, a phone-authoritative proposal/receipt model, device-persisted timers, and push-to-look as the default camera direction. Key reconciliation decisions (researched from the open draft PRs):
{id, tool, payload, payloadHash, snapshotRevision, createdAt, expiresAt, requiredApproval?, userInitiated?}fromsrc/lechef/wire.ts:169-181; re-cut toproposalIDunder the phone'sprop_prefix, top-level snake_case kinds (camelCase payload kinds hoisted:timerStart→timer_start…note→save_note),sha256:-prefixed hash, additive display-onlyrationale, optionalrequiredApproval. Nine payload kinds: feat(lechef): shared LeChef tool layer — phone-authoritative proposals, read tools, eval harness (Part 1, M1) #102's six re-cut plus the three application kinds (plan,swap,adaptation);suggest_recipeis a read tool, not a proposal.pairs.json(schema 1.1.0: 279 pairs, 381 ingredients, 11 roles, 13 restrictions), rechecked fail-closed via exactfacts_keymatch; composition-unknown blocks rather than warns.contracts/ — six JSON Schemas (proposal, receipt, cook-step, plan, substitution, scaling-rules), nine example fixtures (including #102's frozen
action-proposal.json), andcheck.py.Review round 1 (post #147 independent review) — commit 9d987b3
All three findings adopted; none disputed. One directional choice, explained below.
1. HIGH — proposal envelope schema vs the #102 wire it cited — FIXED
proposal.schema.jsonnow requiressnapshotRevision(integer ≥ 1), giving §8.1's revision-binding rule the wire field it rode on in prose only. Both proposal fixtures carry it (12, matching the receipt examples).rationaleandrequiredApprovalare now optional — feat(lechef): shared LeChef tool layer — phone-authoritative proposals, read tools, eval harness (Part 1, M1) #102's wire has norationale, andrequiredApprovalis absent from its frozen fixture; the phone still derives and always emitsrequiredApprovalon re-cut proposals (§8.1 prose says exactly this now).timerStart…note,types.ts:259-281—save_noteis a rename ofnote), and give the full rename map (id→prop_-prefixedproposalID, kind hoisted to top-level snake_case, bare-hex hashsha256:-prefixed). §14's feat(lechef): shared LeChef tool layer — phone-authoritative proposals, read tools, eval harness (Part 1, M1) #102 row carries the same map. §8.3's "Adopted verbatim" became "Adapted from".contracts/examples/action-proposal-102.jsonis feat(lechef): shared LeChef tool layer — phone-authoritative proposals, read tools, eval harness (Part 1, M1) #102's frozen fixture fetched verbatim fromoverhaul/lechef-f1;check.pymaps it through the rename map and requires the mapped envelope to validate againstproposal.schema.json. The mapping recomputes the hash per the runtime rule (wire.ts:90-93— sha256 over compact canonical JSON of the payload) because the frozen fixture's literalpayloadHashis a placeholder: it reproduces neither the payload digest (95281fe6…) nor any constant I could identify (verified: it is not sha256 of"hello world",b94d27b9…).docs/spec/lechef/contracts/", its test file loads the contracts directory by URL and runscheck.py, and itswire.ts/fakePhone.tsuseproposalID,snapshotRevision, andsha256:-prefixed hashes (all read from feat(lechef): bounded tool layer, fake phone/model, and 65-session scripted suite #156's diff this round). Re-basing the schema on feat(lechef): shared LeChef tool layer — phone-authoritative proposals, read tools, eval harness (Part 1, M1) #102's raw envelope now would move two open PRs for no behavioral gain; the map makes the re-cut traceable and machine-checked instead.2. LOW — corpus-naming claim not supported — FIXED
§8.3 now says the three spec-added kinds are named by this spec's registry and that no
plan/swap/adaptationkind string exists in #102's corpus orProposalToolunion — the unsupported "the suite's corpus already names them" claim is gone, as is §8.1's "the suite names speculatively".3. LOW — check.py documents a hash round-trip it didn't perform — FIXED
check.pynow recomputespayloadHash=sha256over the compact canonical JSON of the payload for every proposal fixture and compares (the docstring's claim, previously unchecked).proposalID(a receipt citing an unknown proposal id fails), replacing hash set-membership.resolve()fails loudly on an unknown$defsref (was: silently validated as "any").shoppingListemptiness error now fires only when short lines exist (was unconditional, with a message that could be wrong).Fail-before-fix evidence (commands and results)
python3 contracts/check.py→ exit 1:examples/proposal-substitute.json: 'snapshotRevision' is a required property+ same forproposal-add-timer.json. Fixtures updated → green.proposal-substitute.json'spayloadHashtosha256:000…0→ exit 1, two errors (recompute mismatch + its receipt's hash-equality mismatch). Under the old checker the same mutation only tripped set-membership — and only because both proposals are receipt-pinned; an unreferenced invented hash passed. Stated plainly: the reviewer's "an invented hash passes" was slightly overstated for these fixtures, the substance (no recomputation, reference-blind matching) was correct and is now fixed.receipt-executed.json'sproposalIDto an unknown id → exit 1,references proposalID 'prop_01J9ZZZZZZ', which no proposal fixture defines.$defs): pointing a schema property at#/$defs/nope→ exit 1,KeyError: 'unknown $defs reference: #/$defs/nope — fix the schema, do not validate as any'.step_advance→ exit 1,payload kind 'step_advance' is missing from the §8.1 rename map.head -11 SPEC-part1.md+ separators +tail -n +13+ parts 2–5), verified programmatically this round.check.py: 23 checks over 6 schemas and 8 fixtures / OK — all schemas and fixtures valid(was 20 checks).What I could not check
swift test/ macOS CI compile the untouched app targets on this branch but exercise none of this content.TasteEventkinds defer to the taste spec (separate packets, not in this PR).overhaul/lechef-f1today — if feat(lechef): shared LeChef tool layer — phone-authoritative proposals, read tools, eval harness (Part 1, M1) #102 edits it,check.py's placeholder-hash comment will not catch a drift (only the rename-map and mapped-envelope checks run).Assumptions
alphaper the packet id; branchobv/burst5-fridgeluck-spec-lechef. Review fixes pushed as a fast-forward (no force-push), PR stays draft.Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
🔗 Obvious Project · 🧵 Obvious Thread · 🔀 Obvious PR Artifact