Commit graph

103 commits

Author SHA1 Message Date
da940ebaec feat: add get_role_candidates() and build_from_selection() to assembly engine
Both functions are DB-free public API additions to assembly_recipes.py.
get_role_candidates() scores pantry candidates against a wizard step using
element-profile overlap with prior picks; build_from_selection() builds a
RecipeSuggestion from explicit role overrides with required-role validation.
2026-04-14 11:06:08 -07:00
4f1570ee6f feat: add Store.get_element_profiles() for wizard role candidate lookup 2026-04-14 10:50:46 -07:00
1a5fb23dfd feat: add slug/icon/descriptor to AssemblyTemplate and get_templates_for_api()
Extends AssemblyTemplate dataclass with slug, icon, descriptor, and
role_hints fields. Updates all 13 template instantiations with
appropriate values. Adds _TEMPLATE_BY_SLUG lookup dict and
get_templates_for_api() serialiser for the templates endpoint.
2026-04-14 10:36:58 -07:00
65ef65bb4c feat: add Pydantic schemas for Build Your Own tab endpoints 2026-04-14 09:45:05 -07:00
d24f87a476 docs: add link to docs.circuitforge.tech/kiwi in README 2026-04-14 08:19:32 -07:00
878a9a268c fix: community module integration fixes -- slots payload + ForkResult type
- PublishPayload gains optional slots field; PublishPlanModal maps
  plan.slots into the payload so the backend can compute element
  snapshot scores (seasoning, richness, etc.) from actual recipes
- plan-forked emit type updated to ForkResult across CommunityFeedPanel
  and RecipesView so forked_from is preserved for future navigation
2026-04-13 14:21:33 -07:00
d7bfc083e7 fix: Hall of Chaos quality fixes -- timer cleanup, aria-live, reduced-motion
- onUnmounted clears blooperHoldTimer to prevent stale callback after
  component teardown
- HallOfChaosView loading state gains aria-live="polite" so state
  transitions are announced to screen readers
- CommunityFeedPanel reduced-motion block resets toast translateY offset
  to avoid flash-of-offset-position on slow paint cycles
2026-04-13 12:34:23 -07:00
9246935fd7 feat: Hall of Chaos easter egg -- HallOfChaosView + long-press trigger
Adds the Hall of Chaos overlay component (recipe blooper gallery with
static CSS tilts, chaos level counter, panel-local overlay) and wires
the 800ms long-press trigger on the Bloopers filter tab in
CommunityFeedPanel. Pairs with the backend /community/hall-of-chaos
endpoint and test added in Task 10.
2026-04-13 12:30:48 -07:00
f92ac7a509 fix: publish modal a11y -- dialog-scoped Tab guard + correct first-focus in OutcomeModal 2026-04-13 11:48:57 -07:00
9603d421b6 feat: community publish modals -- focus traps, aria-live, plan + outcome forms 2026-04-13 11:45:32 -07:00
730445e479 fix: community feed a11y -- reduced-motion guards + tablist focus management 2026-04-13 11:38:17 -07:00
8731cad854 feat: community feed Vue frontend -- Pinia store + feed panel + RecipesView tab 2026-04-13 11:34:54 -07:00
86dd9adbcb refactor: use sqlite3.IntegrityError directly for slug collision guard 2026-04-13 11:25:10 -07:00
69e1b70072 fix: community endpoint quality issues — input validation, slot key guard, slug collision, ValueError handling 2026-04-13 11:23:45 -07:00
9ae886aabf fix: community endpoint spec gaps — ld+json content negotiation + premium post tier filter 2026-04-13 11:20:28 -07:00
9c64de2acf feat(community): community API endpoints — browse, publish, fork, delete, RSS, AP
Adds GET /community/posts, GET /community/posts/{slug}, GET /community/feed.rss,
GET /community/local-feed, POST /community/posts, DELETE /community/posts/{slug},
POST /community/posts/{slug}/fork, and POST /community/posts/{slug}/fork-adapt (501 stub).
Wires init_community_store into main.py lifespan. 7 new tests; 115 total passing.
2026-04-13 11:14:18 -07:00
81107ed238 feat(community): KiwiCommunityStore + pseudonym helpers in per-user store 2026-04-13 10:54:13 -07:00
b1ed369ea6 feat(community): mDNS advertisement via zeroconf — defaults OFF, opt-in per a11y audit 2026-04-13 09:59:50 -07:00
f12699349b feat(community): RSS 2.0 feed generator + ActivityPub JSON-LD scaffold 2026-04-13 09:44:51 -07:00
74c7272a50 feat(community): element snapshot — SFAH scores, allergen detection, dietary tags 2026-04-13 09:19:57 -07:00
1a9a8579a2 feat(community): add COMMUNITY_DB_URL config + community features to tiers 2026-04-13 09:02:44 -07:00
b97cd59920 feat(community): migration 028 — community_pseudonyms table in per-user kiwi.db 2026-04-13 08:13:39 -07:00
0b08fbb18d fix: correct leftover_mode tier in README — Free (5/day) not Premium
tiers.py and recipe_engine.py have always implemented this as Free with
a 5/day rate limit. README inherited a stale tier assignment from an
earlier design that was superseded when the rate-limit approach was chosen.

