Voltar para as análises
Relatórios de Campo23 min de leitura

Brief do Agente: Construir Conectores de Relatórios de Fitness OpenClaw para Garmin, WHOOP, Speediance e Mais

Um brief de implementação pronto para agentes para construir conectores de relatórios de fitness OpenClaw em Garmin, WHOOP, Speediance, Cronometer, 8Sleep, snapshots JSON normalizados e repositórios públicos do GitHub.

Toby 3 de maio de 2026

Este artigo deve ser entregue a um agente de codificação de IA como um brief de implementação.

O objetivo não é replicar minha máquina local nem fazer engenharia reversa dos meus arquivos. O objetivo é que um agente leia esta página e construa conectores funcionais para os sistemas de fitness: Garmin, WHOOP, Speediance, Cronometer, 8Sleep e o Open Wearables opcional.

A instrução central é simples: trate cada fornecedor como um conector, persista snapshots JSON normalizados e faça o gerador de relatórios consumir apenas esses snapshots. Essa separação transforma a bagunça das APIs específicas de cada fornecedor em um sistema que um agente consegue construir.

O agente deve construir a mesma classe de conexões, sem depender dos meus caminhos locais exatos:

  • Garmin para cardio, carga de treino, pace, zonas de frequência cardíaca e detalhes da atividade
  • WHOOP para recuperação, VFC, FCR, sono, strain e contexto de prontidão
  • Speediance para histórico de sessões de força, volume, calorias, templates e detalhes dos exercícios
  • Cronometer para contexto de nutrição
  • 8Sleep para dados tardios de sono quando disponíveis
  • OpenClaw como a camada de orquestração que executa as sincronizações, normaliza os dados e gera os relatórios

Também aborda os projetos no GitHub, APIs públicas, contratos de dados, modos de falha e verificações de aceitação que um agente de implementação precisa para entregar uma stack funcional sem ver meu repositório privado.


1. Tarefa do agente

Construa uma stack local-first de relatórios de fitness em OpenClaw que consiga se conectar aos sistemas, normalizar os dados deles e gerar relatórios sem chamadas ao vivo aos fornecedores durante a renderização.

O agente deve produzir:

  1. Scripts de conector
    Um job de sincronização por sistema: Garmin, WHOOP, Speediance, Cronometer e 8Sleep quando configurado.
  2. Snapshots brutos
    Payloads com data, em JSON bruto ou derivados de CSV, para depurar mudanças dos fornecedores.
  3. Contratos normalizados
    Arquivos JSON estáveis nos quais o gerador de relatórios pode confiar mesmo quando os payloads dos fornecedores mudam.
  4. Relatório matinal
    Um relatório que combina recuperação, sono, prontidão, carga de treino, nutrição e o plano do dia.
  5. Snapshot de treino adaptativo
    Um plano datado de Speediance/BJJ/corrida derivado da prontidão do dia e da carga recente.
  6. Relatório noturno
    Uma revisão plano vs. realizado, comparando o que foi recomendado com a realidade de Garmin, WHOOP e Speediance.
  7. Saída publicável
    HTML estático e JSON legível por máquina que possa ser implantado no GitHub Pages ou em outro host estático.

Não construa isso como "um único script que chama seis APIs e renderiza HTML ao vivo". Isso é frágil.

2. Arquitetura que o agente deve implementar

Construa em quatro camadas:

  1. Camada de conectores
    Um job de sincronização por plataforma.

Camada de dados normalizada
Cada sincronização grava snapshots JSON estáveis. 3. Camada de análise/relatórios
O código de relatório lê apenas JSON normalizado. 4. Camada de apresentação
HTML, dashboards, briefings diários, posts no Telegram, resumos de voz.

Essa separação é o que torna o sistema mantível.

Contrato de implementação de IA

Agente, construa este contrato antes de escrever qualquer UI de dashboard:

  • Entradas: apenas variáveis de ambiente e credenciais de fornecedores; nunca codifique segredos diretamente em arquivos de código-fonte.
  • Saídas de sincronização: um snapshot JSON bruto por pull de fornecedor, mais um arquivo JSON normalizado por fornecedor.
  • Entradas de relatório: apenas JSON normalizado. O construtor de relatórios não deve chamar Garmin, WHOOP, Speediance, ou Cronometer diretamente.
  • Modo de falha: se um conector falhar, preserve o arquivo normalizado do último estado válido conhecido de ontem e marque essa fonte como desatualizada no relatório.
  • Auditabilidade: mantenha payloads brutos suficientes para depurar mudanças na API do fornecedor sem registrar tokens, cookies, senhas ou cabeçalhos privados.
  • Gate de envio: e-mail, voz, Telegram e ações de treino adaptativo devem exigir dados de recuperação pontuados do mesmo dia. Um relatório web ainda pode ser gerado em modo degradado, mas o sistema não deve enviar coaching confiante a partir de recuperação desatualizada.
  • Snapshots de plano: planos de treino adaptativo devem ser escritos como snapshots JSON diários antes de serem enviados para qualquer lugar. O relatório noturno pode então comparar o plano com o que realmente aconteceu.

