harness-health-engineering

harness-health-engineering

Enables querying a local health knowledge base with hybrid RAG (vector + FTS5) and exploring backlinks between notes.

Category
访问服务器

README

<div align="center">

🧬 Harness Health Engineering

A local AI lab that helps you discover what actually improves your life.

Physiology streams in from Whoop · lived experience goes in by text · voice · selfie · an on-device agent runs n-of-1 experiments and tells you what actually makes life better — all as plain Markdown you own.

<br/>

local-first method north star RAG Whoop License

</div>


🧭 Explore

The one idea 🔬 The engine 🆚 vs Whoop journal
🔄 How it works 📥 Three ways in 🤳 Photo diaries
🧱 Architecture 🛠️ Technology 🚀 Deploy your own

The one idea

Every health gadget you've owned optimised a number. Recovery. HRV. Steps. And somewhere along the way the number became the point, and your actual life — whether you felt good, did meaningful work, saw people you love — fell out of frame. That's Goodhart's law wearing a fitness band: when a measure becomes the target, it stops measuring anything that matters.

This project flips it. The top-level metric here is not a body score. It is one honest question:

⭐ North-star: "Is my life actually better?"

Everything else — recovery, sleep, HRV, supplements, training load — is demoted to what it really is: an instrument in service of that question. The system will happily tell you that your body looks great this week and your life doesn't, and then help you fix the right thing. No wearable can say that, because no wearable knows what your good life looks like.

Built for people who have tried enough supplements, trackers, routines, and protocols to know that the hard question is not “what is optimal?” but “what is optimal for me, in the life I actually live?”. Not for people who want motivation, streaks, badges, or a prettier sleep chart.

The engine: n-of-1 experiments 🔬

Correlations are guesses. "You sleep worse when you drink" can't tell you if the drink did it or if a hard day caused both. So instead of guessing, the harness runs n-of-1 trials — single-subject experiments, the real methodology personalised medicine uses to decide if something works for one specific person. Every experiment is pre-registered:

Step Rule
Hypothesis a specific causal claim
One variable change exactly one thing — the rule everyone breaks
Baseline a measured "before"
Duration + criterion written before the data, so you can't fool yourself
Verdict merge → it becomes a standing rule, or revert → drop it and log why

This is the difference between "I tried a thing once" and knowledge that compounds. The payoff is a sentence no tracker will ever give you:

"Creatine moved nothing for you in three weeks — stop paying for it." "Caffeine before 14:00 bought you +35 min of deep sleep — it's a rule now."

One variable at a time. A clock. A criterion. A verdict that becomes a rule. That's the whole game, and it's why this gets smarter every week instead of just logging more.

stateDiagram-v2
    direction LR
    [*] --> proposed: /exp new · or agent proposes
    proposed --> active: baseline + criterion set
    active --> active: /exp extend
    active --> merged: criterion met → becomes a rule
    active --> reverted: missed / stopped → logged why
    merged --> [*]
    reverted --> [*]

You drive it from anywhere: /exp new to start, /exp extend to give it more time, /exp stop to call it — or just ask the agent to design a tighter one. Either way it ends in a verdict, not a vibe.

Why it's different from Whoop's journal

Whoop's journaling is genuinely good — and it has a ceiling. Here's where this goes that it structurally can't:

Wearable journal Harness Health Engineering
Top metric a body score your life quality
Evidence correlation n-of-1 causation → rules
Scope body only body × work × people × supplements × bloodwork
Output dashboards decisions and experiments
Reasoning a black box on-device, cited, interrogable in plain language
Memory a feed a versioned record you can ask "why was March hard?"
Guardrail flags metric-tyranny: proxy up, life flat → that's a fail

The discipline is the product. The data is just raw material. The full scientific rationale — n-of-1 design, surrogate-endpoint failure, evidence labelling, confounding — is in METHODOLOGY.md.

How it works

flowchart TD
    W["Whoop API v2"] -->|"OAuth2 · auto 9:00 · serialized refresh"| SYNC["sync.mjs"]
    H(["You · text · voice · selfie"]) -->|"events · mood · energy · social · work · body"| BOT["Telegram bot<br/>capture layer · on-device"]
    SYNC -->|"recovery · HRV · sleep · strain"| RAW["01_raw · daily record"]
    BOT --> RAW
    RAW --> SRC["02_sources · weekly notes<br/>FACT / INFERENCE"]
    SRC --> SYN["04_synthesis · patterns + life-quality"]
    SYN --> EXP["05_decisions · n-of-1 experiments<br/>one variable · criterion · verdict"]
    EXP --> RULE["CLAUDE.md · rules that stuck"]
    EXP -.->|"merge / revert"| RAW
    NS["⭐ north-star:<br/>is life better?"] --- SYN

    AGENT["on-device agent<br/>RAG · cited synthesis · MCP"] --- RAW
    AGENT --- SYN
    AGENT --- EXP

The loop: Signal → Ingest → Source note → Synthesis → Experiment → Verdict → Rule → repeat. Objective body data arrives on its own; you add a 40-second diary; on Sundays the agent scores your week against the north-star and finds what's actually moving it.

