uttrflow / uttrflow/uttrflow-swift

A terminal is formatted as a code editor, so a dictated line break reaches the shell and can run a half-finished command

Open
#612 0 comments 0 reactions 0 assignees View on GitHub
area:dictation bug needs-info P2
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## What happens

`AppKind.terminal` resolves to `.codeEditor` (`Sources/UttrflowCore/Models/AppKind.swift:17`). The code editor's formatter keeps line breaks as given:

```swift
// Sources/UttrflowCore/Models/DestinationFormatter.swift:131-134
.codeEditor: DestinationFormatter(
destination: .codeEditor, firstWord: .fromInsertionPoint, terminalStop: .never,
layout: .preserveNewlines, ...
```

`LayoutPolicy.preserveNewlines` is documented as "Line breaks are kept as given … as dictated code wants" (`DestinationFormatter.swift:82-83`). In an editor a newline is a new line. At an interactive shell prompt a newline is Return: everything before it is run.

A dictation reaches the terminal with a line break in several ways:

- the user says "new line" or "new paragraph" part-way through a command, meaning a visual break;
- the tidy step keeps any break the recogniser or the model produced, since `.preserveNewlines` is the policy.

Then it is inserted in one of two ways:

- **By the Accessibility write**, if the terminal accepts one. That is character input, so the shell's bracketed-paste protection never applies.
- **By the paste.** A shell with bracketed paste holds the text for review. The shell that ships as `/bin/bash` on macOS, many TUIs and REPLs, and remote shells over SSH may not have it on.

Nothing on either path collapses or refuses a line break for a terminal.

## Why it matters

In a terminal, a partial command running is not a formatting slip. `git reset --hard` followed by a break and the rest of a thought runs the first line.

## Needs a product decision

Pick one:

- **(a)** Terminals get their own formatter with `.singleLine`.
- **(b)** A dictation holding a line break into a terminal is inserted with the breaks replaced by spaces, and the user is told.
- **(c)** Multi-line dictation into a terminal is left on the clipboard with a notice.

## How to reproduce

Needs a real terminal (`help wanted` for the insertion half):

1. At a shell prompt without bracketed paste (for example `bash --norc` using the system bash), dictate "echo one new line echo two".
2. Record whether `echo one` runs before you press Return, and which insertion route `uttrflow-dev insert` takes in that terminal (`--via accessibility` versus `--via paste`).

The formatting half can be checked without a terminal: `uttrflow-dev clean --bundle-identifier …` on text holding a break.

## Acceptance criteria

- The chosen policy is a value in `DestinationFormatter.registry` (or a new `Destination`), not a special case in an insertion engine, so both the rules path and the model path read it (#231).
- Corpus cases in `Sources/UttrflowEval/EvaluationCorpus.swift` pin that a spoken break into a terminal never produces `\n` in the inserted text.

Contributor guide

Open the contributing guide

Research direction

Start with AppKind.swift:17 and the formatter entries in DestinationFormatter.swift:82-83 and 131-134, then inspect the terminal identifier in DestinationRules.swift:35. Check the insertion route with the provided clean and insert commands. Done means the chosen terminal policy is represented in the formatter registry or a new Destination, and EvaluationCorpus.swift cases show dictated breaks never produce newline characters.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, swift
Domain
accessibility, cli, desktop-dev
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.