Compare commits

...

2 commits

Author SHA1 Message Date
067bf7a769 fix: health-sync.js HealthUnit method names + serve as inline text
- HealthUnit.gram(prefix) → HealthUnit.gramUnit(prefix) (Scripting app API)
- HealthUnit.millimeterOfMercury() → HealthUnit.fromString('mmHg')
- Updated header: Scriptable → Scripting app
- content-disposition: inline instead of attachment (fixes download issue)
2026-08-22 22:43:16 +01:00
3319a6b233 bd init: initialize beads issue tracking 2026-08-22 22:31:27 +01:00
7 changed files with 176 additions and 23 deletions

View file

@ -64,3 +64,5 @@
# Secret keys (stored in this file but prefer env vars to avoid git exposure): # Secret keys (stored in this file but prefer env vars to avoid git exposure):
# - linear.api_key → use LINEAR_API_KEY env var instead # - linear.api_key → use LINEAR_API_KEY env var instead
# - github.token → use GITHUB_TOKEN env var instead # - github.token → use GITHUB_TOKEN env var instead
sync.remote: "git+https://git.darkmark.co.uk/amerlo/nutrition-mcp.git"

View file

@ -13,3 +13,4 @@
{"id":"int-b0e97dffd303b9e4f164830ebcbe2085","kind":"field_change","created_at":"2026-08-20T15:56:04.581867751Z","actor":"Anthony Merlo","issue_id":"nutrition-mcp-aea","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Hermes skill created at ~/.hermes/skills/productivity/nutrition-tracker/SKILL.md with workflow guidance, meal auto-detection, portion handling, protein estimation guide, and gout/hypertension health context."}} {"id":"int-b0e97dffd303b9e4f164830ebcbe2085","kind":"field_change","created_at":"2026-08-20T15:56:04.581867751Z","actor":"Anthony Merlo","issue_id":"nutrition-mcp-aea","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Hermes skill created at ~/.hermes/skills/productivity/nutrition-tracker/SKILL.md with workflow guidance, meal auto-detection, portion handling, protein estimation guide, and gout/hypertension health context."}}
{"id":"int-c69e98d9ab404dbe46f1b088e3453677","kind":"field_change","created_at":"2026-08-20T16:25:47.847889101Z","actor":"Anthony Merlo","issue_id":"nutrition-mcp-45t","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"25 integration tests added, all passing. Covers: DB init, goals seeding, FTS5 cache search, upsert, portion scaling, sum_nutriments (with no-data handling), meal detection, date format, log entry round trips, goals update, weight log + upsert. Also fixed sum_nutriments display key bug (was using OFF field names instead of display names) and weight_log UNIQUE constraint."}} {"id":"int-c69e98d9ab404dbe46f1b088e3453677","kind":"field_change","created_at":"2026-08-20T16:25:47.847889101Z","actor":"Anthony Merlo","issue_id":"nutrition-mcp-45t","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"25 integration tests added, all passing. Covers: DB init, goals seeding, FTS5 cache search, upsert, portion scaling, sum_nutriments (with no-data handling), meal detection, date format, log entry round trips, goals update, weight log + upsert. Also fixed sum_nutriments display key bug (was using OFF field names instead of display names) and weight_log UNIQUE constraint."}}
{"id":"int-80ae42f606a6a22aef6d8883d3462f72","kind":"field_change","created_at":"2026-08-20T21:57:03.081085913Z","actor":"Anthony Merlo","issue_id":"nutrition-mcp-aav","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"POST /ingest endpoint implemented in src/ingest.rs. Accepts array of health samples (weight, BP, HR, steps, sleep, SpO2). Auth via Bearer token. Tested: 4 samples ingested (weight, BP, steps, HR), 401 on missing auth. 31 tests passing. Server restarted and live. Dependency on 3nl was for vitals tables — ingest uses a generic vitals table with JSON value column, no need to wait for individual table tooling."}} {"id":"int-80ae42f606a6a22aef6d8883d3462f72","kind":"field_change","created_at":"2026-08-20T21:57:03.081085913Z","actor":"Anthony Merlo","issue_id":"nutrition-mcp-aav","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"POST /ingest endpoint implemented in src/ingest.rs. Accepts array of health samples (weight, BP, HR, steps, sleep, SpO2). Auth via Bearer token. Tested: 4 samples ingested (weight, BP, steps, HR), 401 on missing auth. 31 tests passing. Server restarted and live. Dependency on 3nl was for vitals tables — ingest uses a generic vitals table with JSON value column, no need to wait for individual table tooling."}}
{"id":"int-d36257ef0a5cb2afb18ece95e6b92bc7","kind":"field_change","created_at":"2026-08-22T21:35:47.560297Z","actor":"Anthony Merlo","issue_id":"hm-zy2.1","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Fixed 3 API bugs in health-sync.js. Server side verified working. Needs on-device test to fully confirm."}}

5
.gitignore vendored
View file

@ -6,3 +6,8 @@
.env .env
# IDE # IDE
.idea/ .idea/
# Beads / Dolt files (added by bd init)
.dolt/
.beads-credential-key
.beads/proxieddb/

View file

@ -108,4 +108,84 @@ rm -f file # NOT: rm file
2. **Run quality gates** - `cargo build --release && cargo test` 2. **Run quality gates** - `cargo build --release && cargo test`
3. **Close completed issues** - `bd close <id1> <id2> ...` 3. **Close completed issues** - `bd close <id1> <id2> ...`
4. **PUSH** - `git add -A && git commit -m "..." && git push` 4. **PUSH** - `git add -A && git commit -m "..." && git push`
5. **Verify** - `git status` must show clean working tree 5. **Verify** - `git status` must show clean working tree
<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:970c3bf2 -->
## Beads Issue Tracker
This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands.
### Quick Reference
```bash
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --claim # Claim work
bd close <id> # Complete work
```
### Rules
- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
- Run `bd prime` for detailed command reference and session close protocol
- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files
**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.
## Agent Context Profiles
The managed Beads block is task-tracking guidance, not permission to override repository, user, or orchestrator instructions.
- **Conservative (default)**: Use `bd` for task tracking. Do not run git commits, git pushes, or Dolt remote sync unless explicitly asked. At handoff, report changed files, validation, and suggested next commands.
- **Minimal**: Keep tool instruction files as pointers to `bd prime`; use the same conservative git policy unless active instructions say otherwise.
- **Team-maintainer**: Only when the repository explicitly opts in, agents may close beads, run quality gates, commit, and push as part of session close. A current "do not commit" or "do not push" instruction still wins.
## Session Completion
This protocol applies when ending a Beads implementation workflow. It is subordinate to explicit user, repository, and orchestrator instructions.
1. **File issues for remaining work** - Create beads for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **Handle git/sync by active profile**:
```bash
# Conservative/minimal/default: report status and proposed commands; wait for approval.
git status
# Team-maintainer opt-in only, unless current instructions forbid it:
git pull --rebase
bd dolt push
git push
git status
```
5. **Hand off** - Summarize changes, validation, issue status, and any blocked sync/commit/push step
**Critical rules:**
- Explicit user or orchestrator instructions override this Beads block.
- Do not commit or push without clear authority from the active profile or the current user request.
- If a required sync or push is blocked, stop and report the exact command and error.
<!-- END BEADS INTEGRATION -->
<!-- BEGIN BEADS CODEX SETUP: generated by bd setup codex -->
## Beads Issue Tracker
Use Beads (`bd`) for durable task tracking in repositories that include it. Use the `beads` skill at `.agents/skills/beads/SKILL.md` (project install) or `~/.agents/skills/beads/SKILL.md` (global install) for Beads workflow guidance, then use the `bd` CLI for issue operations.
### Quick Reference
```bash
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --claim # Claim work
bd close <id> # Complete work
bd prime # Refresh Beads context
```
### Rules
- Use `bd` for all task tracking; do not create markdown TODO lists.
- Run `bd prime` when Beads context is missing or stale. Codex 0.129.0+ can load Beads context automatically through native hooks; use `/hooks` to inspect or toggle them.
- Keep persistent project memory in Beads via `bd remember`; do not create ad hoc memory files.
**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.
<!-- END BEADS CODEX SETUP -->

View file

@ -108,4 +108,59 @@ rm -f file # NOT: rm file
2. **Run quality gates** - `cargo build --release && cargo test` 2. **Run quality gates** - `cargo build --release && cargo test`
3. **Close completed issues** - `bd close <id1> <id2> ...` 3. **Close completed issues** - `bd close <id1> <id2> ...`
4. **PUSH** - `git add -A && git commit -m "..." && git push` 4. **PUSH** - `git add -A && git commit -m "..." && git push`
5. **Verify** - `git status` must show clean working tree 5. **Verify** - `git status` must show clean working tree
<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:6cd5cc61 -->
## Beads Issue Tracker
This project uses **bd (beads)** for issue tracking. Run `bd prime` to see full workflow context and commands.
### Quick Reference
```bash
bd ready # Find available work
bd show <id> # View issue details
bd update <id> --claim # Claim work
bd close <id> # Complete work
```
### Rules
- Use `bd` for ALL task tracking — do NOT use TodoWrite, TaskCreate, or markdown TODO lists
- Run `bd prime` for detailed command reference and session close protocol
- Use `bd remember` for persistent knowledge — do NOT use MEMORY.md files
**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.
## Agent Context Profiles
The managed Beads block is task-tracking guidance, not permission to override repository, user, or orchestrator instructions.
- **Conservative (default)**: Use `bd` for task tracking. Do not run git commits, git pushes, or Dolt remote sync unless explicitly asked. At handoff, report changed files, validation, and suggested next commands.
- **Minimal**: Keep tool instruction files as pointers to `bd prime`; use the same conservative git policy unless active instructions say otherwise.
- **Team-maintainer**: Only when the repository explicitly opts in, agents may close beads, run quality gates, commit, and push as part of session close. A current "do not commit" or "do not push" instruction still wins.
## Session Completion
This protocol applies when ending a Beads implementation workflow. It is subordinate to explicit user, repository, and orchestrator instructions.
1. **File issues for remaining work** - Create beads for anything that needs follow-up
2. **Run quality gates** (if code changed) - Tests, linters, builds
3. **Update issue status** - Close finished work, update in-progress items
4. **Handle git/sync by active profile**:
```bash
# Conservative/minimal/default: report status and proposed commands; wait for approval.
git status
# Team-maintainer opt-in only, unless current instructions forbid it:
git pull --rebase
git push
git status
```
5. **Hand off** - Summarize changes, validation, issue status, and any blocked sync/commit/push step
**Critical rules:**
- Explicit user or orchestrator instructions override this Beads block.
- Do not commit or push without clear authority from the active profile or the current user request.
- If a required sync or push is blocked, stop and report the exact command and error.
<!-- END BEADS INTEGRATION -->

