diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl new file mode 100644 index 0000000..0c5f080 --- /dev/null +++ b/.beads/issues.jsonl @@ -0,0 +1,9 @@ +{"_type":"issue","id":"hm-zy2.1","title":"Fix health-sync.js — wrong HealthUnit method names and Scriptable/Scripting app confusion","description":"The health-sync.js script doesn't work. Root causes identified:\n\n1. HealthUnit.gram(HealthMetricPrefix.kilo) is wrong — the API uses HealthUnit.gramUnit(HealthMetricPrefix.kilo) for prefixed units, or HealthUnit.gram() for base unit. There is no gram(prefix) overload.\n\n2. HealthUnit.millimeterOfMercury() is not exposed in the Scripting app HealthUnit API. Use HealthUnit.fromString('mmHg') instead.\n\n3. Scriptable vs Scripting app confusion. The script header says 'Scriptable' but the API (Health global, HealthUnit class, queryQuantitySamples) matches the Scripting app (scriptingapp.github.io). Scriptable uses a different pattern (new Health(), setTypeIdentifier, setUnit, quantitySamples). The script must target whichever app is actually installed.\n\n4. The script needs to be tested on-device after fixing.\n\nAcceptance: Script runs without errors in Scripting app, successfully POSTs health samples to /ingest, and server returns 201 with ingested count.","notes":"v11 working end-to-end. Script successfully reads HealthKit and POSTs to /ingest.\nConfirmed: blood_pressure (147/98 from Omron) and steps (24501 from Apple Health) ingested.\nKey fixes through iterations v1-v11:\n1. Scriptable API → Scripting app API (fetch, Notification.schedule, import from 'scripting')\n2. Top-level await → async main() + .then(Script.exit)\n3. HealthUnitPrefix not available → HealthUnit.fromString('kg')\n4. allowInsecureRequest: true for HTTP\n5. timeout on fetch to prevent hanging\n6. @ts-nocheck to suppress type checker errors\n7. Notification imported from 'scripting' (not global)\n\nScript deployed at http://chronos:9432/scriptable/health-sync.js (serves health-sync.tsx as inline text).\nUser has Scripting Pro (required for Health API access).\nAutomation not yet set up — user needs to create iOS Shortcut with scripting://run/Health%20Sync URL.\n\nScript name in Scripting app: 'Health Sync' (user should verify exact name).","status":"closed","priority":0,"issue_type":"bug","assignee":"Anthony Merlo","owner":"atradeus@pm.me","created_at":"2026-08-22T21:31:54Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T22:53:38Z","started_at":"2026-08-22T21:34:26Z","closed_at":"2026-08-22T21:35:47Z","close_reason":"Fixed 3 API bugs in health-sync.js. Server side verified working. Needs on-device test to fully confirm.","dependencies":[{"issue_id":"hm-zy2.1","depends_on_id":"hm-zy2","type":"parent-child","created_at":"2026-08-22T22:31:53Z","created_by":"Anthony Merlo","metadata":"{}"}],"dependency_count":0,"dependent_count":4,"comment_count":0} +{"_type":"issue","id":"hm-zy2","title":"Transform nutrition-mcp into health-mcp with Apple Health integration","description":"Expand nutrition-mcp into a broader health-mcp server. Fix the broken Apple Health sync script, expand metric coverage, add server-side health tools, and rename the project. The existing /ingest endpoint and vitals table are already generic enough to accept any health metric.","notes":"EPIC STATUS — Aug 22 2026:\n\nDONE:\n- hm-zy2.1 ✅ CLOSED — health-sync.tsx v11 working end-to-end. iPhone reads HealthKit (blood pressure, steps) and POSTs to /ingest on chronos:9432. Data confirmed in vitals table via recent_vitals MCP tool.\n\nNEXT UP (all unblocked):\n- hm-zy2.2 — backfill mode (query last 90 days, chunk into batches)\n- hm-zy2.3 — expand metrics (BMI, body fat, HRV, distance, energy, exercise time, etc.)\n- hm-zy2.4 — sleep tracking (needs Health.queryCategorySamples, not quantity)\n- hm-zy2.5 — new MCP tools (health_summary, vitals_trend, log_vital)\n\nNOT STARTED:\n- hm-zy2.6 — health_goals table + tools\n- hm-zy2.7 — workouts table + tools\n- hm-zy2.8 — rename project (do LAST, depends on .5 .6 .7)\n\nKEY CONTEXT FOR NEXT SESSION:\n- Scripting app (NOT Scriptable) — completely different API. Skill 'scripting-app-health-sync' saved with all pitfalls.\n- Script is at scripts/health-sync.tsx, served at /scriptable/health-sync.js on chronos\n- Server deployed on chronos via systemd (nutrition-mcp.service), built with cargo on chronos directly (cross-compile from macOS doesn't work — ring crate needs Linux toolchain)\n- Deploy flow: git push → ssh chronos → git pull → cargo build --release → systemctl --user restart nutrition-mcp\n- User has Scripting Pro (required for Health API)\n- Automation: user needs to set up iOS Shortcut with scripting://run/Health%20Sync URL (not done yet)\n- Working script version: v11","status":"open","priority":1,"issue_type":"feature","owner":"atradeus@pm.me","created_at":"2026-08-22T21:31:35Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T22:53:45Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"hm-zy2.5","title":"Add new MCP tools: health_summary, vitals_trend, log_vital","description":"Add new MCP tools to tools.rs:\n\n1. health_summary — daily/weekly health dashboard combining vitals + activity + sleep in one call. Returns latest values + daily sums.\n\n2. vitals_trend — time-series trend for a specific metric over N days. Returns min/max/avg + data points. Useful for 'weight over 30 days' or 'resting HR trend'.\n\n3. log_vital — manually log a vital (e.g. blood pressure from a non-connected cuff). Inserts into vitals table directly.\n\nFollow existing patterns in tools.rs (#[tool], schemars::JsonSchema for params, match existing error handling style).\n\nAcceptance: cargo build --release \u0026\u0026 cargo test pass. Tools appear in tools/list. Each tool returns correct data from vitals table.","status":"open","priority":2,"issue_type":"feature","owner":"atradeus@pm.me","created_at":"2026-08-22T21:31:58Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T21:31:58Z","dependencies":[{"issue_id":"hm-zy2.5","depends_on_id":"hm-zy2","type":"parent-child","created_at":"2026-08-22T22:31:57Z","created_by":"Anthony Merlo","metadata":"{}"},{"issue_id":"hm-zy2.5","depends_on_id":"hm-zy2.1","type":"blocks","created_at":"2026-08-22T22:32:09Z","created_by":"Anthony Merlo","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0} +{"_type":"issue","id":"hm-zy2.4","title":"Add sleep tracking support (category type) to health-sync script","description":"Sleep data is a HealthKit category type, not a quantity type. Health.queryQuantitySamples() won't work. Need to use Health.queryCategorySamples() for sleepAnalysis.\n\nGroup samples by sleep stage (asleepCore, asleepDeep, asleepREM, asleepUnspecified, awake, inBed) and sum durations per stage.\nStore one vitals row per night: type='sleep', value={inBed: secs, asleepCore: secs, asleepDeep: secs, ...}.\n\nNeed to verify Scripting app supports queryCategorySamples() — check docs at scriptingapp.github.io.\n\nAcceptance: Sleep data is read, grouped by stage, and POSTed as a single JSON object per night.","status":"open","priority":2,"issue_type":"feature","owner":"atradeus@pm.me","created_at":"2026-08-22T21:31:57Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T21:31:57Z","dependencies":[{"issue_id":"hm-zy2.4","depends_on_id":"hm-zy2","type":"parent-child","created_at":"2026-08-22T22:31:56Z","created_by":"Anthony Merlo","metadata":"{}"},{"issue_id":"hm-zy2.4","depends_on_id":"hm-zy2.1","type":"blocks","created_at":"2026-08-22T22:32:08Z","created_by":"Anthony Merlo","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"hm-zy2.3","title":"Expand health-sync script to cover more HealthKit metrics","description":"Add the following HealthKit types to health-sync.js:\n\nBody: bodyMassIndex (latest), bodyFatPercentage (latest)\nCardiovascular: heartRateVariabilitySDNN (latest), walkingHeartRateAverage (latest)\nActivity: distanceWalkingRunning (daily sum), distanceCycling (daily sum), flightsClimbed (daily sum), activeEnergyBurned (daily sum), appleExerciseTime (daily sum), appleStandTime (daily sum)\n\nNo server changes needed — vitals table accepts any type string and value as JSON. Just add readLatest()/readTodaySum() calls and push to samples array.\n\nAcceptance: All listed metrics are read and POSTed. Missing metrics (no data) are silently skipped, not errored.","status":"open","priority":2,"issue_type":"feature","owner":"atradeus@pm.me","created_at":"2026-08-22T21:31:56Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T21:31:56Z","dependencies":[{"issue_id":"hm-zy2.3","depends_on_id":"hm-zy2.1","type":"blocks","created_at":"2026-08-22T22:32:07Z","created_by":"Anthony Merlo","metadata":"{}"},{"issue_id":"hm-zy2.3","depends_on_id":"hm-zy2","type":"parent-child","created_at":"2026-08-22T22:31:55Z","created_by":"Anthony Merlo","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"hm-zy2.2","title":"Add historical backfill mode to health-sync script","description":"Current script only grabs the latest sample per metric. Add a backfill mode that queries all samples from a date range (e.g. last 90 days), chunks them into batches of ~500, and POSTs each batch to /ingest.\n\nFor daily-sum types (steps, energy, distance), iterate day-by-day, summing each day's samples into one row with timestamp_utc=YYYY-MM-DD.\n\nIdempotency is handled by UNIQUE(type, timestamp_utc) + ON CONFLICT DO UPDATE — re-running backfill is safe.\n\nAcceptance: Running backfill for last 30 days populates vitals table with historical data. Re-running produces same row count (upserts).","status":"open","priority":2,"issue_type":"feature","owner":"atradeus@pm.me","created_at":"2026-08-22T21:31:55Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T21:31:55Z","dependencies":[{"issue_id":"hm-zy2.2","depends_on_id":"hm-zy2","type":"parent-child","created_at":"2026-08-22T22:31:54Z","created_by":"Anthony Merlo","metadata":"{}"},{"issue_id":"hm-zy2.2","depends_on_id":"hm-zy2.1","type":"blocks","created_at":"2026-08-22T22:32:07Z","created_by":"Anthony Merlo","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"hm-zy2.7","title":"Add workouts table and workout-related MCP tools","description":"Add a structured workouts table:\nCREATE TABLE workouts (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp_utc TEXT NOT NULL, workout_type TEXT NOT NULL, duration_sec INTEGER, total_energy_kcal REAL, total_distance_m REAL, source TEXT, metadata TEXT, UNIQUE(timestamp_utc, workout_type, source));\n\nAdd MCP tools: log_workout (manual entry), workout_history (query by type/date range).\n\nAlso add workout ingestion to /ingest — if sample type is 'workout', insert into workouts table instead of vitals.\n\nAcceptance: cargo build --release \u0026\u0026 cargo test pass. Workouts are queryable via MCP tools. /ingest routes workout samples correctly.","status":"open","priority":3,"issue_type":"feature","owner":"atradeus@pm.me","created_at":"2026-08-22T21:32:00Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T21:32:00Z","dependencies":[{"issue_id":"hm-zy2.7","depends_on_id":"hm-zy2","type":"parent-child","created_at":"2026-08-22T22:32:00Z","created_by":"Anthony Merlo","metadata":"{}"}],"dependency_count":0,"dependent_count":1,"comment_count":0} +{"_type":"issue","id":"hm-zy2.6","title":"Add health_goals table and get/set health goals MCP tools","description":"Add a health_goals table (like daily_goal but for health metrics):\nCREATE TABLE health_goals (id INTEGER PRIMARY KEY, goals TEXT NOT NULL DEFAULT '{}');\n\nGoals JSON: {steps: 10000, sleep_hours: 8, weight_kg: 80, resting_hr: 60, blood_pressure_systolic: 120, ...}\n\nAdd two MCP tools: get_health_goals, set_health_goals — following the same pattern as get_goals/set_goals.\n\nAcceptance: cargo build --release \u0026\u0026 cargo test pass. Goals persist in SQLite. Tools round-trip correctly.","status":"open","priority":3,"issue_type":"feature","owner":"atradeus@pm.me","created_at":"2026-08-22T21:31:59Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T21:31:59Z","dependencies":[{"issue_id":"hm-zy2.6","depends_on_id":"hm-zy2","type":"parent-child","created_at":"2026-08-22T22:31:58Z","created_by":"Anthony Merlo","metadata":"{}"}],"dependency_count":0,"dependent_count":1,"comment_count":0} +{"_type":"issue","id":"hm-zy2.8","title":"Rename project: nutrition-mcp → health-mcp","description":"Rename the project:\n- Cargo.toml: name, binary name, description\n- Env var prefixes: NUTRITION_MCP_* → HEALTH_MCP_* (with backwards compat alias)\n- Update AGENTS.md, CLAUDE.md module map and references\n- Update config.rs struct/docs\n- Update scripts/health-sync.js server URL comments\n- Update Hermes config.yaml mcp_servers:nutrition → mcp_servers:health\n\nDo this LAST, after all other issues are complete, to minimize disruption during development.\n\nAcceptance: cargo build --release \u0026\u0026 cargo test pass with new names. Old env vars still work via backwards-compat. Hermes MCP config updated.","status":"open","priority":4,"issue_type":"task","owner":"atradeus@pm.me","created_at":"2026-08-22T21:32:01Z","created_by":"Anthony Merlo","updated_at":"2026-08-22T21:32:01Z","dependencies":[{"issue_id":"hm-zy2.8","depends_on_id":"hm-zy2.5","type":"blocks","created_at":"2026-08-22T22:32:09Z","created_by":"Anthony Merlo","metadata":"{}"},{"issue_id":"hm-zy2.8","depends_on_id":"hm-zy2.7","type":"blocks","created_at":"2026-08-22T22:32:10Z","created_by":"Anthony Merlo","metadata":"{}"},{"issue_id":"hm-zy2.8","depends_on_id":"hm-zy2","type":"parent-child","created_at":"2026-08-22T22:32:01Z","created_by":"Anthony Merlo","metadata":"{}"},{"issue_id":"hm-zy2.8","depends_on_id":"hm-zy2.6","type":"blocks","created_at":"2026-08-22T22:32:10Z","created_by":"Anthony Merlo","metadata":"{}"}],"dependency_count":3,"dependent_count":0,"comment_count":0} diff --git a/AGENTS.md b/AGENTS.md index ec2a542..602ddd0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -189,3 +189,94 @@ bd prime # Refresh Beads context **Architecture in one line:** issues live in a local Dolt DB; sync uses `refs/dolt/data` on your git remote; `.beads/issues.jsonl` is a passive export. See https://github.com/gastownhall/beads/blob/main/docs/SYNC_CONCEPTS.md for details and anti-patterns. + + + +--- + +## Beads Workflow Integration + +This project uses [beads_rust](https://github.com/Dicklesworthstone/beads_rust) (`br`) for issue tracking and [beads_viewer](https://github.com/Dicklesworthstone/beads_viewer) (`bv`) for graph-aware triage. Issues are stored in `.beads/` and tracked in git. Current `br` workspaces normally export `.beads/issues.jsonl`; older `bd`/legacy workspaces may use `.beads/beads.jsonl`. `bv` auto-discovers the supported JSONL files, so agents should use `br`/`bv` commands instead of hard-coding a single filename. + +### Using bv as an AI sidecar + +bv is a graph-aware triage engine for Beads projects. Instead of parsing .beads/issues.jsonl / .beads/beads.jsonl directly or hallucinating graph traversal, use robot flags for deterministic, dependency-aware outputs with precomputed metrics (PageRank, betweenness, critical path, cycles, HITS, eigenvector, k-core). + +**Scope boundary:** bv handles *what to work on* (triage, priority, planning). `br` handles creating, modifying, and closing beads. + +**CRITICAL: Use ONLY --robot-* flags. Bare bv launches an interactive TUI that blocks your session.** + +#### The Workflow: Start With Triage + +**`bv --robot-triage` is your single entry point.** It returns everything you need in one call: +- `quick_ref`: at-a-glance counts + top 3 picks +- `recommendations`: ranked actionable items with scores, reasons, unblock info +- `quick_wins`: low-effort high-impact items +- `blockers_to_clear`: items that unblock the most downstream work +- `project_health`: status/type/priority distributions, graph metrics +- `commands`: copy-paste shell commands for next steps + +```bash +bv --robot-triage # THE MEGA-COMMAND: start here +bv --robot-next # Minimal: just the single top pick + claim command + +# Token-optimized output (TOON) for lower LLM context usage: +bv --robot-triage --format toon +``` + +Before claiming, verify current state with `br show --json` or `br ready --json`. `recommendations` can include graph-important blocked or assigned work; only `quick_ref.top_picks` and non-empty `claim_command` fields represent claimable work. + +#### Other bv Commands + +| Command | Returns | +|---------|---------| +| `--robot-plan` | Parallel execution tracks with unblocks lists | +| `--robot-priority` | Priority misalignment detection with confidence | +| `--robot-insights` | Full metrics: PageRank, betweenness, HITS, eigenvector, critical path, cycles, k-core | +| `--robot-alerts` | Stale issues, blocking cascades, priority mismatches | +| `--robot-suggest` | Hygiene: duplicates, missing deps, label suggestions, cycle breaks | +| `--robot-diff --diff-since ` | Changes since ref: new/closed/modified issues | +| `--robot-graph [--graph-format=json\|dot\|mermaid]` | Dependency graph export | + +#### Scoping & Filtering + +```bash +bv --robot-plan --label backend # Scope to label's subgraph +bv --robot-insights --as-of HEAD~30 # Historical point-in-time +bv --recipe actionable --robot-plan # Pre-filter: ready to work (no blockers) +bv --recipe high-impact --robot-triage # Pre-filter: top PageRank scores +``` + +### br Commands for Issue Management + +```bash +br ready --json # Show issues ready to work (no blockers) +br list --status=open --json # All open issues +br show --json # Full issue details with dependencies +br create --title="..." --type=task --priority=2 --json +br update --status=in_progress --json +br close --reason="Completed" --json +br close --reason="Completed" --json +br sync --flush-only # Export DB to JSONL after Beads mutations +``` + +### Workflow Pattern + +1. **Triage**: Run `bv --robot-triage` to find the highest-impact actionable work +2. **Claim**: Use `br update --status=in_progress --json` +3. **Work**: Implement the task +4. **Complete**: Use `br close --reason="Completed" --json` +5. **Sync**: Run `br sync --flush-only` after Beads mutations so the JSONL export is current + +### Key Concepts + +- **Dependencies**: Issues can block other issues. `br ready --json` shows only unblocked work. +- **Priority**: P0=critical, P1=high, P2=medium, P3=low, P4=backlog (use numbers 0-4, not words) +- **Types**: task, bug, feature, epic, chore, docs, question +- **Blocking**: `br dep add ` to add dependencies + +### Git Policy + +`br` never commits or pushes. Follow this repository's own git instructions before staging, committing, or pushing. If the repository says "commit only when asked," that rule overrides any generic workflow advice. + +