Variáveis de ambiente mínimas para um build pronto para o agente:

GARMIN_EMAIL=
GARMIN_PASSWORD=
WHOOP_CLIENT_ID=
WHOOP_CLIENT_SECRET=
WHOOP_ACCESS_TOKEN=
WHOOP_REFRESH_TOKEN=
SPEEDIANCE_USER_ID=
SPEEDIANCE_TOKEN=
SPEEDIANCE_REGION=Global
CRONOMETER_EXPORT_PATH=
EIGHTSLEEP_EMAIL=
EIGHTSLEEP_PASSWORD=

3. Definição de pronto

Um agente de implementação só está pronto quando esses artefatos existem e podem ser regenerados:

  • data/garmin/summary/latest.json
  • data/whoop/normalized/latest.json
  • data/speediance/normalized/history.json
  • data/speediance/normalized/by_exercise.json
  • data/nutrition/latest.json
  • data/eightsleep/normalized/latest.json, se 8Sleep estiver configurado
  • data/training_plans/YYYY-MM-DD_morning.json
  • reports/morning/latest.html
  • reports/nightly/latest.html
  • um gate de envio que retenha envios de e-mail, voz, Telegram e treino adaptativo quando a recuperação WHOOP pontuada do mesmo dia estiver ausente
  • avisos de fonte desatualizada quando um conector falha, mas os dados normalizados do último estado válido conhecido de ontem estão disponíveis
  • uma verificação de ausência de segredos provando que tokens, cookies, senhas e cabeçalhos privados não foram commitados

Se o agente não conseguir autenticar em um fornecedor durante o desenvolvimento, ele ainda deve implementar a interface do conector, .env.example, fixtures falsos, normalizador, tratamento de fontes obsoletas e integração de relatórios.


4. Projetos públicos e referências de código-fonte

Estas são as peças públicas que um agente deve usar como referências de implementação.

Checklist rápido de GitHub/API:

  • Garmin connector: https://github.com/cyberjunky/python-garminconnect
  • Garmin legacy auth context: https://github.com/matin/garth
  • WHOOP official developer API: https://developer.whoop.com/api
  • Speediance public extraction for this build: https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
  • Speediance working fork this was extracted from: https://github.com/ANPC86/SmartGymWorkoutManager
  • Speediance upstream/original reference: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
  • Report generator/template reference: https://github.com/tobyglenn/scriptsJinja
  • Cronometer exports/integrations: https://cronometer.com/

OpenClaw

  • Plataforma/orquestrador: OpenClaw
  • Papel: agendar jobs de sincronização, executar transformações, gerar relatórios, publicar saídas

Garmin

  • Cliente Python principal: cyberjunky/python-garminconnect
    GitHub: https://github.com/cyberjunky/python-garminconnect
  • Biblioteca de autenticação legada que antes era relevante: matin/garth
    GitHub: https://github.com/matin/garth
  • Nota de status: garth está deprecated; python-garminconnect agora usa fluxos de autenticação Garmin mais recentes e é nele que se deve construir.

WHOOP

  • Documentação oficial da API de desenvolvedor: https://developer.whoop.com/api
  • Superfície pública da API: endpoints OAuth2 + REST para recovery, cycles, sleep, workouts, profile, body measurements
  • Wrappers opcionais da comunidade existem, mas um conector construído pelo agente deve se ancorar na API oficial de desenvolvedor WHOOP sempre que possível.

Speediance

  • Referência prática de implementação pública de Speediance: ANPC86/SmartGymWorkoutManager
    GitHub: https://github.com/ANPC86/SmartGymWorkoutManager
  • Linhagem do projeto upstream / referência pública original: hbui3/UnofficialSpeedianceWorkoutManager
    GitHub: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
  • Use o fork ANPC86 SmartGymWorkoutManager como referência prática de conexão porque ele contém trabalho útil em torno de histórico, exports, debugging de API, tratamento de timezone e tratamento de unidades.
  • Esta é uma integração não oficial de Speediance e deve ser tratada como instável por padrão.

Nutrição

  • Site do produto Cronometer / exports / integrações: https://cronometer.com/
  • Trate o Cronometer como uma fonte estruturada de export de nutrição, não como uma dependência mágica direta para relatórios.

5. Atualizações de produção que o agente deve preservar

A versão atual deste stack tem alguns comportamentos importantes que o agente deve preservar.

Máquina única proprietária

O pipeline de fitness deve ter uma máquina autoritativa sempre ligada. Não deixe dois computadores diferentes gerar e deployar relatórios contra o mesmo repositório de saída.

A máquina ativa é responsável pelos jobs de sincronização com fornecedores, geração de relatórios, geração adaptativa de treinos, deploy no GitHub Pages e verificações de watchdog.

Outras máquinas podem visualizar os relatórios ou hospedar dashboards locais, mas não devem regenerar os relatórios de fitness.

Pipeline sequencial em vez de chutes com cron escalonados

Os pipelines matinal e noturno devem rodar como fases ordenadas:

  1. sincronizar dados dos fornecedores
  2. verificar dados obrigatórios do mesmo dia
  3. gerar relatórios
  4. fazer deploy
  5. enviar notificações
  6. gerar resumos em voz, se utilizados
  7. executar validação do watchdog

O erro antigo é agendar essas etapas com offsets fixos de relógio e torcer para que cada fase anterior tivesse terminado. O padrão melhor é um orquestrador que executa cada fase somente depois que a anterior termina de forma limpa.

Gate de recuperação do WHOOP no mesmo dia

Para esta stack, a recuperação do WHOOP no mesmo dia é um gate obrigatório para o coaching. Se a recuperação de hoje estiver ausente, o sistema ainda pode publicar um relatório web com avisos de fonte desatualizada, mas deve reter os envios de email, voz, coaching pelo Telegram e treinos adaptativos.

Essa única regra evita o pior modo de falha: uma recomendação plausível construída a partir da recuperação de ontem.

Tratamento de dados atrasados do 8Sleep

O 8Sleep pode atualizar depois da primeira execução matinal. Uma reexecução deve forçar a atualização de hoje e de ontem antes de regenerar, em vez de confiar em um arquivo JSON local existente só porque ele existe.

Apenas zonas de FC reais do Garmin

Não invente distribuições de zonas de frequência cardíaca a partir da frequência cardíaca média. Se o detalhe da atividade do Garmin incluir dados de tempo na zona, use-os. Se não incluir, oculte esse gráfico ou marque-o como indisponível.

Revisão da execução do plano

O relatório noturno agora funciona melhor quando compara o plano do dia com os dados reais do dia:

  • treino de BJJ planejado vs treino de BJJ do WHOOP
  • sessão de Speediance planejada vs sessões de Speediance concluídas
  • corrida planejada vs distância de corrida do Garmin
  • passos planejados vs passos do Garmin

Isso transforma o relatório noturno em um loop de feedback, em vez de apenas um resumo.

Modo sombra do Open Wearables

O Open Wearables é útil como uma futura camada de abstração, mas eu não trocaria de uma vez um sistema pessoal de relatórios que já funciona. A migração mais segura é o modo sombra:

  1. manter o pipeline baseado em arquivos existente como autoritativo
  2. importar ou espelhar dados de Garmin/WHOOP no Open Wearables
  3. exportar os dados do Open Wearables de volta para arquivos JSON sombra
  4. comparar os arquivos sombra com os arquivos de produção
  5. promover somente depois que contagens, datas e registros do mesmo dia coincidirem

Os arquivos sombra nunca devem sobrescrever as entradas de produção durante o piloto.


6. Garmin: a camada de cardio e detalhes de atividade

Se WHOOP responde "quão recuperado estou?", Garmin responde "o que exatamente eu fiz?"

Garmin é onde o relatório obtém:

  • distância
  • pace e velocidade
  • duração
  • FC média e máxima
  • zonas de frequência cardíaca
  • cadência
  • potência
  • efeito de treino
  • metadados da atividade
  • detalhes mais amplos de cardio/treino que WHOOP não enfatiza tão fortemente

Repositório público para usar

Recomendado: cyberjunky/python-garminconnect

GitHub: https://github.com/cyberjunky/python-garminconnect

Por que isso importa:

  • está ativamente posicionado como o wrapper Python do Garmin Connect a ser usado
  • expõe uma superfície muito ampla de endpoints do Garmin
  • inclui exemplos e padrões de tratamento de tokens
  • substituiu suposições de autenticação mais antigas que quebravam em mudanças anteriores do Garmin

Nota importante de compatibilidade com Garmin

Historicamente, muitas builds usavam garth.

GitHub: https://github.com/matin/garth

Mas garth agora está explicitamente descontinuado. Isso importa porque um agente não deve centralizar uma nova implementação em autenticação descontinuada.

Exemplo mínimo executável de Garmin

from garminconnect import Garmin
from datetime import date
from pathlib import Path
import json
import os

email = os.environ["GARMIN_EMAIL"]
password = os.environ["GARMIN_PASSWORD"]

client = Garmin(email=email, password=password)
client.login()

today = date.today().isoformat()
stats = client.get_stats(today)
activities = client.get_activities_by_date(today, today)

payload = {
    "date": today,
    "stats": stats,
    "activities": activities,
}

out = Path("data/garmin/raw")
out.mkdir(parents=True, exist_ok=True)
(out / f"{today}.json").write_text(json.dumps(payload, indent=2))

O que normalizar a partir de Garmin

Não despeje payloads brutos de Garmin diretamente na lógica do seu relatório final. Normalize-os primeiro em campos como:

  • calendarDate
  • totalSteps
  • restingHeartRate
  • sleepingSeconds
  • bodyBattery
  • activityName
  • activityType
  • durationSeconds
  • distanceMeters
  • distanceMiles
  • averageHR
  • maxHR
  • calories
  • trainingEffect
  • cadence
  • power

Padrão de armazenamento recomendado

  • data/garmin/raw/YYYY-MM-DD.json
  • data/garmin/normalized/YYYY-MM-DD.json
  • data/garmin/summary/latest.json

Isso oferece tanto capacidade de reprodução quanto acesso rápido ao relatório.


7. WHOOP: a camada de recuperação e prontidão

WHOOP é o que torna os relatórios úteis como um motor de decisão, em vez de apenas um registro de atividades.

Ele contribui com:

  • score de recuperação
  • HRV
  • frequência cardíaca em repouso
  • desempenho do sono
  • strain
  • contexto de ciclo
  • enquadramento de prontidão para recomendações matinais e noturnas

API pública a ser usada

Use a API oficial para desenvolvedores do WHOOP:

  • Documentação: https://developer.whoop.com/api

Grupos de endpoints relevantes:

  • /developer/v2/cycle
  • /developer/v2/recovery
  • /developer/v2/activity/sleep
  • /developer/v2/activity/workout
  • /developer/v2/user/profile/basic
  • /developer/v2/user/measurement/body

Limitação crítica

Uma das constatações de implementação mais importantes: os dados de diário não estão disponíveis na API do WHOOP.

Se você quer respostas de diário ou anotações de hábitos, não dá para contar com um endpoint público da API do WHOOP para isso. As opções práticas são:

  • exportação manual de CSV a partir do WHOOP
  • sua própria camada paralela de diário
  • metadados separados que você anexa após a sincronização

Essa limitação precisa ser declarada de forma clara no artigo porque afeta qualquer implementação séria.

Exemplo mínimo executável com WHOOP

from pathlib import Path
import json
import os
import requests

BASE = "https://api.prod.whoop.com/developer/v2"
TOKEN = os.environ["WHOOP_ACCESS_TOKEN"]
headers = {"Authorization": f"Bearer {TOKEN}"}

def get(path):
    response = requests.get(f"{BASE}{path}", headers=headers, timeout=30)
    response.raise_for_status()
    return response.json()

payload = {
    "recovery": get("/recovery"),
    "sleep": get("/activity/sleep"),
    "workouts": get("/activity/workout"),
}

out = Path("data/whoop/raw")
out.mkdir(parents=True, exist_ok=True)
(out / "latest.json").write_text(json.dumps(payload, indent=2))

O que normalizar a partir do WHOOP

Normalize em campos como:

  • recovery_score
  • hrv_rmssd_milli
  • resting_heart_rate
  • spo2_percentage
  • skin_temp_celsius
  • sleep_performance_percentage
  • respiratory_rate
  • strain
  • cycle_start
  • cycle_end
  • workout_sport_name

Padrão de armazenamento recomendado

  • data/whoop/raw/recovery.json
  • data/whoop/raw/sleep.json
  • data/whoop/raw/workouts.json
  • data/whoop/normalized/latest.json

8. Speediance: a camada de musculação

Speediance é o conector mais incomum de toda a stack.

