Skip to content

Repository files navigation

Weekly Health Report

iOS CI codecov

Weekly Health Report is a small iPhone app that turns selected Apple Health data into a readable weekly summary and an explicitly reviewed daily JSON snapshot. Pick a reporting period, refresh the data, then copy the plain-text report or manually export the daily JSON to a Google Drive destination you selected.

It is a personal informational utility, not medical software.

Weekly Health Report running on an iPhone simulator with synthetic health data Synthetic Daily JSON Export screen showing a prepared snapshot and explicit export action
Weekly report Daily JSON review and export

All screenshots use invented values and identities. They are documentation examples; the repository does not contain exported or personal HealthKit values.

What it reports

Area Included measurements
Body Latest weight and recording time, weight trend, body fat and trend, waist circumference and four-week trend
Daily activity Average daily steps, active energy, Apple Exercise Time, workout count, type, duration and start time
Heart and sleep Blood pressure, resting heart rate, HRV, sleep and days with Apple Watch data
Fitness estimates Latest VO₂ max with four-week, three-month and six-month averages, plus blood oxygen
Glucose A weekly average calculated from daily values, observed range and days with data
Medications Taken medication events, dose and time on iOS 26 or later
Daily JSON only Source-filtered nutrition totals, completed-day averages and trends for all 39 Apple Health dietary quantity types, plus private date-bound notes you type and explicitly export

The app has one main screen, a manual Daily JSON Export screen and a separate Developer Diagnostics screen for checking daily values against Apple Health. Copy Report puts a human-readable version on the iOS clipboard.

On the main report, a normal system screenshot also offers Apple's native Full Page representation. The app creates that report PDF in memory only when iOS requests it, using one stable snapshot and a document layout independent of the scrolling form. It includes all report sections and the current blood-pressure detail state, but not navigation, export, copy, refresh or diagnostics controls. Other screens provide only the ordinary screenshot. Saving or sharing remains in the system screenshot editor; the app adds no screenshot or share button and keeps no generated file.

See a synthetic Full Page report Complete synthetic Full Page weekly health report containing every metric section

This mock-up shows the document structure returned to the iOS screenshot editor. Every value and name is invented.

Export daily JSON to Google Drive

Daily export is a separate, manual workflow. Opening Daily JSON Export restores any known account, destination and nutrition-source choices, then prepares a fresh immutable snapshot in memory. Nothing is uploaded until you review that snapshot and tap Export prepared snapshot.

  1. Connect the Google account that should receive the file. The app requests only drive.file, which limits it to files and folders opened or created through the app.
  2. Select an existing folder by its exact Drive ID, or explicitly create a dedicated WeeklyHealthReport Exports folder. Folder names are labels, not identity.
  3. Authorise and select the exact Apple Health nutrition source whose data should be included, then save any date-bound notes you want to export. Draft notes are excluded.
  4. Review the report date, data cutoff, nutrition source, note count, completed-day windows and encoded byte count. Use Review exact JSON to inspect the actual bytes prepared for upload.
  5. Tap Export prepared snapshot. Refresh first if a saved note or relevant selection changed, because the previous preview is deliberately made stale rather than silently altered.

The version 3 JSON envelope records schema_version, report_date, time_zone, data_as_of, exported_at and day_window. Its today object contains the current day's values through the frozen cutoff and an ordered notes array. app_context contains deterministic completed-day summaries and trends. Nutrition covers Apple's 39 supported dietary quantity types, restricted to the selected HealthKit source; missing or inaccessible values remain explicit states rather than becoming zero.

Each local reporting date has one canonical health-daily-YYYY-MM-DD.json file in the selected destination. The filename is a convention; the securely stored Drive file ID is its identity. A later export for the same date updates that exact file without deleting it first. The app reports success only after reading back the account, folder and file metadata and confirming that the remote bytes exactly match the reviewed snapshot.

There is no automatic export, background sync or offline queue. Disconnecting Google or changing the app's destination does not delete files already stored in Drive. For the normative field and state rules, see the daily export contract. Developers enabling Drive in a local build should also read the product setup notes.

