Skip to content

docs(spec): community spec — user recipes, Explore, challenges, Tables, API, mocks - #150

Merged
SamGu-NRX merged 4 commits into
alphafrom
obv/burst5-fridgeluck-spec-community
Oct 16, 2026
Merged

SamGu-NRX merged 4 commits into
alphafrom
obv/burst5-fridgeluck-spec-community

Conversation

@obvious-autobuild

@obvious-autobuild obvious-autobuild Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Community spec: user recipes, Explore, challenges and battles, Tables, API, mocks

Base: alpha · Implements the community packet of the overhaul SPEC (docs/spec/overhaul-20261011/SPEC.md on branch docs/spec-overhaul-20261011) · Draft PR, for review only — not for merge.

What changed and why

Adds docs/spec/community/:

  • SPEC.md (~620 lines, 13 sections) — the community round of the overhaul, specified end to end:
    • §1 ranks the three candidate directions (Explore-first leads; battles ride along as a challenge type; campus waits for a named partner), judged against Sam's ask, the "small extensions / not cooking for likes" guard rails, and what can actually run (the app has no account system or community network client today; verified by grep on alpha).
    • §2 user recipes: private by default, prospective revisions, duplicate/import gating (imported recipes cannot be published in burst5), rights declarations, publish preview ("What leaves your phone"), moderation states, withdraw.
    • §3 Explore: on-device ranking (PR feat(community): FLCommunityCore — sharing, challenges, taste profile, user recipes, Explore ranking #106's ExploreRanking verbatim: 0.6 fit + 0.4 taste with 0.5 neutral prior, 6 dp, 5-level tie-break), fit lines, cookedBy floor of 10, cold-start catalog mix, no likes/followers/profiles.
    • §4 challenges and battles: one lifecycle (draft→open→voting→closed), six types with campus reserved, one-vote-per-account movable votes, self-vote exclusion, no live tallies, 24 h vote-age rule, web links readable without the app, PR kitchen-knowledge: challenge packs (budget, food-bank, seasonal, use-it-up) #116 packs frozen by reference, waste tracking reserved.
    • §5 Tables: 2–8 members, owner-approved invites, shared cooks only (never pantry/profile), block-pair card filtering, redaction on departure.
    • §6 identity and safety: Sign in with Apple verified server-side; PR Community backend: scaffold, identity, Explore with moderation #104 session mechanics verbatim (fla1./flr1., 15-min/30-day, family revocation); content-hash-bound moderation; fail-closed screening (503); mutual blocks; 10/day reports; resumable deletion. PR Community backend: scaffold, identity, Explore with moderation #104's 18+ publishing gate is extended to every sharing surface.
    • §7–§8 backend and client: a separate backend/community bun package (overrides the overhaul's "module inside gemini-agent" per the packet brief — LeChef work must not share a deploy surface with moderation), Firestore store; iOS CommunityMigrations, share-preview builder, offline outbox with idempotent retry, feed caches, contract-tested API client.
    • §9 every screen in words (purpose, entry points, layout, exact copy, every state, accessibility; the Table feed adopts the overhaul's mocks/community.html verbatim).
    • §10 taste events (local-only records, never leaving the device); §11 three implementation slices (API / client / groups) with file ownership, public interfaces, tests, done-when clauses; §12 decisions ledger + four open decisions for Sam; §13 evidence appendix.
  • contracts/ — the community API as machine-checked artifacts: 24 JSON Schemas, 33 operations (openapi.yaml), 31 example fixtures, manifest.json, and check.py (stdlib-only) that validates every example against its schema, manifest coverage, OpenAPI/manifest sync, schema-object shape, constraint fields, and spec cross-references.

A load-bearing assumption is stated up front in the SPEC: the packet assumes a small, trusted-by-default community produces enough shared recipes and opted-in cook data for Explore to feel alive without moderation volume beyond one operator — with the evidence that would confirm or break it after the first month.

Review rounds

  • Adversarial review (independent reviewer, findings at commit 1b48421): verified every substantive claim against the repo — PR Community backend: scaffold, identity, Explore with moderation #104 mechanics (shared/sessionCore.ts, explore/publications.ts, config.ts floors/limits, safety/deletion.ts), PR feat(community): FLCommunityCore — sharing, challenges, taste profile, user recipes, Explore ranking #106's formula and fixtures, PR kitchen-knowledge: challenge packs (budget, food-bank, seasonal, use-it-up) #116's pack files, PR Personal cookbook: store, transaction service, and flow-check (M1) #71's editor, all overhaul quotes and mock copy (verbatim matches). All 14 findings (0 blockers, 8 majors, 4 minors, 2 nits) fixed in commit 0fd6113: gap-free section renumbering with all refs re-pointed (including schema descriptions), vote path prose/contract alignment, Explore cap consistency, outbox report operation, OpenAPI error responses (422/429/503/409/403) against the error schema, quarantined_rights defined, FitLine extended to the overhaul's five states, and real refs in the evidence appendix.
  • Independent review on this PR (4 findings, all fixed in commit 2f9ebea): the 41 bare-string OpenAPI schema values converted to Schema Objects ($ref mappings — the checker now rejects bare strings and records the fail-first state: 43 findings before the fix, including the 2 dangling prose references at SPEC.md lines 78/187, also fixed); prose section-reference audit extended to check.py (§-style and "section N.N" forms both linted; further wrong-target refs for migrations, 18+ gate, preview builder, taste events, and event logging corrected); constraint validation added to the checker (pattern/minLength/maxLength/minimum/maximum/exclusiveMinimum) — mutation-tested: the pre-fix checker accepted a vote entryId violating its pattern and a table name over maxLength, the post-fix checker rejects both.
  • OpenAPI 3.1 validity round (commit 56acb07, driven by openapi-spec-validator on this PR's contracts): every Response Object now carries its required description (33 added; the checker recorded 33 failures first), and every path template variable is declared as a required path parameter (15 templated paths, 22 undeclared occurrences; the checker recorded 22 failures first). Fixing the path parameters exposed a real bug in the checker's YAML-subset reader — it parsed block sequences as nested mappings because the mapping branch won on deeper indents — fixed by giving the sequence branch precedence. check.py fails first on each new rule, passes after the fix.

How I checked it

  • python3 docs/spec/community/contracts/check.py → exit 0: OK - 24 schemas, 33 operations, 31 example files, OpenAPI 3.1 in sync. at head 56acb07.
  • python3 -m openapi_spec_validator (openapi-spec-validator 0.7.4, the reference OpenAPI 3.1 validator) → exit 0 on the dereferenced document at head 56acb07. The validator cannot dereference the contracts' canonical $id base URL (https://fridgeluck.dev, an unregistered domain) over the network, so validation ran on a copy with every external $ref inlined from the local schemas/ files (sibling-preserving, recursion-depth-guarded; 0 unresolved $refs remain before validation). Structural validity of the raw document — operation/response/parameter/schema-object rules — is what this pass certifies; fetching the $id URLs is future work for when the domain is live.
  • JSON Schema files parse (json.load over all 24) and validate their 31 example fixtures under Draft 2020-12 with a referencing registry over the schemas' $ids.
  • Hosted macOS CI runs on this branch (docs-only content; the workflow builds the iOS sources unchanged): green on 1b48421 and on 56acb07 (run 38798361297).

What I could not check

What I assumed

  • The packet brief binds the direction choices: Explore leads, battles ride along, campus waits; the backend is re-homed from the overhaul's gemini-agent module to a separate backend/community package.
  • Where the overhaul SPEC and this spec disagree, this spec wins for community surfaces (stated in the intro).
  • Community collection naming, error-code set, and outbox operation enum are proposed here as contract, since no community client/server exists to constrain them.
  • The 18+ gate extension and the "cook counts below 10 render as nothing" rule adopt Sam's stated defaults and are flagged in the decisions ledger rather than re-asked.

🔗 Obvious Project · 🧵 Obvious Thread · 🔀 Obvious PR Artifact

SamGu-NRX and others added 2 commits October 15, 2026 10:45
User recipes, Explore, challenges and battles, Tables, identity/safety,
backend/client architecture, mocks in words, taste events, and three
implementation slices, drafted on top of the overhaul SPEC.

Contracts: 24 JSON Schemas, 33 operations, 31 example fixtures, and a
stdlib-only check.py that validates every example against its schema,
manifest coverage, and OpenAPI/manifest sync (exit 0).

Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
Review round (0 blockers, 8 majors, 4 minors, 2 nits), all addressed:
- renumber sections gap-free ascending (challenges 4, tables 5,
  identity 6, backend 7, app 8, mocks 9, events 10, slices 11) and
  re-point every cross-reference, including contract schema descriptions
- vote path in prose matches the contract (PUT /v1/challenges/{id}/vote
  with entryId; DELETE = removeVote)
- Explore candidate cap stated consistently (500 server-side before
  ranking, max 100 cards per response)
- outbox gains the report operation so offline reports are never dropped
- OpenAPI now declares error responses (422/429/503 publish, 409
  entries/tables/votes, 429 reports, 403 moderation) against error schema
- quarantined_rights defined in prose (rights re-verification on reopen)
- FitLine.state extended to the overhaul's five fit states
- evidence appendix cites real refs (PR #104/#106 branch heads, stage-0
  planning path)
- moderation decision path, RecipeRef community value, invite-mock
  section ref, and publication-state spelling note corrected

Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b420667d-3c65-453c-b171-8fc980a90b55

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@SamGu-NRX
SamGu-NRX changed the base branch from main to alpha October 15, 2026 11:19
@obvious-autobuild

Copy link
Copy Markdown
Author

Independent review (Obvious, Autobuild + Max)

Reviewed at head 0fd611353b8cb09d6ecbea1f49287d74f5d2a5ab (2 commits: 1b48421 spec, 0fd6113 fixes; both confined to docs/spec/community/). I did not write this PR; my only write here is this comment. Every numbered claim below was re-run or re-read this session; commands and results are under "Verified".

Verdict: changes needed

One major finding (the OpenAPI document is not valid OpenAPI 3.1, and three implementation slices pin to it), three minor. The prose SPEC itself is in strong shape: every "verbatim" citation I traced held, and the contract examples pass a reference JSON Schema validator with zero failures.

Findings (by severity)

1. Major — openapi.yaml is not a valid OpenAPI 3.1 document: all 41 schema references are bare strings.

  • Where: docs/spec/community/contracts/openapi.yaml:24 (first of 41; grep -cE '^\s+schema: "' = 41), e.g. schema: "schemas/requests.schema.json#/$defs/AuthAppleRequest".
  • Evidence: in OpenAPI 3.1 schema must be a Schema Object (object or boolean); a string is illegal. python3 -m openapi_spec_validator openapi.yaml → exit 1: "'schemas/requests.schema.json#/$defs/AuthAppleRequest' is not of type 'object', 'boolean'". check.py cannot catch this by design — its YAML-subset reader extracts operationIds only — yet its OK line says "OpenAPI 3.1 in sync", which reads as stronger than it is. The SPEC pins future work to this file: §7.4 "Every response validates against the module's contribution to contracts/openapi.yaml in tests", §8.5 client "generated/validated against contracts/openapi.yaml", §11.1 round-trip "validated against contracts/openapi.yaml". Any generator/validator/docs toolchain fed this file rejects it as-is.
  • Smallest correct fix: mechanical rewrite of the 41 schema: values to schema: { $ref: "..." }; then optionally teach check.py to reject string-valued schema: keys (its parser already sees those lines) or run a reference OpenAPI validator as a second check.

2. Minor — two dangling "section N.N" cross-references, contradicting the body's "0 unresolved" claim.

  • SPEC.md:78 — "food-safety lint and allergen tagging run on the phone first; see section 7.5" — this SPEC's §7 ends at 7.4, and the overhaul SPEC's §7 has no numbered subsections (its bullet 5 is the GRDB write-authority rule, not lint). Likely meant §6.5 (Automated screening).
  • SPEC.md:187 — "(section 10.5 for the mock rationale: hiding live tallies removes bandwagon-voting…)" — this SPEC's §10 has no subsections; overhaul §10 item 5 is LeChef; git grep bandwagon over docs/spec-overhaul-20261011 returns nothing.
  • The body's cross-reference check ("a script resolved every internal §N.N reference — 0 unresolved") evidently matched only the §N.N form, not the prose section N.N form.
  • Smallest correct fix: repoint line 78 → §6.5; on line 187 drop the number and cite the real source (the tally rule lives in mocks/community.html:155's aggregate-notes rule) or name the overhaul section explicitly.

3. Minor — check.py validates a subset of the schemas' own constraints; "validates every example against its schema" overstates.

  • Evidence: the 24 schemas carry 12 pattern, 29 maxLength, 13 minLength, 15 minimum, 5 maximum, 1 exclusiveMinimum constraints; check.py implements none of them. Mutation test: an example with every string stretched ×500 (breaking every maxLength) plus a pattern-breaking value still passed except the structural checks I deliberately broke. Today this is latent, not live — the reference validator (jsonschema Draft 2020-12) passes all 31 manifest-mapped examples with zero failures. The risk is drift: a future example violating length/regex/numeric bounds passes the machine check and becomes a canonical fixture for §8.5's decoding tests and §11.1's round-trip tests.
  • Smallest correct fix: ~12 lines in check.py (re.search for pattern; comparisons for the four numeric keywords and two length keywords), or one docstring line stating the limitation so the body can claim it accurately.

4. Minor — the PR body says "Base: main"; the PR targets alpha.

  • gh pr view --json baseRefName → alpha. One-word body fix (the overhaul-SPEC pointer beside it is fine).

Verified (commands → results)

  • gh pr view 150 --comments, gh pr diff 150 (full diff read: 59 files, +4018/−0, all under docs/spec/community/), gh pr checks 150 → build-and-test pass (5m29s), dead-code-advisory pass; CodeRabbit skipped (bot user) — the only existing comment.
  • Checkout at 0fd6113; repo guidance (AGENTS.md) read; commit stats confirm both commits confined to docs/spec/community/ (59 files +3965, then 9 files +184/−131).
  • python3 docs/spec/community/contracts/check.py → exit 0 with the body's exact claimed output "OK - 24 schemas, 33 operations, 31 example files, OpenAPI 3.1 in sync."
  • Independent reference validation (jsonschema Draft 2020-12 + referencing registry over the schemas' $ids): 0 metaschema failures across all 24 schemas; 0 failures across all 31 manifest-mapped examples — so finding 3's blind spot is currently latent.
  • check.py bites when it should: mutated createTable.request.json (required fields removed + unexpected property) → exit 1 with both problems named; restored → exit 0; git status --porcelain empty afterwards (no repo file left modified; nothing committed or pushed by this review).
  • Counts: SPEC.md 623 lines / 13 H2 sections (body: ~620 / 13 ✓); 24 schemas ✓; 33 manifest operations = 33 OpenAPI operationIds ✓; 31 examples = 21 responses (33 − 12 declared no-body) + 10 requests ✓.
  • Citation spot-checks against the cited heads (all fetched this session): PR feat(community): FLCommunityCore — sharing, challenges, taste profile, user recipes, Explore ranking #106's ExploreRanking.swift has fit: 0.6, taste: 0.4, neutralTastePrior: 0.5, .rounded(toPlaces: 6) ✓; PR Community backend: scaffold, identity, Explore with moderation #104's community/shared/sessionCore.ts has fla1./flr1. and family-revocation verdicts, config.ts has minCookedCountFloor: 10 and reportLimitPerDay: 10 ✓; PR kitchen-knowledge: challenge packs (budget, food-bank, seasonal, use-it-up) #116's four pack files + usda_ingredient_catalog.sqlite ✓; PR Personal cookbook: store, transaction service, and flow-check (M1) #71's CookbookRecipePolicy/CookbookRecipeEditor/UserRecipeTransactionService paths ✓; PR Food-safety canon: cited rulebook, strict fail-closed linter, spoilage copy lint, conformance CLI (supersedes #97) #126 data/food-safety/rules.json and PR FLIngredientFacts: canonical ingredient facts with fail-closed restriction evaluation #127 data/ingredient-facts/ ✓.
  • Alpha claims: no Sign-in-with-Apple/community-client code under apps/ or packages/ (git grep on origin/alpha) ✓; server.ts /healthz present ✓; Migrations.swift is 537 lines with the recipes table at line 14 ✓.
  • Overhaul-branch quotes: "perform your cooking for likes", "Imported text from someone else…", "reports hide it pending review", "Sharing requires a Sign in with Apple account and is adult-only (18+)" (SPEC.md:105) all verbatim ✓; "Counts appear at 10 cooks or more…" verbatim at mocks/community.html:155 ✓; overhaul §10 items 4 and 6 match the SPEC's "§10 decision 4"/"§10.6" citations ✓; §9.7's mock copy strings verbatim ✓; stage-0 planning file present ✓.
  • Prose↔contract: /challenges/{challengeId}/vote PUT/DELETE match §9.4 ✓; no /web/ path in openapi.yaml (matches §4.4's "outside the contract") ✓; table_full/recipe_revised_offline/quarantined_rights codes present in OpenAPI descriptions and error.schema.json ✓; explore-feed maxItems: 100 ✓; 204 responses present for the no-body operations ✓.

Couldn't verify

SamGu-NRX and others added 2 commits October 15, 2026 19:52
Round-2 review (comment 6199518876), all four findings addressed, each
with a check that fails before its fix:

- Major: openapi.yaml was not valid OpenAPI 3.1 - all 41 schema values
  were bare strings. Rewritten to Schema Objects ({$ref: ...}); check.py
  now rejects string-valued schema keys (failed with 41 errors before
  the rewrite, passes after).
- Minor: two dangling prose cross-references (SPEC.md:78 section 7.5,
  :187 section 10.5). check.py now lints both the §N.N and prose
  section/forms (failed with 2 errors before, passes after). A same-class
  audit found six more wrong-target refs left by the renumber (lines 68,
  76, 87, 115, 134, 217), all repointed. :187 now cites the real source:
  section 9.5's mock copy, with the overhaul mock's aggregate rule named.
- Minor: check.py now enforces pattern, minLength/maxLength and
  minimum/maximum/exclusiveMinimum on examples. Mutation control: the
  old checker passed a 500-char name (maxLength 60) and a pattern-
  breaking entryId with exit 0; the new checker fails both; restored
  examples pass.
- Minor: PR body said Base: main; the PR targets alpha. Fixed in the
  body.

Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
Every OpenAPI 3.1 Response Object now carries a required description
(33 success responses were missing one), and every path template
variable is declared as a required path parameter (15 paths, 22
undeclared occurrences), fixing both findings from openapi-spec-validator.

check.py: response objects without descriptions, path parameters not
declared, and the YAML-subset reader's block-sequence branch precedence
are now all enforced/fixed. Runs fail-first before each fix.
@SamGu-NRX
SamGu-NRX merged commit 416016d into alpha Oct 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants