waxwing/app/core/config.py
pyr0ball 5f5cb99db6 feat: bootstrap Waxwing Phase 1 scaffold
Plant registry, grow event calendar, and gardening knowledge base
populated via cf-harvest ingest endpoint. All 23 tests passing.

Stack:
- FastAPI + SQLite (cf-core migrations) on port 8522
- Vue 3 + Vite + Pinia SPA on port 8521
- 5 SQL migrations: locations → plants → grow_events, knowledge_sources → knowledge_facts
- Earthy green theme (--color-primary: #4a7c59) matching CF theme system

Knowledge ingest contract:
- POST /api/v1/knowledge/ingest — idempotent on fact_hash (sha256 of type+payload+video_path)
- 8 fact types: companion_planting, soil_amendment, propagation, pest_diagnosis,
  harvest_timing, instruction, medicinal, history_context
- Partial batch failure: malformed facts collected in rejected[], valid facts inserted
- Re-ingesting same video batch: facts_skipped_duplicate > 0, no duplicates

Wired views: RegistryView (plant CRUD), KnowledgeView (facts + type filter chips)
Stub views: CalendarView, SettingsView
2026-06-10 00:03:41 -07:00

37 lines
1.2 KiB
Python

"""Waxwing application config — env-driven, no pydantic-settings dependency."""
from __future__ import annotations
import os
from pathlib import Path
from circuitforge_core.config.settings import load_env
_ROOT = Path(__file__).resolve().parents[2]
load_env(_ROOT / ".env")
class Settings:
API_PREFIX: str = os.environ.get("API_PREFIX", "/api/v1")
PROJECT_NAME: str = "Waxwing — Gardening Assistant"
CORS_ORIGINS: list[str] = [
o.strip()
for o in os.environ.get("CORS_ORIGINS", "").split(",")
if o.strip()
]
DATA_DIR: Path = Path(os.environ.get("DATA_DIR", str(_ROOT / "data")))
DB_PATH: Path = Path(os.environ.get("DB_PATH", str(DATA_DIR / "waxwing.db")))
COORDINATOR_URL: str = os.environ.get("COORDINATOR_URL", "http://localhost:7700")
CF_LICENSE_KEY: str | None = os.environ.get("CF_LICENSE_KEY")
DEBUG: bool = os.environ.get("DEBUG", "false").lower() in ("1", "true", "yes")
CLOUD_MODE: bool = os.environ.get("CLOUD_MODE", "false").lower() in ("1", "true", "yes")
CLOUD_DATA_ROOT: Path = Path(os.environ.get("CLOUD_DATA_ROOT", "/devl/waxwing-cloud-data"))
def ensure_dirs(self) -> None:
self.DATA_DIR.mkdir(parents=True, exist_ok=True)
settings = Settings()