View file

@ -1,16 +1,25 @@
// Health Sync — reads Apple Health and POSTs to nutrition-mcp server // Health Sync — reads Apple Health via Scripting app and POSTs to health-mcp server
// Run via Scripting app automation at 9:30am daily // Run via Scripting app automation at 9:30am daily
// Server: http://chronos:9432/ingest // Server: http://chronos:9432/ingest
// //
// Uses Scripting app's Health API: Health.queryQuantitySamples() with HealthUnit. // Uses Scripting app's Health API:
// Health.queryQuantitySamples(type, options) — returns samples
// sample.quantityValue(unit) — extracts numeric value
// HealthUnit / HealthMetricPrefix — unit construction
//
// Docs: https://scriptingapp.github.io/guide/Device%20Capabilities/Health/
// Variables used by Scripting app. These must be at the very top of the file.
// icon-color: deep-blue; icon-glyph: heart;
const SERVER_URL = "http://chronos:9432/ingest"; const SERVER_URL = "http://chronos:9432/ingest";
const API_KEY = "333f09ce904e9cbbe3b578fda393be92869122c7222dbccd"; const API_KEY = "333f09ce904e9cbbe3b578fda393be92869122c7222dbccd";
// --- Units for each quantity type --- // --- Units for each quantity type ---
// HealthUnit API: https://scriptingapp.github.io/guide/Device%20Capabilities/Health/HealthUnit
const U = { const U = {
kg: HealthUnit.gram(HealthMetricPrefix.kilo), kg: HealthUnit.gramUnit(HealthMetricPrefix.kilo),
mmHg: HealthUnit.millimeterOfMercury(), mmHg: HealthUnit.fromString("mmHg"),
bpm: HealthUnit.count().divided(HealthUnit.minute()), bpm: HealthUnit.count().divided(HealthUnit.minute()),
count: HealthUnit.count(), count: HealthUnit.count(),
percent: HealthUnit.percent() percent: HealthUnit.percent()
@ -153,22 +162,22 @@ if (samples.length === 0) {
await notify("No health data found today"); await notify("No health data found today");
} else { } else {
const req = new Request(SERVER_URL); const req = new Request(SERVER_URL);
req.method = "POST"; req.method = "POST";
req.headers = { req.headers = {
"Authorization": `Bearer ${API_KEY}`, "Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json" "Content-Type": "application/json"
}; };
req.body = JSON.stringify({ samples: samples }); req.body = JSON.stringify({ samples: samples });
try { try {
const res = await req.loadJSON(); const res = await req.loadJSON();
console.log(`Server response: ${JSON.stringify(res)}`); console.log(`Server response: ${JSON.stringify(res)}`);
await notify(`Sent ${res.ingested || samples.length} samples`); await notify(`Sent ${res.ingested || samples.length} samples`);
} catch (e) { } catch (e) {
console.log(`POST error: ${e}`); console.log(`POST error: ${e}`);
await notify(`Error: ${e.message || e}`); await notify(`Error: ${e.message || e}`);
} }
} // end else } // end else
console.log("=== Health Sync done ==="); console.log("=== Health Sync done ===");

View file

@ -108,14 +108,15 @@ async fn health_check() -> &'static str {
"OK" "OK"
} }
/// Serve the Scriptable health-sync.js file for easy phone download. /// Serve the health-sync.js script for easy phone access.
/// No auth — it's just a script, no sensitive data. /// No auth — it's just a script, no sensitive data.
/// Served as inline text so Safari displays it for copy-paste into Scripting app.
async fn serve_scriptable_script() -> impl axum::response::IntoResponse { async fn serve_scriptable_script() -> impl axum::response::IntoResponse {
let script = include_str!("../scripts/health-sync.js"); let script = include_str!("../scripts/health-sync.js");
( (
[ [
("content-type", "text/javascript; charset=utf-8"), ("content-type", "text/javascript; charset=utf-8"),
("content-disposition", "attachment; filename=\"health-sync.js\""), ("content-disposition", "inline"),
], ],
script, script,
) )