Closes #67
2026-04-12 18:06:44 -07:00
0b74915ee0 feat(community): wire COMMUNITY_DB_URL + COMMUNITY_PSEUDONYM_SALT into cloud compose 2026-04-12 17:45:20 -07:00
192ecc7078 fix(browse): use subquery for FTS5 MATCH (alias unsupported in WHERE clause) 2026-04-09 12:53:06 -07:00
0d7223a12b fix(browse): remove source_url reference (column is source; field unused in response) 2026-04-09 12:47:23 -07:00
0b9e3553a7 fix(frontend): remove unused removeConstraint function (TS6133) 2026-04-09 12:31:18 -07:00
6da86dd0a7 feat(hard-day): tier-sort results — premade first, simple second
Hard Day Mode now prioritises results by effort tier before match_count:
  Tier 0 (premade): frozen/instant title keywords, or ≤2 ingredients with
    heat/microwave-only steps (frozen dinner, heat-and-eat, microwave meal)
  Tier 1 (super simple): ≤3 ingredients + any easy method (quesadilla,
    cheese toast, scrambled eggs)
  Tier 2 (easy/moderate): everything else that passed the 'involved' filter

Assembly templates default to tier 1 (inherently simple). Normal mode sort
is unchanged — match_count only.
2026-04-08 23:18:29 -07:00
a523cb094e perf(browser): replace LIKE scans with FTS5; cache category counts
- Add migration 021: recipe_browser_fts FTS5 table on category + keywords
  columns, eliminating LIKE '%keyword%' full sequential scans on 3.1M rows
- _count_recipes_for_keywords now uses FTS5 MATCH (O(log N) vs O(N))
- browse_recipes reuses cached count, eliminating the second COUNT(*) scan
  per page request; ORDER BY r.id replaces the unindexed ORDER BY title sort
- Module-level _COUNT_CACHE keyed by (db_path, keywords) means domain-switch
  category counts are computed once per process lifetime

feat(find): dietary preset grid, Big 9 allergen pills, Hard Day Mode surface

- Dietary constraints replaced with toggle-button preset grid (8 options)
  + free-text "Other" field; removes dense freeform text input
- Allergies replaced with Big 9 pill picker (peanuts, tree nuts, shellfish,
  fish, milk, eggs, wheat, soy, sesame) + "Other" for custom entries
- Hard Day Mode surfaced as a standalone aria-pressed button above the
  dietary collapsible; no longer buried inside a collapsed section
- Active-state dot indicators on both collapsibles show filter engagement
  at a glance without expanding