Diferente do Garmin e do WHOOP, este não é uma plataforma oficial pública e bem estruturada para desenvolvedores. O agente deve usar estes repositórios públicos como referências de conexão:

Extração/referência pública: https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager

ANPC86/SmartGymWorkoutManager
GitHub: https://github.com/ANPC86/SmartGymWorkoutManager

Esse repositório é, por si só, um fork pessoal / continuação do projeto público original do Speediance:

hbui3/UnofficialSpeedianceWorkoutManager
GitHub: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager

Esses repositórios são o ponto de partida importante porque mostram como:

  • se autenticar nos endpoints do Speediance
  • inspecionar dados de treino e respostas da API
  • navegar/exportar o histórico de treinos
  • gerenciar templates/treinos de forma amigável para desktop
  • lidar com questões práticas como exibição de fuso horário e tratamento de pesos em imperial/métrico

Por que esses repositórios importam

Use o fork ANPC86 SmartGymWorkoutManager como base prática para o padrão de integração Speediance, preservando a referência upstream hbui3 para fins de procedência. Juntos, eles são as referências públicas mais claras para trabalhar com dados do Speediance fora do aplicativo oficial.

Aviso de estabilidade

O projeto original observa que o Speediance vem implementando atualizações de segurança. Isso significa que:

  • esta integração pode quebrar
  • cabeçalhos e comportamento de autenticação podem mudar
  • endpoints podem mudar
  • você deve isolar este conector atrás de uma etapa de normalização para que seus relatórios sobrevivam às mudanças do lado do fornecedor

Padrão executável mínimo para Speediance

Se você usar ANPC86/SmartGymWorkoutManager como ponto de partida, conferindo o upstream hbui3/UnofficialSpeedianceWorkoutManager para o contexto original, a abordagem limpa é:

  1. Execute o app ou a camada cliente localmente
  2. Faça autenticação com sua conta Speediance
  3. Extraia o histórico de treinos a partir dos métodos de API que ele expõe
  4. Exporte o JSON normalizado para o seu próprio diretório de dados

Pseudo-exemplo usando esse padrão de cliente:

# Modele isso em torno do api_client.py em:
# https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
from api_client import SpeedianceClient
from datetime import date
from pathlib import Path
import json
import os

client = SpeedianceClient()
success, msg, debug = client.login(
    os.environ["SPEEDIANCE_USER_ID"],
    os.environ["SPEEDIANCE_TOKEN"],
)
if not success:
    raise RuntimeError(msg)

start_date = os.environ.get("SPEEDIANCE_START_DATE", "2026-01-01")
end_date = date.today().isoformat()
records = client.get_training_data(start_date, end_date)

out = Path("data/speediance/raw")
out.mkdir(parents=True, exist_ok=True)
(out / "history.json").write_text(json.dumps(records, indent=2))

O que normalizar a partir do Speediance

Normalize em campos como:

  • training_id
  • date
  • title
  • duration_seconds
  • calories
  • total_volume
  • exercise_count
  • template_name
  • planned_duration
  • actual_duration
  • exercise_breakdown
  • estimated_1rm

Modelo de dados de melhor prática

Para um sistema de relatórios sério, mantenha dois índices:

  1. bySession
  • um registro por treino concluído
  1. byExercise
  • um fluxo de registros por nome de movimento
  • inclui peso, repetições, lado, id da sessão, timestamp

Essa estrutura torna gráficos de progressão e detecção de PRs triviais depois.

Padrão de armazenamento recomendado

  • data/speediance/raw/monthly/YYYY-MM.json
  • data/speediance/normalized/history.json
  • data/speediance/normalized/by_exercise.json
  • data/speediance/dashboard/latest.json

Snapshots adaptativos de treinos do Speediance

A versão mais avançada desta build não lê apenas treinos concluídos do Speediance.

Ele também cria treinos planejados a partir de dados de prontidão em tempo real.

O padrão útil é:

  1. Carregar recuperação WHOOP do mesmo dia, strain atual, strain BJJ, body battery Garmin, FC de repouso, carga de corrida recente, clima e histórico recente do plano Speediance.
  2. Classificar o dia em uma categoria como build, maintain, recover, protect ou post_bjj_brutal.
  3. Selecionar um implemento Speediance para o treino inteiro, geralmente alças, barra ou corda.
  4. Escolher apenas exercícios no aparelho para o treino núcleo de Speediance.
  5. Adicionar de zero a dois acessórios off-Speediance somente quando a recuperação permitir.
  6. Escrever o plano em data/training_plans/YYYY-MM-DD_context.json.
  7. Usar o snapshot tanto para a recomendação da manhã quanto para a revisão noturna da execução do plano.

Para controle de repetição, compare a assinatura do novo treino com snapshots de planos recentes. A versão de produção usa uma janela de unicidade rolante que cresce até 30 dias e sempre carimba o título do treino com a data de hoje, para que um treino que reapareça ainda esteja atualizado e pesquisável.


9. Cronometer: a camada de contexto de nutrição

Independentemente do aplicativo de nutrição exato que você usa, o papel é o mesmo: dar ao relatório contexto sobre a ingestão de energia.

Isso importa porque carga de treino sem contexto de nutrição leva a conclusões ruins.

O relatório deve ser capaz de perguntar:

  • A recuperação estava baixa porque a carga de treino estava alta?
  • Ou porque o sono foi ruim e a ingestão calórica foi baixa?
  • O atleta estava subalimentado em relação à produção?

Conselho prático de implementação

Não dependa de uma API de nutrição em tempo real no momento da renderização. Use uma das opções:

  • Exportação CSV
  • Ingestão por webhook
  • Sincronização agendada para JSON normalizado

Normalize em campos como:

  • calories_consumed
  • protein_g
  • carbs_g
  • fat_g
  • fiber_g
  • target_calories
  • estimated_deficit

Padrão de armazenamento recomendado

  • data/nutrition/raw/YYYY-MM-DD.csv
  • data/nutrition/normalized/YYYY-MM-DD.json
  • data/nutrition/latest.json

10. 8Sleep: a camada de contexto de sono que chega atrasada

8Sleep é opcional, mas se estiver configurado, o agente deve tratá-lo como qualquer outro conector: sincronizar primeiro, normalizar em segundo, renderizar a partir dos arquivos por último.

O comportamento importante é o tratamento de dados atrasados. Os dados de sono podem mudar após a primeira execução da manhã, então uma reexecução manual ou uma retentativa agendada deve forçar a atualização tanto de hoje quanto de ontem antes de regenerar o relatório.

Normalize campos como:

  • sleep_score
  • sleep_start
  • sleep_end
  • time_in_bed_seconds
  • time_asleep_seconds
  • hrv
  • resting_heart_rate
  • temperature_adjustments
  • away_mode

Padrão de armazenamento recomendado:

  • data/eightsleep/raw/YYYY-MM-DD.json
  • data/eightsleep/normalized/YYYY-MM-DD.json
  • data/eightsleep/normalized/latest.json

11.

O que o OpenClaw realmente faz neste stack

O OpenClaw não é a fonte de dados. Ele é a camada de orquestração e raciocínio.

A função dele é:

  • executar jobs de sincronização conforme o agendamento
  • armazenar saídas estáveis
  • comparar fontes
  • gerar o HTML do relatório
  • publicar links
  • produzir resumos amigáveis a partir dos dados normalizados

Isso significa que o código de geração de relatórios deve ler de arquivos como:

  • data/garmin/summary/latest.json
  • data/whoop/normalized/latest.json
  • data/speediance/normalized/history.json
  • data/nutrition/latest.json
  • data/eightsleep/normalized/latest.json

O gerador de relatórios nunca deve precisar saber como funciona a autenticação do Garmin ou como os cabeçalhos do Speediance mudaram nesta semana.


12. Estrutura de diretórios construível por agente

Aqui está uma estrutura que um agente pode criar antes que qualquer autenticação real de fornecedor seja bem-sucedida:

project/
  data/
    garmin/
      raw/
      normalized/
      summary/
    whoop/
      raw/
      normalized/
    speediance/
      raw/
      normalized/
      dashboard/
    nutrition/
      raw/
      normalized/
    eightsleep/
      raw/
      normalized/
    training_plans/
  scripts/
    sync_garmin.py
    sync_whoop.py
    sync_speediance.py
    sync_nutrition.py
    sync_eightsleep.py
    gate_same_day_recovery.py
    build_adaptive_plan.py
    build_report.py
  reports/
    morning/
      latest.html
    nightly/
      latest.html
  frontend/
    data/

A estrutura de arquivos faz parte da interface. Mantenha-a simples o suficiente para que um agente futuro consiga inspecionar o sistema, localizar cada conector, executar novamente uma única sincronização e comparar os payloads brutos com as saídas normalizadas.


13. Exemplo de padrão de construtor de relatório

Quando cada conector grava JSON normalizado, o código real do relatório se torna simples.

