# garden

Garden management web app at https://garden.riverway.ca. FastAPI + SQLite + Jinja2.
Tracks the user's home garden — areas (with sketch layouts + plant positions),
plantings, plant groups, watering stations, supplies, species/varieties (with
sketch-spacing metadata), and unified field notes (comments + raw captures).

For the full architecture, status, deferred work, and known issues, see
**[PLANNING.md](./PLANNING.md)**. For the field-note processing flow and accumulated
accuracy rules, see **[PROCESSING.md](./PROCESSING.md)**.

## Project info
- Type: custom (FastAPI in Docker)
- Internal port: 8000 (mapped to host port `${PORT}` in `.env`)
- Domain: garden.riverway.ca
- Created by: rian
- Created: 2026-04-13

## Getting started for the user
1. Visit https://garden.riverway.ca and log in.
2. Quick capture (audio + photo + text): `/capture`.
3. Process unprocessed field notes: see PROCESSING.md flow.
4. Process existing comments since the last run: same flow (comments and field
   notes share the unified `field_notes` table).

## Managing the container
Always go through `srv-gw` (NOT `docker` directly):
```bash
srv-gw deploy --project garden     # full recreate (reads .env + docker-compose.yml)
srv-gw restart --project garden    # quick restart (does NOT reload .env)
srv-gw status --project garden
srv-gw logs --project garden
srv-gw stop --project garden
srv-gw start --project garden
```

**Note on `.env` changes:** plain `restart` does NOT reload env vars. Use `deploy` to
pick up new credentials, model changes, etc.

## External services

### Google AI Studio (Gemini)
Used for audio transcription of field notes. Future: comment rollup, planning
assistant, AI auto-classification. One key per app per server policy.

- **Account:** rianbowden@gmail.com (Gemini Pro tier — note: Pro subscription
  does NOT grant API access; the API key below is a separate Google AI Studio
  key billed under Tier 1 / Postpay)
- **Project name:** `gen-lang-client-0482810064` ("Default Gemini Project")
- **Project number:** `72950551150`
- **Manage keys / usage:** https://aistudio.google.com/apikey
- **Key location:** `GEMINI_API_KEY` in `/srv/apps/garden/.env` (660 rian:garden-dev).
  Never commit this file. To rotate: regenerate in AI Studio, update `.env`,
  `srv-gw deploy --project garden` (deploy, not restart, since env_file reload).
- **Default model:** `gemini-2.5-flash` for transcription (override with
  `GEMINI_TRANSCRIBE_MODEL` env var).

## Working in this codebase

### Where things live
- `/srv/apps/garden/app/main.py` — single-file FastAPI app (~5300 lines): all routes,
  schema migrations in `init_db`, helpers, the species-icon registry, sketch geometry
  math, field-note processing helpers.
- `app/templates/` — 35+ Jinja2 templates including reusable macros under `_*.html`.
- `app/static/` — vanilla JS modules + style.css.
- `data/garden.db` — SQLite, with periodic backups in the same dir.
- `data/notes/YYYY-MM/<uuid>.<ext>` — all uploaded media (capture audio + photos AND
  featured images for any entity).
- `data/artifacts/` — AI-generated markdown (planting plans, fertilization schedules,
  shopping lists, watering plans).

### Conventions baked in
- **Macros for reusable UI:** `_capture_widget.html`, `_comments.html`,
  `_featured_image.html`, `_picker.html`, `_species_icons.html`. Pull these in via
  `{% from '_x.html' import macro %}` rather than duplicating UI.
- **Featured image system** — entities with featured images use the
  `featured_image_block(entity_type, id, path, name)` macro on detail pages and the
  `featured_image_thumb(path, alt, extra_class)` macro on cards. Backend dispatch
  through `FEATURED_IMAGE_ENTITIES` constant + `_set_featured_image()` helper.
- **Sketch geometry** — `sketch_geometry(L, W, rotation_deg)` helper computes viewBox,
  rect coords, and rotation origin for the rotated rectangle. Used for both area
  sketches and (later) any other rotated-rect rendering.
- **Plant spacing** — every species has `plants_per_unit` + `space_per_unit_sqft`.
  Varieties have nullable overrides. `load_plants_by_area` resolves the effective
  spacing via `COALESCE(variety, species, default)`.
- **Field notes (unified)** — `field_notes` table holds both raw captures (status='new'
  with audio/photo) AND finalized comments (status='processed' with body+kind+
  comment_date+targets). The legacy `comments` and `comment_targets` tables were
  dropped 2026-05-07; the unified table is the only source. Helper function names
  like `load_comments` keep their old names for now.

### Doing things
- **Adding a new species/variety/area/etc.** → use the form-based UI; backends
  validate. For bulk imports, write a one-off script that uses the
  helper functions in main.py (search for `get_or_create_species`, `add_pg`, etc.).
- **Processing field notes** → follow PROCESSING.md two-pass flow. Always present
  action list before executing.
- **Adding a new entity type** → see the deferred "animals" entity in PLANNING.md
  for a worked-example checklist.
- **Schema changes** → add to the `init_db()` migration block in main.py with an
  idempotent `if column not in cols` guard. Never drop columns or data without an
  explicit ask + a fresh DB backup.
- **Restarting after code changes** → `srv-gw restart --project garden` (templates
  reload per-request; restart picks up main.py changes).
- **Restarting after `.env` changes** → `srv-gw deploy --project garden` (full
  container recreate is required to reload `env_file`).

### Backups
- DB backups land in `data/garden.db.backup-*`. Notable:
  `garden.db.backup-20260504-225256-pre-fnmerge` (pre-comments-unification snapshot).

## Recent significant changes
See PLANNING.md "Done since last revision" section for the full list. Highlights from
the 2026-04-17 → 2026-05-07 window:
- Field-note unification (comments + captures → one `field_notes` table; legacy
  `comments` and `comment_targets` tables dropped 2026-05-07)
- Audio transcription via Gemini 2.5 Flash
- Featured images on 8 entity types
- Area sketch SVG with 45° rotations, plant icons, child-area positioning, dotted grid
- Plant spacing metadata on species + variety override
- Spring 2026 planting plan committed (planting #26 with 65 plant_groups + comfrey #54)
- Watering schedule artifact (single-zone time-of-day grid)
- 16 accuracy rules accumulated in PROCESSING.md from 2 processing passes
- **Archive flag** (`is_archived`) on every entity (2026-05-07) — `_archive.html`
  macro renders the chip + button; default queries filter archived out, `?archived=1`
  reveals them. Cascades documented in PLANNING.md.
- **Animals as species** (2026-05-07) — `species.type` (plant|animal) +
  `primary_function` (edible/ornamental/support/weed for plants;
  beneficial/pest for animals). No separate animals table.
- **Click-to-edit detail pages** (2026-05-07) — every detail page field is wrapped in
  `<span class="editable">`; click → input → blur saves via single
  `POST /api/edit/{entity}/{id}` endpoint validated against `EDITABLE_FIELDS` whitelist.
  The old `*_form.html` templates are still used by `/<type>/new` creation flows;
  `/<type>/{id}/edit` GET routes are gone (404). New file: `app/static/inline-edit.js`.
- **Floating capture (chat-bubble)** (2026-05-07) — fixed bottom-left bubble on every
  authenticated page opens a modal with `Note | Chat` toggle. Note tab uses the existing
  capture widget with a primary-target pill (defaults to current page's entity, falls
  back to current year). Chat tab is a Gemini function-calling chat assistant
  (`gemini_chat_complete` runs the tool-call loop) with hybrid grounding: light starter
  context + 10 callable tools (`get_planting_detail`, `find_plants`, `find_empty_space`,
  `search_notes`, etc.) + meta `suggest_new_tool`. Configurable via
  `GEMINI_CHAT_MODEL` (default `gemini-2.5-flash`).
- **Activity log** (2026-05-07) — `activity_log` table records every user mutation
  (add/edit/delete/archive/unarchive) with old→new diffs for edits. `/timeline` and
  `/timeline/{type}/{id}` accept `?view=log` to flip from comments to the log feed.
  Sketch repositioning is intentionally NOT logged (too noisy).
- **Layout mode** (2026-05-07) — new `/areas/{id}/layout` route with full-viewport
  tap-pick-tap-place editing, inventory tray, auto-rotate to fit screen,
  companion-aware Gemini auto-arrange. Mobile-friendly alternative to the
  drag-in-dialog model. New file: `app/templates/layout_mode.html`. New endpoint:
  `POST /api/areas/{id}/auto-arrange`.

## Tone and conventions
- **Always present a plan before executing data changes.** The user explicitly works
  in pass 1 (per-note draft) → pass 2 (consolidate) → confirmation → execute.
- **Be paranoid about typos and ambiguity.** PROCESSING.md Rule 4 (auto-fix typos)
  and Rule 13 (verify sub-area paths) exist because real bugs hit during processing.
- **When the user references existing data, search globally** (PROCESSING.md Rule 16).
  Don't restrict to the subtree you're already focused on.
- **Updates to overviews when state changes** (PROCESSING.md Rule 15) — when a note
  describes a state change, also revise the affected entity's `notes`/`structure_features`,
  not just file a comment.
