uttrflow / uttrflow/uttrflow-swift

[P2] Recognize CRLF and CR line endings when determining caret sentence state

Open
#822 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## Problem

`InsertionPoint.sentenceState(before:)` treats a caret on a fresh line after CRLF or CR as mid-sentence. The real rules transformer consequently lowercases the first dictated word. Equivalent LF context starts the sentence correctly.

## Verified reproduction

On main `5c310667cd35c44abd8bbd26c19b0905471287b4`, supply an English transcription of `the migration finished overnight` to `RuleBasedTransformer` with an `AppContext` using the document destination (`com.apple.Notes`) and preceding text `previous line` followed by the tested newline.

Actual production results:

| Preceding line ending | Sentence state | Transformed text |
| --- | --- | --- |
| LF | startOfSentence | The migration finished overnight. |
| CRLF | midSentence | the migration finished overnight. |
| CR | midSentence | the migration finished overnight. |

The isolated regression asserts `.startOfSentence` and the capitalized result for all three. LF passes; CRLF and CR each fail both assertions. This exercises the actual Core value and complete rules transformer, with synthetic context and transcription. No live Accessibility delivery or actual speech recognition is claimed.

## Cause and path

- [InsertionPoint.swift:39](https://github.com/uttrflow/uttrflow-swift/blob/5c310667cd35c44abd8bbd26c19b0905471287b4/Sources/UttrflowCore/Models/InsertionPoint.swift#L39) splits only on the LF `Character`. Swift treats CRLF as one `Character`; neither CRLF nor CR is split here. Removing trailing whitespace then exposes the previous line's last word instead of an empty current line.
- [FirstWordPass.swift:61](https://github.com/uttrflow/uttrflow-swift/blob/5c310667cd35c44abd8bbd26c19b0905471287b4/Sources/UttrflowAI/Passes/FirstWordPass.swift#L61) uses that `.midSentence` state to lowercase the first word.
- `MacContextEngine+System.read` obtains the field value and selected range and passes them through `CaretText.around`, which preserves the text's line endings. Thus a field that exposes CRLF in its Accessibility value can supply this input; the issue does not assume every editor does so.

## Acceptance criteria

Determine the current line using supported newline characters, treating CRLF as one boundary. Preserve the existing list/heading marker and mid-sentence behavior. Add LF, CRLF and CR cases both for a bare line break and a marker on the new line, including an end-to-end rules-transformer capitalization assertion.

## Related work

Checked open and closed issues and open PRs. Closed #204 addressed opening markers; this is the newline-boundary case in the current implementation. #803 concerns clipboard diffs, #814 concerns model-response cleanup, and #789 concerns suggestion surroundings. None covers caret sentence detection.

Contributor guide

Open the contributing guide

Research direction

Start in Sources/UttrflowCore/Models/InsertionPoint.swift at sentenceState(before:) and compare its newline handling with the behavior described for LF, CRLF, and CR. Review Sources/UttrflowAI/Passes/FirstWordPass.swift to understand the capitalization outcome, then run or extend the isolated regression and end-to-end rules-transformer checks. Done means bare breaks and new-line markers preserve the expected sentence state and capitalization without changing existing marker or mid-sentence behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
desktop, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
85/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.