import json
from pathlib import Path

base = Path("data")

garmin = json.loads((base / "garmin/summary/latest.json").read_text())
whoop = json.loads((base / "whoop/normalized/latest.json").read_text())
speediance = json.loads((base / "speediance/normalized/history.json").read_text())
nutrition = json.loads((base / "nutrition/latest.json").read_text())
eightsleep_path = base / "eightsleep/normalized/latest.json"
eightsleep = json.loads(eightsleep_path.read_text()) if eightsleep_path.exists() else {}

summary = {
    "recovery": whoop.get("recovery_score"),
    "hrv": whoop.get("hrv_rmssd_milli"),
    "rhr": whoop.get("resting_heart_rate"),
    "steps": garmin.get("totalSteps"),
    "body_battery": garmin.get("bodyBattery"),
    "lifting_volume": speediance.get("today", {}).get("total_volume"),
    "calories_in": nutrition.get("calories_consumed"),
    "sleep_score": eightsleep.get("sleep_score"),
}

html = f"""
<html>
  <body>
    <h1>Relatório Diário de Fitness</h1>
    <ul>
      <li>Recuperação: {summary['recovery']}</li>
      <li>HRV: {summary['hrv']}</li>
      <li>RHR: {summary['rhr']}</li>
      <li>Passos: {summary['steps']}</li>
      <li>Body Battery: {summary['body_battery']}</li>
      <li>Volume de Musculação: {summary['lifting_volume']}</li>
      <li>Calorias Consumidas: {summary['calories_in']}</li>
      <li>8Sleep Pontuação: {summary['sleep_score']}</li>
    </ul>
  </body>
</html>
"""

out = Path("reports/morning")
out.mkdir(parents=True, exist_ok=True)
(out / "latest.html").write_text(html)

É aqui que todo o design compensa: uma vez que a camada de sincronização está consistente, a camada de relatório fica monótona da melhor maneira possível.


14. Para que cada conector realmente serve

Este é o modelo mental mais simples:

WHOOP

Usar para:

  • recuperação
  • HRV
  • RHR
  • desempenho do sono
  • strain
  • enquadramento de prontidão

Garmin

Usar para:

  • detalhes de corrida e cardio
  • pace, potência, cadência
  • zonas de FC
  • efeito de treino
  • histórico detalhado de atividades

Speediance

Usar para:

  • histórico de treinos de força
  • volume total
  • detalhe de exercícios
  • execução planejada vs. real da sessão
  • progressão em nível de movimento se você construir indexação por exercício

Aplicativo de nutrição

Usar para:

  • ingestão calórica
  • contexto de macronutrientes
  • detecção de subalimentação

8Sleep

Usar para:

  • detalhes do sono que chegam atrasados
  • duração e pontuação do sono específicas da cama
  • verificações cruzadas do contexto do sono contra WHOOP e Garmin

OpenClaw então combina todos eles em uma única superfície de relatório e recomendação.


15. Entregáveis de conexão por sistema

Este é o checklist que o agente de implementação deve satisfazer antes de polir a interface do relatório.

Pontos de conexão Garmin

  • Biblioteca: garminconnect de cyberjunky/python-garminconnect
  • Autenticação: e-mail/senha do Garmin Connect com o tratamento de token/sessão da biblioteca
  • Cadência de pull: sincronização diária pela manhã mais sincronização opcional pós-treino
  • Pulls mínimos:
    • estatísticas diárias de passos, FC em repouso, segundos de sono, body battery, calorias
    • atividades por data para sessões de corrida/ciclismo/cardio
    • detalhes da atividade quando disponível para zonas de FC, pace, cadência, potência, efeito de treino
  • Saída normalizada: data/garmin/summary/latest.json

Pontos de conexão WHOOP

  • Documentação da API: https://developer.whoop.com/api
  • Autenticação: fluxo de token de acesso OAuth2 + refresh token
  • URL base: https://api.prod.whoop.com/developer/v2
  • Grupos mínimos de endpoints:
    • /cycle para contexto de strain/ciclo
    • /recovery para score de recuperação, HRV, FC em repouso
    • /activity/sleep para desempenho e tempo de sono
    • /activity/workout para treinos e dados de strain WHOOP
    • /user/profile/basic e /user/measurement/body para contexto de perfil/corpo quando necessário
  • Saída normalizada: data/whoop/normalized/latest.json