What it tracks

Daily (auto): recovery, HRV, resting HR, sleep, strain — from Whoop. Daily (you, ~40s — by text, voice, or selfie): events (your impressions journal), mood, energy, social, work, movement, supplements. Weekly: one integral "is life better?" 1–5. Quarterly: six life dimensions — emotion, connection, body, meaning, autonomy, growth.

Three ways in 📥

Lived experience is messy, and you shouldn't have to sit at a keyboard to capture it. The bot takes three modalities — mix them freely, several per day:

Mode How Processing Privacy
✍️ Text type a line appended to today's record local
🎙️ Voice send a voice note transcribed on-device (Whisper ONNX) → text audio never leaves the machine
🤳 Selfie send a photo archived to a local visual diary, reviewed on demand by the agent biometric — never committed to git

A photo is auto-classified on-device (CLIP, zero-shot — the image never leaves the machine) into one of three local diaries, each read against its own canon — all descriptive, never diagnostic. No caption needed; a caption simply overrides the guess:

Type (auto) Diary Canon the agent uses
selfie (default) face skin / fluid / affect signals over time
food meals plate composition · protein · fibre · processing · timing
stool gut Bristol Stool Scale — type, colour, frequency

Every message lands as a timestamped line - 14:30 … in 01_raw/health/YYYY-MM-DD.md, so the shape of the day is preserved — not flattened into one average. Commands set the rest: /north for your north-star, /exp to run an n-of-1, /week · /month · /year for horizons.

Three photo diaries, one on-device eye 🤳

Your face, your plate, and your gut all leave visible traces of how you live — and a wearable sees none of them. The harness turns photos into longitudinal signals, while staying strictly on the safe side of the line: it describes and compares over time, it never diagnoses.

The on-device eye: how routing works 👁️

Send any photo — no caption, no menu. The bot identifies what it is with CLIP zero-shot image classification running locally (ONNX, the same on-device stack as the voice transcriber). The image never leaves the machine; nothing is uploaded.

flowchart TD
    P["📷 photo<br/>(Telegram)"] --> DL["bot: download"]
    DL --> CLIP{"on-device CLIP<br/>zero-shot · ONNX"}
    CLIP -->|face| S1["photos/ · face"]
    CLIP -->|meal| S2["photos/food/ · food"]
    CLIP -->|toilet| S3["photos/stool/ · gut"]
    S1 --> STORE["local · gitignored<br/>only a filename ref in the daily log"]
    S2 --> STORE
    S3 --> STORE
    STORE -.->|"on request: 'review my …'"| AGENT["agent vision<br/>(strong model)"]
    AGENT --> OBS["dated observations · local"]
    OBS --> HYP["hypothesis"] --> EXP["n-of-1 experiment"]
  • Selfie is the safe default — the classifier must clear a confidence margin to file a photo as food or stool; otherwise it stays in the neutral face diary.
  • A caption always wins — write "food" / "stool" / "selfie" to override the guess.
  • Storage is the only automatic step. Content is never auto-analysed — the deep read happens only when you ask the agent ("review my selfies / food / stool"), keeping a strong model's quality without sending anything anywhere by default. (Warm classification ≈ 150 ms.)

1 · Face — the visual diary

What the agent reads from a face — over time, not in one shot:

Group Signals May reflect Cross-checked against
💧 Fluid / puffiness under-eye bags, facial fullness, lid heaviness water retention, fatigue sleep, salt/alcohol at night, cycle phase, stress
🎨 Skin tone redness/flush, sallowness, pallor, blotchiness vascular reaction, tiredness alcohol, heat/exertion, recovery, hydration
🧴 Texture / breakouts spot count & location, shine vs dryness hormonal pattern, hydration cycle phase, sugar/dairy (hypothesis), stress, sleep
👁️ Eyes sclera redness, dark circles, clarity of gaze tiredness, irritation sleep, alcohol, screens, allergy
🌳 Affect / vitality jaw/brow tension, downturned vs lit-up mood, energy mood/energy 1–5, "lived as wanted?"

2 · Food — read against the plate canon

Method: the plate canon — ~½ vegetables · ~¼ protein · ~¼ complex carbs · + healthy fat.

Signal May reflect Cross-checked against
protein present? satiety, stable glucose energy, afternoon sugar cravings
fibre / veg share gut transit, fullness stool, energy
processing level (whole vs ultra-processed) inflammation (hypothesis) mood, energy
refined sugar / fast carbs glucose swings energy, sleep, skin
meal timing (late eating) overnight recovery sleep, next-day recovery

No calorie counting — unreliable from a photo; the agent reads composition and timing, not numbers. Described neutrally, never moralised — an eating-disorder guardrail keeps the focus on food → how you feel, not control or guilt.

3 · Gut — the Bristol Stool Scale

Method: the clinical Bristol Stool Scale (type 1–7, with 3–4 as the healthy middle) plus colour.

