Skip to content

fix(copy): write counts of one in the singular across the app (#7913) - #8055

Open
tnalbant wants to merge 2 commits into
uttrflow:mainfrom
tnalbant:fix/7913-counts-of-one
Open

tnalbant wants to merge 2 commits into
uttrflow:mainfrom
tnalbant:fix/7913-counts-of-one

Conversation

@tnalbant

@tnalbant tnalbant commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What this changes, and why

Six user-visible counts were written with a plural noun. Each now reads the singular at exactly one:

  • the panel's whitespace row: Whitespace only · 1 character (Clip.swift)
  • the Insights range label: 1 word · 16 October, and the coverage line: Dictated on 1 of 1 day shown. (InsightsPresentation.swift)
  • three Diagnostics counters: 0 of 1 piece, 0 of 1 segment, 0 of 1 dictation (DiagnosticsPresentation.swift)
  • the typing-stopped error: Typing stopped after 0 of 1 character. (TextInsertionError.swift)

The obvious inline fix (count == 1 ? "character" : "characters" at each site) would have repeated the same ternary in six files across three modules, and UttrflowClipboard and UttrflowCore cannot import UttrflowUX where the existing MainFormatting.count lives. So CountedNoun goes into UttrflowCore — of(_:singular:plural:) for the noun alone and count(_:singular:plural:) for the number with it — and MainFormatting.count now delegates to it, so the surfaces cannot drift apart again.

The noun follows the number the sentence actually prints: the Insights coverage line counts reachable days, so 1 of 2 days shown stays plural, and 1 of 1 day shown does not.

How you know it works

Unit cases added, one per surface: CountedNounTests (new file), a ClipTests case at one and two spaces, InsightsPresenter.caption and .coverage at a count of one and of two, and DiagnosticsPresenter.decodingRows / .segmentRows at a single piece and a single segment (both also at the plural stay unchanged).

The test suite did not run on my machine, and I have not ticked make verify below. swift test cannot build the test bundle here, on two failures that are present on a clean checkout of main and in files this change does not touch:

  • Tests/UttrflowClipboardTests/SecretShapesMutationTests.swift and SecretShapesOracleTests.swift: the compiler is unable to type-check this expression in reasonable time
  • Tests/UttrflowInputTests/SuggestionAcceptorTests.swift: the compiler crashes while emitting SIL for insertRefusesWhenCancelled

Both are Swift 6.4 / macOS 27 toolchain behaviour; CI runs macos-26. Moving those files aside does not help, because other tests in the same target use helpers they define.

What did run locally:

swift build --target UttrflowCore        → 0 errors
swift build --target UttrflowClipboard   → 0 errors
swift build --target UttrflowUX          → Build complete
swift build --target UttrflowCoreTests   → Build complete
swift build --target UttrflowUXTests     → Build complete
make lint                                → clean (LineLength/formatting fixed with make format first)
make comment-audit                       → 0 multi-line blocks, baseline unchanged
make verify-static                       → green (includes public-api-audit after the baseline update below)

So the new test files compile, but they have not executed anywhere yet: in .github/workflows/ci.yml a pull request runs the static job only (make verify = verify-static), and the full gate (make verify (full): build, unit tests, coverage, offline audit) runs on workflow_dispatch. A maintainer running it will be the first execution; if it fails there, it is mine to fix.

The change adds one public type and two public functions to UttrflowCore, so Scripts/public_api_baseline.json records them (enum CountedNoun: 1, func count: 2, func of: 7) — the second commit is that line, so the audit reviews the delta instead of failing on it.


  • make verify passes locally — the static half does (make verify-static is green here, and the make verify job is green on this head); the build the other half needs cannot complete on this machine (lint, PII audit, build, tests, coverage floor, offline audit) — see above: build and tests cannot run on this machine, lint and the comment audit do pass
  • New behaviour has a test, or there is a reason in the PR why it cannot
  • No real email address, postal address or personal data in fixtures — no fixtures added
  • Comments are one line, present tense, and describe what the code does now
  • A latency claim says where its clock starts and stops — no latency claim here

Drafted with an AI coding assistant (OpenCode Go, deepseek-v4.1-flash) and reviewed against the issue's expected strings; the runs quoted above are from this branch.

Fixes #7913

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@naveen-bhatt naveen-bhatt added the bug Something isn't working label Oct 21, 2026
@tnalbant
tnalbant force-pushed the fix/7913-counts-of-one branch from c0483ba to 7d7a4c0 Compare October 21, 2026 21:44

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@tnalbant
tnalbant force-pushed the fix/7913-counts-of-one branch from 7d7a4c0 to 7433283 Compare October 31, 2026 22:18
Several user-visible counts were written with a plural noun: the panel's
whitespace row ("1 characters"), a formatted-text row, the Insights range label
("1 words") and its coverage line ("1 of 1 days shown"), three Diagnostics
counters, and the typing-stopped error ("0 of 1 characters").

Add CountedNoun to UttrflowCore — the modules that need it cannot import
UttrflowUX — and route each site through it. MainFormatting.count now delegates
to the same helper so every surface writes the same words.

- Sources/UttrflowCore/Support/CountedNoun.swift: the noun, and the count with it
- Sources/UttrflowCore/Errors/TextInsertionError.swift, Sources/UttrflowClipboard/Clip.swift:
  the two sites outside UttrflowUX
- Sources/UttrflowUX/{MainPresentation,PanelPresenter+RowProjection,InsightsPresentation,
  DiagnosticsPresentation}.swift: the five sites inside it
- Tests: CountedNounTests, a clip case, and the Insights/Diagnostics cases at a count of one

Refs uttrflow#7913
The new public helper adds a type and two functions to UttrflowCore, so the
baseline rises by one each and the audit can review the delta instead of
failing on it.

Refs uttrflow#7913
@tnalbant
tnalbant force-pushed the fix/7913-counts-of-one branch from 7433283 to 453501d Compare November 6, 2026 16:45
@tnalbant

tnalbant commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main (8483081, release 26.1106.0). Two things changed in the rebase.

The formatted-text row is gone. PanelPresenter.measurements no longer renders a rich-text row on main: upstream removed that branch, so the surface this PR fixed there no longer exists. I dropped that half of the change and the test that went with it rather than keep a call into a row nothing shows. Six surfaces remain: the whitespace row, the Insights range label and its coverage line, the three Diagnostics counters, and the typing-stopped sentence.

The baseline was re-recorded by the repo's own tool. Scripts/public_api_audit.py --update --after-merge writes the three declarations CountedNoun adds (the enum, and the count and of overloads), so Scripts/public_api_baseline.json shows 9073 -> 9076 in the diff instead of failing the audit.

Local evidence on this Mac:

  • swift build --target UttrflowUX builds.
  • swift build --target UttrflowCoreTests builds, and running UttrflowCoreTests.xctest executes 1219 tests in 175 suites with the new CountedNoun suite passing. The 18 issues that run reports are all TimestampsTests (Yesterday 4:14 PM, Wed, 1 Jul at 12:46 PM), in a file this change does not touch.
  • swift build --target UttrflowUXTests and swift build --target UttrflowClipboardTests still cannot build here: the first stops on Sources/UttrflowAI/AppleFoundationCleanupModel.swift:19 (GenerationOptions(sampling:) is deprecated against the macOS 27 SDK and the target compiles with warnings as errors), the second on a type-check budget failure inside a @Test macro. Both fail on a clean main on this machine too.

So the Insights and Diagnostics unit cases are unverified locally; CI is the gate for those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Counts of one are written as plurals: "1 characters", "1 of 1 days shown", "0 of 1 dictations", "1 words"

2 participants