uttrflow / uttrflow/uttrflow-swift

Insights counts words, apps and spoken days from the calendar day before its first bar, so the caption and list disagree with the chart

Open Beginner friendly
#722 0 comments 0 reactions 0 assignees View on GitHub
area:dictation bug good first issue P2
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## What happens

Insights filters the history with `HistoryPresenter.retained` (`Sources/UttrflowUX/InsightsPresentation.swift:155-156`), which keeps anything newer than `days × 86,400` seconds (`DictationRecord.survives`, `Sources/UttrflowHistory/DictationRecord.swift:54-57`). The chart then draws exactly `days` calendar days ending today (`bars`, `:211-213`). A window of N × 24 hours reaches back into one more calendar day than the chart has bars, so dictations from that day are:

- added to the caption's word total (`caption`, `:233`, `entries.totalWords`),
- counted in the "where the words went" list and its percentages (`places`, `:178`, `:297-322`),
- counted in pace and "Left as dictated" (`:176-177`),
- counted as a spoken day towards the seven needed before charting (`daysSpokenOn`, `:158`),

but appear in no bar and not in the average (`:285-294`).

Measured with a throwaway test over the Insights fixtures (now = 15 June 15:20, default 7-day retention): a week of entries of 10 words in one app, plus one entry of 10 words in a second app dated 6 days 20 hours earlier (8 June, 19:20):

| Figure | Expected (what the bars show) | Actual |
|---|---|---|
| Caption | `70 words · 9–15 June` | `80 words · 9–15 June` |
| Sum of bars | 70 | 70 |
| Places | first app 100% | first app 88%, second app 12% ("10 words") |

## Why it matters

The caption and the list contradict the chart right above them, and an app can be listed as a share of dictating with no bar in which that dictating happened. It happens every day for anyone who dictated in the evening a week ago.

## How to reproduce

In `Tests/UttrflowUXTests/InsightsPresentationTests.swift`, add to `HistoryFixture.aWeek()` one entry at `now - (6 days + 20 hours)` and check that `chartCaption` starts with the sum of `days.map(\.words)`, and that `places` has one app.

## Acceptance criteria

- Every figure on the charted page (caption total, places, pace, accuracy, and the days-spoken count) is computed from the same calendar days the bars show.
- The retention promise itself (`survives`) is unchanged; this is only what the page counts.
- A test pins the row above.

## Where to start

- `Sources/UttrflowUX/InsightsPresentation.swift:150-192`: filter `kept` to entries whose start of day is inside the bars' span before handing it to the figures.
- Related: #675 (when charting starts at all), #615 (weekday arithmetic).
- Run `make verify` (export `DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer` first) and read CONTRIBUTING.md.

**Size:** S, about an hour.

Contributor guide

Open the contributing guide

Research direction

Start in Sources/UttrflowUX/InsightsPresentation.swift:150-192 and review the bars and figure calculations. Add the boundary case to Tests/UttrflowUXTests/InsightsPresentationTests.swift using HistoryFixture.aWeek(), then run the focused tests or make verify. Done means the caption, places, pace, accuracy, and days-spoken count use the same calendar span as the bars while DictationRecord.survives remains unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
analytics
Issue type
Bug
Difficulty
2/5
Estimated time
Under an hour
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.