Read May reflect Cross-checked against
type 1–2 (hard lumps) slow transit, constipation-leaning water, fibre, magnesium, travel
type 3–4 normal
type 6–7 (loose / watery) fast transit trigger foods, stress, FODMAPs, caffeine
colour (pale-clay · black-tarry · red) bile flow · possible bleed red-flag → doctor

Black/tarry stool or visible blood → see a doctor, not a diary entry — no interpretation attempted.

Hard limits, across all three diaries

  • Not a diagnosis — any worrying sign resolves to "see a doctor," never an interpretation.
  • Constitution ≠ trend — innate features (dark circles, face shape) are constants, not changes.
  • Shooting noise — light, angle, makeup, time of day distort more than physiology; mismatched shots → low confidence.
  • Biology lags — skin breakouts (and gut shifts) surface days after a trigger; never pinned to "yesterday."
  • One shot ≠ a pattern — value is the trend; strongest evidence = paired shots, "morning after X vs morning without X" — already almost an n-of-1.

Architecture: the knowledge pyramid 🧱

Everything is plain Markdown in a layered pyramid — raw signal at the base, decisions at the top. Each layer only consumes the one below it, so evidence flows upward and nothing is asserted without a trail back to its source.

Layer Holds Example
00_context north-star, metrics, the domain frame "is life better?", leading vs lagging metrics
📥 01_raw daily records — you + Whoop 2026-06-13.md, photos, voice notes
🔖 02_sources weekly notes, evidence-labelled FACT / INFERENCE per week
📚 03_wiki what you've learned, baselines personal HRV, supplement stack
🧩 04_synthesis patterns + life-quality the cross-layer story
🔬 05_decisions n-of-1 experiments one variable · criterion · verdict
🎁 06_outputs finished artefacts specs, talks
flowchart TB
    CAP["✍️ 🎙️ 🤳 capture · ⌚ Whoop"] --> R["📥 01 · raw"]
    R --> S["🔖 02 · sources<br/>FACT / INFERENCE"]
    S --> Y["🧩 04 · synthesis<br/>patterns · life-quality"]
    Y --> D["🔬 05 · decisions<br/>n-of-1 experiments"]
    D --> RU["✅ rules that stuck"]
    D -. "merge / revert" .-> R
    NS["⭐ 00 · north-star"] -. "is life better?" .-> Y

The retrieval, hooks, and agent all read this pyramid — never raw guesses. The full scientific rationale lives in METHODOLOGY.md; the layer contracts in AGENTS.md.

Technology

Layer Stack
Ingest Whoop API v2, OAuth2 (serialized, race-safe token refresh), Node 22, zero-dep
Capture free Telegram bot (local, long-polling) — text · voice · selfie — + Markdown
Voice whisper (ONNX, on-device) + prebuilt ffmpeg-static — transcription, audio never leaves the device
Vision on-device CLIP (ONNX) auto-routes photos → selfie / food / stool diaries; deep review by agent on demand — non-diagnostic
Knowledge base layered Markdown pyramid 00→06 with frontmatter contracts + evidence labels
Retrieval hybrid RAG — multilingual-e5-small (ONNX) + sqlite-vec + FTS5 BM25, fused via RRF
Agent MCP server (kb_search / kb_think / kb_backlinks) for any MCP client
Control plane Claude Code hooks (evidence + frontmatter linters), permissions, working-memory invariant
Automation macOS launchd — morning sync + brief, hands-off
Quality kb-doctor health-check, weekly dream-cycle audit

Quickstart

📖 Standing up your own copy? Follow the full step-by-step in SETUP.md — Telegram bot, Whoop app, .env, auto-start, and an honest privacy breakdown.

corepack enable
pnpm run setup
cp .env.example .env            # WHOOP + Telegram bot tokens
pnpm whoop:auth                 # one-time OAuth → .whoop/ (gitignored)
pnpm whoop:sync                 # pull physiology + push a morning brief
pnpm kb:index
pnpm kb:think "what actually moves my life quality?"
pnpm kb:doctor

Daily rhythm: morning sync + brief run themselves · evening text/voice/photo your diary to the bot · Sunday ask the agent to review the week.

Privacy & safety

Local-first, but honest about the edges. Your record lives on your disk; pre-processing (voice→text, photo-type, search) runs on-device; photos and sensitive diaries are git-ignored and never pushed; secrets (.env, .whoop/) are git-ignored and deny-read by the agent. What does leave the machine, by design: messages transit Telegram (the Bot API is not end-to-end encrypted), Claude/Anthropic processes what you send the agent to analyse, and Whoop returns your physiology. Nothing is sold or posted publicly. Full breakdown in SETUP.md.

Not a medical device. The agent never diagnoses; any worrying signal resolves to one recommendation — see a specialist.

Contributing

Built as one person's body-as-codebase, designed to generalise to any self-quantifier. PRs especially welcome on: wearable adapters (Oura, Garmin, Apple Health), a live Whoop MCP server, richer experiment designs, and synthesis evals. See CONTRIBUTING.md and the open issues. (Yes, Bryan, you too.)

License

MIT © 2026 Christina Vinter. See LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选