fix(a11y): aria-describedby wiring for wildcard checkbox and tag inputs (#40)

- Persistent hint spans replace placeholder-only instructions for constraint
  and allergy fields (WCAG 3.3.2)

fix(browse): auto-select highest-count category on domain switch (#41)

- Eliminates the 3-decision cold start (domain → category → content)
- Surprise Me button added for zero-decision random navigation
2026-04-08 23:10:48 -07:00
4bb93b78d1 feat(ux/nd): collapse Find tab into level picker + two filter sections with active indicators 2026-04-08 22:51:43 -07:00
8c1443d156 fix(ux/nd): Browse tab auto-selects top category on mount; add Surprise Me button (closes #41) 2026-04-08 22:30:49 -07:00
001e46ba9a fix(a11y): add aria-describedby and persistent hints for wildcard checkbox and tag inputs (closes #40) 2026-04-08 22:27:28 -07:00
d7c0ae011a chore: bump pyproject.toml version to 0.2.0 2026-04-08 22:16:38 -07:00
f1cde57fdf chore: bump version to 0.2.0 2026-04-08 22:10:36 -07:00
3530071187 Merge pull request 'feat: Phase 2 — saved recipes, browser, accessibility, level UX' (#69) from feature/orch-auto-lifecycle into main 2026-04-08 15:13:45 -07:00
74a7c068bc feat(ux): rename creativity levels with descriptive labels and inline descriptions
- "Use What I Have" / "Allow Swaps" / "Get Creative" / "Surprise Me 🎲"
- Active level shows a one-liner description beneath the selector
- Hover tooltips repeat the description for mouse users
- Label changed from "Creativity Level" to "How far should we stretch?"
- Wildcard confirmation copy updated to match new framing
2026-04-08 15:03:51 -07:00
e203ad4bdc fix(a11y): WCAG accessibility improvements across frontend
- Global :focus-visible ring in theme.css — covers all interactive elements
  with keyboard-nav focus ring without affecting mouse/touch users
- Removed pulse-urgent animation (safety policy violation — infinite animation)
- Global prefers-reduced-motion guard suppresses all animations system-wide
- Added .sr-only utility class for screen-reader-only content
- Tab bar (RecipesView): role=tablist/tab/tabpanel + aria-selected + arrow key nav
- Modal focus management: trap focus on open, restore on close, Escape to dismiss
  (SaveRecipeModal, RecipeDetailPanel, SavedRecipesPanel new-collection dialog)
- aria-modal=true on all modal dialogs
- Icon-only buttons now have contextual aria-labels:
  chip-remove: "Remove constraint: vegetarian" / "Remove allergy: peanuts"
  bookmark: "Bookmark: {title}" / "Remove bookmark: {title}"
  dismiss: "Hide recipe: {title}"
  browser save toggle: "Save recipe: {title}" / "Edit saved recipe: {title}"
- InventoryList qty +/- buttons: aria-label="Increase/Decrease quantity"
- Quantity number inputs: aria-label="Quantity"
- Select elements (SavedRecipesPanel): labelled via .sr-only for-id pattern
- Star rating group: role=group + aria-labelledby; each star: aria-pressed
- Ingredient checkboxes: label wraps input + span (label association fix)
- aria-live="polite" announcer for dynamic recipe results count
- Dynamic aria-labels on status messages (role=alert/status + aria-live)
2026-04-08 14:35:18 -07:00
793df1b5cf feat: saved recipes, recipe browser, and recipe detail panel
- Saved recipes: save/unsave, star rating, notes, tags, collections (migrations 018-020)
- Recipe browser: domain/category browsing with pantry match badges, pagination
- Recipe detail panel: full directions, ingredient checklist, swap candidates, prep notes
- Grocery links: affiliate links for missing ingredients
- Nutrition filters and display chips on recipe cards
- Bookmark toggle persisted to saved_recipes table
- Tier gates on saved recipes (paid) and collections (premium)
- Browser telemetry for domain/category click tracking
- Cloud compose: CLOUD_DATA_ROOT volume mount for per-user SQLite trees
- manage.sh: cf-orch agent sidecar in local stack
- README: updated feature list and stack description
2026-04-08 14:35:02 -07:00
c064933b14 refactor: use shorter circuitforge_core.api import for feedback router 2026-04-05 21:21:50 -07:00
f3bc796f2c feat: migrate feedback endpoint to circuitforge-core router
Replace hand-rolled feedback.py with make_feedback_router() from
circuitforge_core.api.feedback. Update tests to mount the shared
router on a minimal FastAPI app and mock at the core module level.
2026-04-05 17:57:36 -07:00
6a59c8dfd1 fix: row_factory in _household_store; validate household_id from Heimdall; monkeypatch CLOUD_DATA_ROOT in accept test; add KIWI_BASE_URL to compose.cloud.yml 2026-04-04 22:59:06 -07:00
11a0d1f3a6 feat: handle household invite accept on app load via URL hash 2026-04-04 22:53:55 -07:00
7cce05b95a feat: household management UI in Settings (Premium-gated) 2026-04-04 22:51:03 -07:00
70b1319b60 feat: add householdAPI typed wrappers to api.ts 2026-04-04 22:48:25 -07:00
c7861344b7 feat: add MessageResponse schema; wire response_model on leave + remove-member endpoints 2026-04-04 22:47:39 -07:00
7650747651 feat: household API endpoints (create, status, invite, accept, leave, remove-member) 2026-04-04 22:45:12 -07:00
dce8d05a09 refactor: use str | None + Field(default_factory=list) in household schemas 2026-04-04 22:41:53 -07:00
2db4de6d8f feat: add household Pydantic schemas 2026-04-04 22:40:30 -07:00
e605954254 chore: bump circuitforge-core dep to >=0.8.0; fix stale resources imports
- pyproject.toml: circuitforge-core>=0.6.0 → >=0.8.0 (orch split)
- vl_model.py: circuitforge_core.resources → circuitforge_orch.client
- llm_recipe.py: circuitforge_core.resources → circuitforge_orch.client
2026-04-04 22:39:04 -07:00
ed6813713e test: use tmp_path for _user_db_path tests; remove duplicate comment
Patch _user_db_path tests to monkeypatch CLOUD_DATA_ROOT onto a
tmp_path so they never touch /devl or any real filesystem path.
Remove duplicate X-Real-IP comment block in cloud_session.get_session.
2026-04-04 22:38:41 -07:00