Privacy

All HealthKit reading and calculation happens on the iPhone. Nothing leaves the device unless you copy the text report yourself or explicitly open Daily JSON Export, review the automatically prepared or manually refreshed snapshot, and choose Export prepared snapshot.

The optional Drive feature:

  • requests only Google's drive.file permission, never a whole-Drive scope;
  • sends the exact reviewed health JSON directly from the app to Google Drive;
  • stores OAuth credentials and minimal account, destination and canonical-file identity in this-device-only Keychain items;
  • has no analytics, telemetry, backend, database, hosted component, automatic export, background sync or offline queue;
  • never enumerates destination contents or treats limited Drive visibility as proof that a folder is empty; and
  • supports one active exporting installation and blocks ambiguous identity recovery.

Typed notes and unfinished drafts are stored in this app's Application Support directory with iOS file protection. Drafts are never exported. Saved notes enter only a newly refreshed JSON preview and remain on-device until you review and explicitly export those exact bytes. An edit or deletion makes an existing preview stale. Verified prior-day notes are removed lazily only when the same unchanged revision was remotely verified; drafts are retained.

The note editor also offers a dedicated microphone path on supported devices and locales. Microphone and speech permissions are requested only after you tap it. The app starts capture only when SFSpeechRecognizer reports on-device support and every request requires on-device recognition; there is no server-recognition fallback. Audio is streamed only into the active recognition request and is never persisted, logged, exported or uploaded. Partial text stays separate until Speech finalises it. If a pause resets the live result, recognition fails, or Stop returns an empty, incomplete or no final result, the app assembles the affected recognised text once and keeps it as one editable candidate. The typed draft stays unchanged until that candidate is explicitly added, and a three-second Stop fallback prevents the editor remaining in an indefinite finishing state. Late callbacks from that capture are ignored. If the complete addition exceeds a note limit, the draft likewise stays unchanged and the candidate remains separately editable until it is accepted after editing or explicitly discarded. Ordinary keyboard Dictation is controlled separately by iOS and is not covered by this local guarantee.

Google receives the selected JSON and applies its own storage/account terms. A successful app status means Drive metadata and content bytes were read back and matched; it does not prove that another consumer fetched the file. The separate synthetic harness remains development evidence and uses a different OAuth client.

The app asks only for read access to the HealthKit types it uses. HealthKit does not tell an app whether read access was denied, so a successful query with no visible samples is shown as No data, not zero.

See the requested Health permissions

The app requests read access to Body Mass, Body Fat Percentage, Waist Circumference, Blood Glucose, Blood Pressure Systolic, Blood Pressure Diastolic, VO₂ Max, Oxygen Saturation, Step Count, Heart Rate, Resting Heart Rate, Heart Rate Variability (SDNN), Sleep Analysis, Active Energy, Apple Exercise Time and Workouts. The Daily JSON Export flow separately requests read-only access to Apple's 39 dietary quantity types when you refresh visible nutrition sources. On iOS 26 or later, it can also request access to medications that you select individually.

It never asks for write access, background delivery or clinical health records. If you installed an older build before a metric was added, iOS should offer the new read permission the next time the app runs.

Glucose is read from Apple Health. The app does not connect directly to Abbott, Lingo or another sensor account. The sensor's own app must write bloodGlucose samples to HealthKit first.

Blood pressure is also read from Apple Health rather than directly from a cuff. A monitor's companion app, such as Omron Connect, must first save complete blood-pressure correlations to HealthKit.

Nutrition is also an Apple Health feature rather than a direct provider integration. In Daily JSON Export, first-time nutrition authorisation and source selection are explicit. The app stores that choice by HealthKit bundle identifier; the source name is only a label. On later foreground visits it silently resolves only that exact source and prepares a fresh preview without presenting HealthKit authorisation. Every nutrition statistic is restricted to the selected source, and a missing or unavailable selection blocks preview refresh rather than falling back to combined nutrition data.

Run it on your iPhone

You need a Mac with the current stable Xcode, an iPhone and an Apple development team for code signing. The deployment target is iOS 17. Medication reporting requires iOS 26 or later.

The published app uses com.otherweather.WeeklyHealthReport as its canonical bundle identifier. Forks and local variants should override it with an identifier owned by their development team.

  1. Clone the repository and open WeeklyHealthReport.xcodeproj in Xcode.
  2. Copy Config/Signing.local.xcconfig.example to Config/Signing.local.xcconfig.
  3. In the local file, replace YOUR_TEAM_ID with your Apple development team ID and choose a bundle identifier that is unique to your team.
  4. Select the WeeklyHealthReport target and open Signing & Capabilities. Confirm that your team, bundle identifier and the HealthKit capability are present.
  5. Connect and trust your iPhone. Enable Developer Mode if iOS asks for it.
  6. Select the iPhone as the run destination and press Run.
  7. Approve the Health read permissions you want the app to use.

Config/Signing.local.xcconfig is ignored by Git, so your personal signing values stay local. No App Store setup is required.

Optional Google Drive export setup

The checked-in build fails closed with Drive controls disabled. To enable them, create a separate native iOS OAuth client for the product app's exact bundle identifier, then copy Config/DriveOAuth.local.xcconfig.example to the ignored Config/DriveOAuth.local.xcconfig and set the client ID and reversed redirect scheme. Do not reuse the synthetic-harness client and do not add a client secret, API key, web client, hosted origin or backend. See the product setup notes.

After explicit Google consent, an account with no prior destination binding must either choose an existing folder by its exact Drive ID or explicitly create one dedicated WeeklyHealthReport Exports folder. Folder names are never searched or treated as identity. Later foreground visits revalidate the secure session, account-specific folder and exact saved nutrition source, then prepare a new in-memory snapshot. Missing, inaccessible or trashed stored destinations are never silently replaced. Export remains a separate explicit action; account removal, destination changes and exact-file migration or recovery are contextual controls. Google's mobile Picker requires a consent step when granting access to another folder or file, but the app pins that flow to the already connected account rather than asking for a new account choice.

On iOS 26 or later, Health presents a separate medication chooser. To change access later, open Health, tap your profile picture, then go to Apps > WeeklyHealthReport. When you add a new medication in Health, enable WeeklyHealthReport on the final screen if you want the app to read it.

Choose a reporting period

All dates use the iPhone's local calendar and time zone. Date-and-time values use the shared dd/MM/yy - HH:mm 24-hour format throughout the app and copied report. The start is included and the end is excluded.

  • Last 7 Completed Days is the default. It runs from local midnight seven calendar days ago to local midnight today.
  • Current Week runs from the locale-aware start of this week to local midnight today. It excludes today's partial data.
  • Previous Week is the previous complete locale-aware calendar week.

These are calendar periods, not a rolling 168-hour window. Last 7 Completed Days still contains seven calendar days when daylight-saving time changes.

What gets copied

The copied report is plain text. Latest weight, waist, blood oxygen and blood pressure are selected independently of the weekly period, so a measurement recorded today can appear alongside a report of completed days.

See a synthetic copied report
Weekly Health Report
Last 7 Completed Days
18–24 Aug 2026
Generated: 26/08/26 - 09:00

Steps
Average Daily Steps: 2,727
Data Coverage: 7 / 7 days
Weekly Total: 19,089

Weight
Latest Weight: 100.6 kg
Measured: 25/08/26 - 00:00
7-day Average: 100.8 kg
Weight Trend: -0.4 kg vs previous 7d

Body Composition
Body Fat: 26.5% latest
7-day Average: 26.7%
28-day Average: 26.7%
Body Fat Trend: ↓ 0.9 pp vs previous 28d
Waist Circumference: 101.4 cm
Waist Measured: 24/08/26 - 09:00
4-week Waist Trend: -1.7 cm vs ~4 weeks earlier

Heart
Resting HR Average: 73 bpm
Resting HR Trend: +3.0 bpm vs previous 7d
HRV Average: 42 ms
HRV Trend: -5.0 ms vs previous 7d
Watch Data Coverage: 4 / 7 days

Blood Pressure
Latest reading: 123/78 mmHg
Recorded: 24/08/26 - 20:14
Morning average: 124.1/79.2 mmHg
Latest batch: 125.3/79.7 mmHg
Recorded: 24/08/26 - 08:11 · 3 readings
Coverage: 5/7 days · 15 readings
Evening average: 122.8/77.6 mmHg
Latest batch: 122.7/77.3 mmHg
Recorded: 24/08/26 - 20:14 · 3 readings
Coverage: 4/7 days · 12 readings
Period averages use completed days. Morning is before 14:00; evening is from 17:00. Mid-afternoon readings are excluded from both slot summaries.

Cardiorespiratory
Latest VO₂ Max: 32.1 mL/kg/min
VO₂ Max Measured: 24/08/26 - 09:00
4-Week Average: 31.8 mL/kg/min (8 days)
3-Month Average: 30.9 mL/kg/min (24 days)
6-Month Average: 29.7 mL/kg/min (51 days)
Latest Blood Oxygen: 97%
Blood Oxygen Measured: 24/08/26 - 09:00
Period Typical: 97%
Daily Median Range: 96–98%
Blood Oxygen Coverage: 7 / 7 days
Apple Watch blood-oxygen measurements are wellness estimates, not medical measurements.

Glucose
Daily Average: 5.8 mmol/L
Observed Range: 3.9–8.7 mmol/L
Data Coverage: 7 / 7 days

Activity
Active Energy: 1,974 kcal
Exercise: 89 min
Workouts: 1
Workout Time: 30m
Walking: 30m — 18/08/26 - 00:00

Sleep
Average Sleep: 6h 48m

Medications Taken
No taken medication events are visible for this period.

How the calculations work

Correct HealthKit aggregation is the main reason this project exists. Cumulative measurements use HealthKit statistics rather than manually adding raw samples from an iPhone, Apple Watch and other sources. Measurements such as HRV are calculated per day first so that a day with more samples does not dominate the week.

Read the metric-by-metric rules
  • Weight: the latest visible body-mass sample in the preceding 30 days is shown independently. For trend, multiple readings on a day are averaged first; the mean of sampled days in the latest seven completed days is compared with the preceding seven completed days. Each side requires at least three sampled days. The signed difference is reported in kg.
  • Body fat: HealthKit percent values are fractional (0.30 means 30.0%) and are converted to percentage points at the query boundary. Up to 60 days of visible samples are read. The independent latest measurement may include today. The seven-day and current or previous 28-day averages use only completed local-calendar days, with an inclusive start and exclusive local-midnight end. Multiple readings on one completed day are averaged first, then sampled days receive equal weight. Each average requires at least two sampled days. Trend is the current 28-day daily mean minus the previous 28-day daily mean, in percentage points.
  • Waist circumference: the latest visible manual measurement from an eight-week lookback ending at refresh time is displayed in centimetres with its timestamp, independently of the selected weekly period. Sparse measurements are not averaged. For a four-week trend, the app compares it with the visible sample closest to 28 days earlier, but only when that sample is 21 to 35 days older. Otherwise it reports insufficient history. A measurement entered today can appear immediately.
  • Blood glucose: HealthKit's daily discreteAverage, discreteMin and discreteMax statistics are calculated for each complete local calendar day. Values are converted using HealthKit's blood-glucose molar mass and displayed in mmol/L. The weekly average is the arithmetic mean of valid daily averages, so days with more sensor readings do not dominate. The observed range is the minimum and maximum visible statistic across the period, and coverage reports days with data. The app does not apply a target range, time-in-range score, diagnosis or medical interpretation.
  • VO₂ max: the latest visible estimate and timestamp from the preceding six calendar months are displayed. Multiple estimates on one local calendar day are averaged first, then sampled days receive equal weight in rolling four-week, three-month and six-month averages ending at refresh time. Each average requires at least three sampled days and reports its sampled-day count. VO₂ max is a discrete Watch estimate, not a clinical exercise test. The app does not classify fitness or provide medical interpretation.
  • Blood oxygen: the latest visible oxygen-saturation sample from a 30-day lookback is displayed with its timestamp. For the selected completed-day period, visible discrete samples are converted from HealthKit fractions to percentage points. The median is calculated within each complete day, followed by the median and range of valid daily medians. This prevents days with more background measurements from dominating and reduces the effect of isolated outliers. Coverage reports valid days. Apple Watch blood-oxygen values are general wellness estimates, not medical measurements.
  • Blood pressure: HealthKit stores one blood-pressure reading as a correlation containing its systolic and diastolic quantity samples. The app requests read access to both quantity types and accepts only correlations containing exactly one visible sample of each type; it never joins independent samples. Complete pairs from a 30-day lookback ending at refresh time are converted to mmHg. The newest pair is shown with its timestamp, including a reading from today. For slot summaries, morning means before 14:00 local time and evening means 17:00 or later. Readings from 14:00 through 16:59 remain eligible to be the latest reading and remain visible in Diagnostics, but are excluded from both slot summaries rather than being guessed into one. Within each completed local day and slot, systolic and diastolic values are averaged separately over the same set of paired readings. The selected-period average is then the arithmetic mean of those daily batch averages, giving every sampled day equal weight. Coverage reports sampled days, reporting days and complete paired readings separately for morning and evening. Latest morning and evening batches use the latest qualifying day in the 30-day lookback and may include today. The app reports no blood-pressure trend, classification, target or interpretation.
  • Steps: a local-calendar-day HKStatisticsCollectionQueryDescriptor uses cumulativeSum. HealthKit resolves contributing sources; the app never manually sums raw iPhone and Watch samples. Apple documents that a statistics collection omits intervals with no matching samples, so the average is the sum of visible daily totals divided by sampled days, not every reporting day. Coverage always shows sampled days out of reporting days. A returned total of zero remains a visible sampled day; an absent statistic remains No data, not zero or proof that read access was denied.
  • Resting heart rate: the app obtains one HealthKit discreteAverage statistic for each complete calendar day, then calculates the arithmetic mean of valid daily values. Days without a visible value are omitted and days with more samples receive no extra weight. The selected period is compared with the immediately preceding period containing the same number of complete days. A signed bpm trend requires at least three valid days on each side.
  • HRV: the app uses the same daily-first and equivalent-period comparison with heartRateVariabilitySDNN, converted to milliseconds. A signed trend requires at least three valid days on each side. HRV is not presented as a readiness score or medical interpretation.
  • Apple Watch coverage: coverage is the number of complete reporting days containing at least one heart-rate sample whose HealthKit device metadata identifies an Apple Watch. Day membership is start-inclusive and end-exclusive, so a sample exactly at local midnight belongs only to the following day. Coverage shows evidence of Watch data on a day, not continuous wear time. An empty query is shown as No data because it may also mean heart-rate read access was denied.
  • Apple Exercise Time: one HealthKit cumulativeSum statistic covers the exact report interval and is converted to minutes. Raw samples are not summed manually.
  • Active energy: one HealthKit cumulativeSum statistic covers the exact report interval and is converted to kcal. This is an activity measurement, not total energy expenditure.
  • Workouts: the app reads HKWorkout samples whose start date is inside the report interval. It shows the count, summed duration, activity type, duration and local start time in dd/MM/yy - HH:mm format. Functional Strength Training is shortened to FST. A workout crossing midnight belongs to the day on which it started. An empty result is shown as No data because HealthKit does not distinguish missing read access from an empty history.
  • Sleep: only asleepUnspecified, asleepCore, asleepDeep and asleepREM samples are included. awake and inBed are excluded. Included intervals from all sources are clipped and combined so overlaps count once. Each report date is a local noon-to-noon night bucket ending on that wake date. Only nights with visible asleep time enter the average.
  • Medications on iOS 26 or later: the person chooses individual medications through Apple's medication access sheet. The app queries active and archived authorised concepts, then includes only HKMedicationDoseEvent samples with a taken status and a start time inside the selected completed-day period. Events are grouped by HealthKit's stable medication concept identifier, independently of query or display order, so a changed strength appears as a separate row and concepts with the same display name remain separate. When refreshes overlap, only the newest relevant full-report or medication-only refresh may publish medication state. Each row reports the latest logged quantity and time plus the number of taken events. Diagnostics lists every event. Medications without a visible taken event are omitted from copied text. Missing events are never treated as a missed dose or non-adherence.
  • Nutrition in Daily JSON Export: the app supports all 39 current HealthKit dietary quantity types through one fixed catalogue. It uses source-filtered HealthKit cumulativeSum statistics and converts energy to kcal, water to mL and nutrients to the catalogue's g, mg or mcg unit at the query boundary. Source discovery builds a complete local snapshot and replaces the previous snapshot atomically only after every query succeeds; concurrent source-filtered reads therefore see either the previous or the next complete selection map, while failure or cancellation preserves the previous map. The current schema v3 retains the nutrition payload introduced in schema v2: today's partial total through the captured cutoff and exactly seven chronological completed-day states per nutrient. Current and previous averages are arithmetic means over visible sampled days and state both sampled and reporting days. A signed current-minus-previous trend is available only with 7/7 visible days in both windows; otherwise it is insufficient_data. Missing source-filtered statistics remain no_data_or_access, never zero. Nutrition is not added to the weekly screen, copied report or Diagnostics and has no target, score or interpretation.
  • Private notes in Daily JSON Export: schema v3 always includes today.notes as an ordered array of strings, including [] when no notes are saved. Each string belongs to the envelope's reporting date and time zone. Local record identities and timestamps are not exported, and drafts never enter JSON. A preview freezes the saved-note revision alongside its HealthKit cutoff; later note changes invalidate it rather than being patched into reviewed bytes. Notes are user-authored context, not HealthKit data or medical interpretation, and are not added to the weekly screen, copied report or Developer Diagnostics.
  • On-device note dictation: the dedicated editor microphone uses the iOS 17 SFSpeechRecognizer live-audio path only when the active locale supports on-device recognition. Permission denial, restriction, unsupported locale/device and temporary unavailability leave typing available. A complete final transcript is appended once. If silence resets the live result, recognition fails, or explicit Stop produces an empty, incomplete or no final result, ordered recognised fragments are assembled once into a separate editable review candidate. Stop falls back after three seconds if Speech provides no terminal callback, and any later callback from that capture is ignored. A recovered or limit-rejected candidate blocks accidental editor dismissal until it is accepted or explicitly discarded; only acceptance changes the typed draft. Capture stops when the editor closes or the app backgrounds, and no audio artifact enters note storage or JSON.

Apple does not fully document the sleep source precedence used by the Health app. Combining overlapping asleep intervals is the closest transparent and defensible calculation available through documented HealthKit data.

Check the results against Apple Health

Daily Steps totals have been compared successfully with Apple Health on a real iPhone. A one-step difference can still appear in the final average when two interfaces round the same daily inputs differently.

For your own check, run a Debug build, select Last 7 Completed Days, and use the same dates and local time zone in both apps. Open Developer Diagnostics at the bottom of the report screen to see daily values and exact totals.

See the complete validation checklist
  1. Steps: compare every daily diagnostic value, distinguish a visible zero from No visible data, then average only the visible daily totals. Confirm the same sampled-day coverage appears on the report, copied text, Full Page document, Diagnostics and Daily JSON.
  2. Weight: compare the current and previous seven-day daily values. Today's partial day is excluded from averages, but the independent latest measurement can still be today.
  3. Waist: compare the latest measurement and timestamp with Health's Waist Circumference detail. For trend, confirm that Diagnostics selected the closest sample to 28 days earlier and that it is 21 to 35 days older than the latest sample.
  4. Blood glucose: first confirm that the sensor's samples appear in Health. Compare each daily diagnostic average and range with Health for the same complete day, then average the valid daily averages. Allow for vendor-to-Health synchronisation delay.
  5. VO₂ max: compare every raw diagnostic estimate and timestamp with Health's Cardio Fitness data. Recalculate the daily means, then compare the four-week, three-month and six-month windows. Confirm the sampled-day count before comparing rounded averages.
  6. Blood oxygen: compare each raw diagnostic value with Health, then independently calculate each completed day's median. Compare the median and range of those daily medians, not Health's raw-sample average or range. The latest value can be from today even though the period summary excludes today.
  7. Blood pressure: first let the monitor's companion app finish synchronising. In Health, open Search > Heart > Blood Pressure, then inspect the individual measurements for the same dates. In Diagnostics, confirm that every systolic/diastolic pair, timestamp and source matches one Health reading. Confirm that pre-14:00 readings enter Morning, readings from 17:00 enter Evening, and 14:00–16:59 readings appear only in the raw list. For each completed day and slot, average systolic and diastolic over the same paired readings. Then average those daily batch values across sampled days and compare the unrounded diagnostic result, sampled-day coverage and reading count. Finally confirm that the main-screen latest pair and latest batch timestamps can include today while the period averages do not.
  8. Resting heart rate and HRV: compare each valid day's diagnostic value with Health's daily view for the selected and immediately preceding equivalent periods. Average only the valid days.
  9. Active energy and exercise: compare the exact unrounded diagnostic totals over the selected dates before comparing rounded display values.
  10. Workouts: compare workout start dates, count and total duration.
  11. Sleep: compare each diagnostic night with the Health date on which you woke. If a night differs, check for overlapping third-party or manually entered records.
  12. Medications: compare every taken-event timestamp in Diagnostics with Health. Confirm that an unlogged medicine is absent and a changed strength appears as a separate row. Today's event enters the default report only after that day is complete.
  13. Daily notes: add, edit and delete invented text, then refresh the daily preview. Confirm today.notes matches the saved order exactly, a draft is absent, and any later saved-note change disables the old preview until refresh. On a separately authorised iPhone, test complete file protection with invented notes: lock during a pending draft save and after a prepared preview, confirm notes show temporary unavailability and export is disabled, then unlock and activate or tap Retry. Confirm the draft and last saved notes remain, the draft can be saved, and a new preview is required. Also verify the dedicated microphone in Airplane Mode for one supported locale, denial/restriction, interruption, backgrounding and editor dismissal; confirm typed and safely finalised text survives and that no audio file is retained.
  14. Tap Copy Report, paste it into Notes, and compare it with the screen. Diagnostics and daily notes are never included in copied text.

Simulator tests cover calendar boundaries, paired blood-pressure aggregation, daily-first averages, missing data, sleep overlap handling, workout totals, nutrition catalogue/schema semantics, date-bound note persistence and preview invalidation, synthetic speech state/transcript handling, formatting, clipboard output and the deterministic full-page screenshot document. A simulator cannot prove the native Full Page screenshot-editor flow, nutrition source visibility, provider coverage, iOS file-protection behaviour through a real lock cycle, representative personal HealthKit data or physical-device on-device speech behaviour and audio lifecycle, so those checks still require separately authorised iPhone testing.

CI also enforces unsigned Xcode static analysis, publishes layer-aware simulator coverage in GitHub Actions and sends app-target coverage to Codecov. The reproducible baseline, pure-domain regression gate, external disclosure boundary and runtime evidence are documented in CI static analysis and coverage.

Values can legitimately differ while Health or a sensor app is still synchronising, when historical read access is limited, when the selected dates differ, or because Apple has not documented part of its source precedence. Investigate material discrepancies through the daily and nightly diagnostics rather than hiding them through rounding.

Glucose, blood pressure and other health values are informational. The app provides no medical classification, interpretation, target or treatment advice and must not be used to make treatment decisions.

Development notes

DEVELOPMENT_NOTES.md records the Codex-assisted development experiment and its bounded token and API-equivalent cost estimates.

Licence

Licensed under the MIT License.

About

Privacy-first native iPhone utility for producing weekly summaries from Apple Health data.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages