--ISSUE
Content-Type: application/sprints
Sprints:

--ISSUE
Content-Type: application/modules
Modules:
        - Name: homostat
          Path: .

--ISSUE
Content-Type: application/bugzilla
URL: https://bugs.code.tiararodney.com/rest
Mappings:
        - Module: homostat
          Product: tiararodney.com
          Component: Status Pipeline

--ISSUE
Content-Type: application/issue
ID: 1
Type: feature
Title: Initialize Python package structure
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Set up byteb4rb1e.homostat as a proper Python package with
             pyproject.toml, src layout, and dependencies. Establish the
             foundational project structure for the ETL pipeline.

--ISSUE
Content-Type: application/issue
ID: 2
Type: feature
Title: Write project entrypoint docs
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Create DEVELOPMENT.md, CONTRIBUTING.md, and rewrite README.md as
             the primary entrypoint documents for the repository. These replace
             AGENTS.md as the canonical guides for developers and agents working
             on the project.

--ISSUE
Content-Type: application/issue
ID: 3
Type: feature
Title: Fitbit source adapter
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Extract Fitbit-specific fetch logic into a source adapter module.
             The adapter handles OAuth, token refresh, endpoint paths, rate
             limits, pagination, and raw response handling. Returns raw payloads
             in a consistent envelope with provenance metadata.

--ISSUE
Content-Type: application/issue
ID: 4
Type: feature
Title: fddb source adapter
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Extract fddb-specific fetch logic into a source adapter module. The
             adapter handles login, session handling, HTML fetching, scraping
             mechanics, and request retries. Returns raw payloads in a
             consistent envelope with provenance metadata.

--ISSUE
Content-Type: application/issue
ID: 5
Type: feature
Title: Raw warehouse layer
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Implement the raw warehouse for storing fetched source data with
             minimal interpretation. Uses JSONL for raw payloads partitioned by
             date and source. Includes provenance metadata (source system,
             endpoint, fetch timestamp, source record ID). SQLite tables
             hydrated from JSONL partitions.

--ISSUE
Content-Type: application/issue
ID: 6
Type: feature
Title: Canonical warehouse schema and transformers
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Define the canonical warehouse schema for provider-agnostic domain
             entities (heart_rate_sample, activity_session, sleep_session,
             sleep_stage, body_measurement, nutrition_day, meal, meal_item).
             Implement transformers that map raw provider records into canonical
             records. Store as CSV partitioned by table and day. Distinguish
             observed vs inferred data. Carry provenance from raw layer.

--ISSUE
Content-Type: application/issue
ID: 7
Type: feature
Title: Projection builders
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Implement projection builders that generate status.json and
             history/*.json output files from canonical warehouse data via
             SQLite views. Projections are decoupled from sync — they can be
             rebuilt independently without re-fetching from sources.

--ISSUE
Content-Type: application/issue
ID: 8
Type: feature
Title: Remove legacy scripts
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Remove the original monolithic scripts (fitbit_sync.py,
             fddb_sync.py, backfill.py, log_measurements.py, deploy.sh) once the
             new pipeline fully replaces their functionality.

--ISSUE
Content-Type: application/issue
ID: 9
Type: feature
Title: Intraday projections for heart rate, steps, and calories
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Add intraday projection output for heart-rate-sample,
             step-snapshot, and calorie-snapshot. These expose the full
             per-minute or per-sync resolution as JSON files under the
             projection output, enabling intraday graphs on the site.

--ISSUE
Content-Type: application/issue
ID: 10
Type: feature
Title: Migrate existing data into canonical warehouse
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Manually migrate the existing JSON data (data/status.json and
             data/history/*.json) into the canonical warehouse JSONL partitions.
             This bootstraps the warehouse with historical data so the new
             pipeline has continuity with the old one.

--ISSUE
Content-Type: application/issue
ID: 11
Type: feature
Title: Smoke tests for pipeline
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Add smoke tests that exercise the full pipeline end-to-end against
             live services. Cover Fitbit (fetch, raw warehouse, canonical
             transform, projection) and fddb (fetch, parse, canonical
             transform). Tests are skipped when credentials are not present.

--ISSUE
Content-Type: application/issue
ID: 12
Type: feature
Title: CLI entrypoint
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Add a CLI for the new pipeline: authorize (Fitbit OAuth), sync
             (fetch + warehouse), and project (build projections from
             warehouse). Replaces the old script-based invocation.

--ISSUE
Content-Type: application/issue
ID: 13
Type: feature
Title: Config-driven projection resolution with INI + argparse integration
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Add a config dataclass for projection settings (intraday resolution
             per entity, history days, directories). Load defaults from INI
             file, override via CLI flags. Build argparse introspection that
             generates CLI arguments from dataclass annotations. Apply
             resolution downsampling in projection builder. Config framework
             goes in util/ as a byteb4rb1e-utils migration candidate.

--ISSUE
Content-Type: application/issue
ID: 14
Type: bugfix
Title: Surface resting heart rate in projections
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Extract restingHeartRate from the Fitbit daily heart rate summary
             in the transformer and store as a canonical record. Surface it in
             the status.json projection. Currently hardcoded to 0.

--ISSUE
Content-Type: application/issue
ID: 15
Type: feature
Title: Capture Fitbit goals as observed snapshots
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Extract steps_goal and active_minutes_goal from the Fitbit
             activities endpoint response (payload.goals) and store them as
             canonical snapshot records. Goals change over time and should be
             tracked historically as observed data, not hardcoded. Surface the
             latest values in projections.

--ISSUE
Content-Type: application/issue
ID: 16
Type: feature
Title: Implement steps streak as a projection query
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Compute steps_streak_days as a SQL window function over step
             snapshots in the projection builder. A streak day is any day where
             the max step count exceeds the goal. Currently hardcoded to 0.

--ISSUE
Content-Type: application/issue
ID: 17
Type: feature
Title: CLI command for manual measurements
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Add a measurements command to the CLI for logging body data not
             tracked by wearables (muscle mass, circumferences). Writes directly
             to the canonical warehouse as body-measurement records. Replaces
             log_measurements.py.

--ISSUE
Content-Type: application/issue
ID: 18
Type: bugfix
Title: Fix mypy linting errors
Status: open
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: Resolve the pre-existing mypy errors across the codebase: missing
             type annotations in test_http.py, missing generic type parameters
             in builder.py, untyped imports in adapters/fitbit.py, and other
             strict-mode violations. Goal is a clean tox -e lint pass.

--ISSUE
Content-Type: application/issue
ID: 19
Type: bugfix
Title: Heart rate transformer crashes when value is a string
Status: done
Priority: medium
Created: 2026-03-20
Module: homostat
Relationships: 
Description: The Fitbit intraday HR endpoint sometimes returns
             activities-heart[0].value as a string (average HR) instead of an
             object with restingHeartRate. The transformer calls .get() on the
             string, causing an AttributeError during sync.

--ISSUE
Content-Type: application/issue
ID: 20
Type: bugfix
Title: Add clear_partition to canonical warehouse
Status: open
Priority: medium
Created: 2026-03-21
Module: homostat
Relationships: 
Description: Add a clear_partition(entity_name, date) method to
             CanonicalWarehouse that truncates the JSONL partition before
             writing. Call it at the start of each source sync to prevent
             duplicate records accumulating across repeated syncs.

--ISSUE
Content-Type: application/issue
ID: 21
Type: bugfix
Title: Deduplicate multi-row projection queries
Status: done
Priority: medium
Created: 2026-03-21
Module: homostat
Relationships: 
Description: Add DISTINCT to projection queries for activity_session, meal,
             meal_item, and sleep_stage to prevent duplicate rows when multiple
             syncs have appended to the same partition.

--ISSUE
Content-Type: application/issue
ID: 22
Type: bugfix
Title: Projection drops non-zero measurement values when partial records exist
Status: done
Priority: medium
Created: 2026-03-21
Module: homostat
Relationships: 
Description: The projection picks the latest body_measurement row, but partial
             records (e.g. only waist) have 0 for all other fields, overwriting
             previously known values. Fix by coalescing the latest non-zero
             value per field across recent records using a CTE.

--ISSUE
Content-Type: application/issue
ID: 23
Type: bugfix
Title: bs4 dependency missing
Status: done
Priority: medium
Created: 2026-03-27
Relationships: 
Description: add missing beautifulsoup dependency

--ISSUE
Content-Type: application/issue
ID: 24
Type: feature
Title: Water intake ingestion
Status: in-progress
Priority: medium
Created: 2026-03-28
Module: homostat
Relationships: 
Description: Add a water-intake canonical entity and a CLI command for manual
             water intake logging, similar to the existing measure command for
             body measurements. Wire up projections to query real water data
             instead of the current hardcoded zeros.

--ISSUE
Content-Type: application/issue
ID: 25
Type: bugfix
Title: Activity sessions duplicated when calories change between fetches
Status: done
Priority: medium
Created: 2026-03-28
Module: homostat
Relationships: 
Description: The DISTINCT-based deduplication from issue 21 fails when Fitbit
             recalculates activity calories between syncs, producing
             near-duplicate rows that differ only in calories. Replace SELECT
             DISTINCT with GROUP BY on the natural key (date, start_time, name)
             and HAVING fetched_at = MAX(fetched_at) to keep only the latest
             observation.

--ISSUE
Content-Type: application/issue
ID: 26
Type: bugfix
Title: Resting heart rate always zero — intraday endpoint lacks RHR
Status: done
Priority: medium
Created: 2026-03-29
Module: homostat
Relationships: 
Description: The Fitbit sync only calls heart_rate_intraday() which returns
             value as a string, not a dict with restingHeartRate. Add a call to
             the non-intraday heart_rate() summary endpoint to extract resting
             HR.

--ISSUE
Content-Type: application/issue
ID: 27
Type: feature
Title: Incremental hydration for projection builder
Status: done
Priority: medium
Created: 2026-03-29
Module: homostat
Relationships: 
Description: The projection hydrates all canonical JSONL partitions into an
             in-memory SQLite database on every run (currently 156k+ rows). As
             historical data accumulates, this full-rebuild becomes the
             bottleneck — the projection queries themselves are fast.
             Investigate incremental hydration strategies: persistent SQLite
             with date-based partition tracking, loading only the date(s) being
             projected, or a hybrid approach.

--ISSUE
Content-Type: application/issue
ID: 28
Type: bugfix
Title: Sleep and nutrition history duplicated from repeated syncs
Status: done
Priority: medium
Created: 2026-03-30
Module: homostat
Relationships: 
Description: Apply the same GROUP BY natural key / HAVING fetched_at =
             MAX(fetched_at) deduplication pattern from bugfix/25 to all
             remaining projection queries: sleep_session, sleep_stage,
             nutrition_day, meal, and meal_item — both status and history.

--ISSUE
Content-Type: application/issue
ID: 29
Type: bugfix
Title: Hydration dedup drops manual body tape measurements
Status: done
Priority: medium
Created: 2026-03-30
Module: homostat
Relationships: 
Description: Remove body-measurement from NATURAL_KEYS since it receives
             complementary data from two sources (manual tape measurements and
             Fitbit weight sync) that must coexist. The measurement query
             already handles multiple rows by picking the latest non-zero value
             per field.