Pontos de conexão Speediance

  • Extração pública para esta build: https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
  • Referência upstream: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
  • Autenticação: fluxo não oficial baseado em token/user-id exposto pela camada cliente SmartGym
  • Coletas mínimas:
    • histórico de treinos
    • detalhes de exercício/sessão
    • metadados de treino/modelo personalizado se você quiser relatórios planejado vs real
    • captura de resposta bruta de API/debug sem segredos
  • Saídas normalizadas:
    • data/speediance/normalized/history.json
    • data/speediance/normalized/by_exercise.json

Pontos de conexão Cronometer

  • Fonte pública: exports/integrations https://cronometer.com/
  • Abordagem de implementação recomendada: export CSV ou drop de arquivo agendado, não uma dependência de API em tempo de renderização ao vivo
  • Campos mínimos: data, calorias, proteína, carboidratos, gordura, fibra e quaisquer micronutrientes que você queira na análise de recuperação
  • Saída normalizada: data/nutrition/latest.json

Pontos de conexão 8Sleep

  • Autenticação: fluxo de login/sessão apoiado por variáveis de ambiente, sem credenciais no código-fonte
  • Cadência de coleta: sincronização matinal mais suporte a rerun/refresh para hoje e ontem
  • Coletas mínimas:
    • score de sono
    • tempo de sono
    • tempo dormindo e tempo na cama
    • HRV e FC em repouso quando disponíveis
    • contexto de temperatura e away-mode quando disponíveis
  • Saída normalizada: data/eightsleep/normalized/latest.json

Ponto de conexão para geração de relatório

O gerador de relatórios deve ler apenas arquivos normalizados estáveis e snapshots de planos. Um formato prático é:

data/garmin/summary/latest.json
data/whoop/normalized/latest.json
data/speediance/normalized/history.json
data/speediance/normalized/by_exercise.json
data/nutrition/latest.json
data/eightsleep/normalized/latest.json
data/training_plans/YYYY-MM-DD_morning.json
data/training_plans/YYYY-MM-DD_post_bjj.json

Essa é a superfície de conexão real. Tudo upstream pode quebrar e ser corrigido de forma independente.


16. As regras reais de implementação

Se um agente vai construir isso com sucesso, essas regras importam mais do que qualquer trecho de código isolado:

  1. Normalize cada fornecedor em seu próprio schema
    Nunca deixe um relatório depender do formato de payload do fornecedor.

  2. Mantenha snapshots brutos
    Quando uma sincronização quebra, payloads brutos salvam você.

Never render from live APIs if the report is time-sensitive
Sync first, render second.

  1. Treat unofficial integrations as disposable adapters
    Especially Speediance.

  2. Make Garmin and WHOOP complement each other, not compete
    WHOOP = readiness. Garmin = execution detail.

  3. Model strength data at both session and exercise level
    Otherwise progression reporting stays shallow.

  4. Gate coaching on today's readiness, not yesterday's
    Missing same-day recovery should degrade the system to web-only reporting.

  5. Save the plan before judging the day
    A nightly adherence score only works if the morning or post-BJJ plan was stored as data.

  6. Pilot new backends in shadow mode
    Open Wearables or any other abstraction layer should prove it can match current production files before it becomes the source of truth.


Lista de referência final de implementação

Estas são as referências públicas que um agente de codificação de IA deve receber primeiro ao implementar este sistema:

  • OpenClaw como a camada de orquestração
  • Conector Garmin: https://github.com/cyberjunky/python-garminconnect
  • Contexto histórico de autenticação Garmin: https://github.com/matin/garth (descontinuado; use como contexto, não como centro de uma nova construção)
  • API oficial de desenvolvedor WHOOP: https://developer.whoop.com/api
  • Extração pública de Speediance para esta build: https://github.com/clawdassistant85-netizen/speediance-smartgym-workout-manager
  • Referência upstream/original de Speediance: https://github.com/hbui3/UnofficialSpeedianceWorkoutManager
  • Referência de gerador/modelo de relatório: https://github.com/tobyglenn/scriptsJinja
  • Exportações de nutrição do Cronometer: https://cronometer.com/
  • Contrato do conector 8Sleep: sincronização apoiada por ambiente que grava data/eightsleep/normalized/latest.json

Se você está entregando este artigo para Claude Code, Codex, OpenClaw, ou outro agente de implementação, a instrução correta é: construa os conectores primeiro, escreva os snapshots JSON normalizados em segundo lugar, imponha o gate de recuperação do mesmo dia em terceiro, e então construa o renderizador de relatório por último. Não comece projetando o relatório HTML final.


#openclaw#garmin#whoop#speediance#relatórios de fitness#sistemas de IA