# Data Goblin Plan This is the high-level development plan for **Data Goblin**, a small personal logging system with a SQLite core and a fast CLI. ## v0.1 Goal Make `dgob` usable for daily manual logging. ```text v0.1 = I can use dgob every day instead of my Markdown file. ``` No weather sync, REST API, charts, or markdown import yet. ## v0.1 Scope ### Include - `dgob version` - `dgob init` - `dgob add` - `dgob symptom` - `dgob event` - `dgob coffee` - `dgob painkiller` - `dgob today` - `dgob show DATE` - `dgob events` - SQLite schema creation - simple friendly CLI output ### Exclude For Now - SMHI weather integration - blood pressure logging - REST API - markdown import - correlations/statistics - full TUI - authentication/users ## v0.1 Database Tables ### `daily_log` One row per day. Fields: - `date` - `mood` - `sleep_quality` - `slept_hours` - `notes` - `created_at` - `updated_at` ### `daily_symptom` Daily symptom severity values. Examples: - `tooth_comfort` - `headache` - `jaw_tension` Fields: - `id` - `date` - `symptom` - `severity` - `notes` - `created_at` ### `event` Timestamped things that happened. Examples: - `coffee +1 cup` - `painkiller +1 dose` - `walk 25 min` Fields: - `id` - `timestamp` - `kind` - `amount` - `unit` - `notes` - `created_at` ### `schema_version` Tracks database schema version for future migrations. ## Suggested Commands ### Initialize Database ```sh dgob init ``` ### Add Or Update Daily Log ```sh dgob add --mood 7 --sleep 6.5 --sleep-quality 6 --notes "jaw annoying" dgob add --date 2026-05-05 --mood 7 ``` ### Add Daily Symptom ```sh dgob symptom tooth_comfort 4 dgob symptom headache 2 --notes "started after lunch" ``` ### Add Events ```sh dgob event coffee dgob event painkiller dgob event walk --amount 25 --unit min ``` ### Convenience Aliases ```sh dgob coffee dgob painkiller ``` ### Show Data ```sh dgob today dgob show 2026-05-05 dgob events # defaults to today dgob events --date 2026-05-05 ``` ## Database Path Priority Planned lookup order: 1. `--db ./path/to/goblin.db` 2. `DATA_GOBLIN_DB` 3. default path: `~/.local/share/data-goblin/goblin.db` ## Project Structure Idea ```text src/ main.odin dgob/ db.odin schema.odin daily.odin symptom.odin event.odin query.odin time.odin ui.odin ``` ## v0.1 Acceptance Checklist The following flow should work: ```sh dgob init dgob version dgob add --mood 7 --sleep 6.5 --sleep-quality 6 --notes "jaw annoying" dgob symptom tooth_comfort 4 dgob coffee dgob coffee dgob event walk --amount 25 --unit min dgob today dgob show 2026-05-05 dgob events --date 2026-05-05 ``` Expected database result: ```text one daily row one symptom row three event rows ``` ## Future Milestones ### v0.2 Markdown Import - Import existing Markdown logs. - Preserve raw data where parsing is uncertain. - Report import issues instead of silently discarding data. ### v0.3 Blood Pressure - Add dedicated blood pressure table. - Support multiple readings per day. - Track systolic, diastolic, pulse, posture, arm, and notes. ### v0.4 SMHI Weather Sync - Fetch daily weather and pressure data from SMHI Open Data (no authentication required, CC BY 4.0). - Store daily pressure average/min/max. - Later support hourly observations. #### SMHI API Notes (researched 2026-05-06) The old PMP3gv2 API was shut down on 2026-03-31 and returns HTTP 404. Use the replacement: **SNOW1gv1**. Endpoint: ``` GET https://opendata-download-metfcst.smhi.se/api/category/snow1g/version/1/geotype/point/lon/{LON}/lat/{LAT}/data.json ``` Key response fields (under `timeSeries[n].data`): | Field | Unit | Notes | |---|---|---| | `air_pressure_at_mean_sea_level` | hPa | Main pressure field | | `air_temperature` | °C | | | `relative_humidity` | % | | | `symbol_code` | integer 1–27 | Weather condition | | `wind_speed` | m/s | | - All times in the response are UTC. Time key is `time` (not `validTime` as in the old API). - Missing values use `9999` as sentinel — filter these out. - Coordinates in the response are flat `[lon, lat]` (not nested `[[lon, lat]]`). - Use `referenceTime` from the response body instead of the removed `approvedtime.json` endpoint. - No hard rate limit, but SMHI's terms ask you to cache responses and avoid redundant fetches. A once-daily fetch at sync time is well within acceptable use. - Fetch once per day; take `timeSeries[0].data.air_pressure_at_mean_sea_level` for near-current pressure. ### v0.5 Summary Views And Export - Add joined daily summary view. - Export CSV for external analysis. ### v0.6 Simple Analysis - Basic stats. - Simple correlations. - Pressure delta vs symptom severity. ### v0.7 REST API - Add thin HTTP API over the same core logic. - Keep business logic out of the server layer. ### v0.8 Withings Integration - OAuth authentication against the Withings Public API (no enterprise contract required). - Store access token and refresh token in a new `integration_config` table. - Implement token refresh automatically on expiry. - New command: `dgob withings auth` — opens OAuth URL in browser, captures callback, stores tokens. - New command: `dgob withings sync` — pulls data since last sync using `lastupdate` cursor. - Sync cursor stored in `integration_config` to support incremental updates. #### Data to sync - **Weight and body composition** (`measure?action=getmeas`) → `measurements` table. - **Blood pressure and heart rate** (`measure?action=getmeas`) → `measurements` table (feeds into v0.3 data). - **Sleep summary** (`sleep?action=getsummary`) → sleep fields in `daily_log` (duration, stages, HRV, score). - **Daily activity** (`measure?action=getactivity`) → `event` rows (steps, calories, distance). #### Notes - Withings Public API is free for personal use with no contract. - OAuth callback can use a local `http://localhost:PORT/callback` for CLI use. - Available biomarkers depend on which Withings devices you own. - Rate limit on the free tier: 120 requests per minute, up to 5 000 users. ## Notes Keep the goblin small at first. Build the logging habit before building the observatory.