Skip to content

fix(F19+F20): strip UTF-8 BOM in read; bound interject channel - #91

Merged
yogthos merged 1 commit into
mainfrom
fix/f19-bom-strip
May 21, 2026
Merged

fix(F19+F20): strip UTF-8 BOM in read; bound interject channel#91
yogthos merged 1 commit into
mainfrom
fix/f19-bom-strip

Conversation

@yogthos

@yogthos yogthos commented May 21, 2026

Copy link
Copy Markdown
Collaborator

Track F-MEDIUM #19 (BOM strip in read) and #20 (mpsc::Sender(64) for interject channel with try_send). 2 new tests for F19, 681 pass.

Two F-MEDIUM fixes from ROADMAP.md.

## F19 — UTF-8 BOM strip

Old Windows-saved files start with U+FEFF (0xEF 0xBB 0xBF). Before
this, the BOM survived `read_line` and ended up as an invisible
prefix on the first line shown to the LLM. opencode's
`Bom.readFile()` does the same strip on its side.

`read.rs` line loop now tracks `first_line` and strips a leading
`'\u{FEFF}'` from line 1 only. Mid-file BOMs (rare but possible
when concatenating files) stay as regular chars.

## F20 — Bounded interject channel

`AgentRunner::interject_tx: mpsc::UnboundedSender<()>` could grow
without bound if the user hammered the interject keybind while
the runner was in a long LLM call. Each press allocated an entry
even though all but the first were redundant (the runner drains
via `try_recv()` after the first wakeup).

- Switch to `mpsc::Sender<()>` with capacity 64.
- UI uses `try_send(())` instead of `send(())`: if the channel is
  full, no-op (we already have a wakeup queued).
- Updated all 9 ownership transfer sites + the runner-side
  receiver type.

## Tests

F19: two new tests in `agent::tools::read::tests`:

- `read_strips_utf8_bom_from_first_line`: writes a file starting
  with `\u{FEFF}`, asserts the output has no BOM byte anywhere.
- `read_only_strips_bom_at_start_of_file`: BOM in line 2 stays
  intact — guards against the strip applying to wrong lines.

F20: no new tests (capacity-bound is a runtime contract; the
existing interjection-queue tests in ui already exercise the
try_send path).

681 pass (was 679). All build profiles clean.
@yogthos
yogthos merged commit 1bed2a5 into main May 21, 2026
1 check passed
@yogthos
yogthos deleted the fix/f19-bom-strip branch May 21, 2026 05:02
yogthos added a commit that referenced this pull request May 21, 2026
All actionable Track F items now landed:

- F-CRITICAL (PRs #76, #77): ACP perm asks routed to Deny, find/glob/list_dir hide dotfiles by default
- F-HIGH (PRs #78#84): compress aligns cut-point, read streams large files, ACP parallel tool ids, bash pgid cleanup, symlink canonicalize, session schema version, quote-aware bash splitter
- F-MEDIUM (PRs #85, #86, #87, #89, #90, #91): interleaved bash output, compress net-savings, Retry-After parsing, plugin docs, relative-path normalize, BOM strip, bounded interject channel
- F-SKIP (F9, F11, F15): verified false positives or N/A; rationale documented inline

Status legend updated; ordering recommendation replaced with the
shipped-status section.

Co-authored-by: Yogthos <yogthos@gmail.com>
allen-munsch pushed a commit to allen-munsch/dirge that referenced this pull request Jun 3, 2026
…-code#91)

Two F-MEDIUM fixes from ROADMAP.md.

## F19 — UTF-8 BOM strip

Old Windows-saved files start with U+FEFF (0xEF 0xBB 0xBF). Before
this, the BOM survived `read_line` and ended up as an invisible
prefix on the first line shown to the LLM. opencode's
`Bom.readFile()` does the same strip on its side.

`read.rs` line loop now tracks `first_line` and strips a leading
`'\u{FEFF}'` from line 1 only. Mid-file BOMs (rare but possible
when concatenating files) stay as regular chars.

## F20 — Bounded interject channel

`AgentRunner::interject_tx: mpsc::UnboundedSender<()>` could grow
without bound if the user hammered the interject keybind while
the runner was in a long LLM call. Each press allocated an entry
even though all but the first were redundant (the runner drains
via `try_recv()` after the first wakeup).

- Switch to `mpsc::Sender<()>` with capacity 64.
- UI uses `try_send(())` instead of `send(())`: if the channel is
  full, no-op (we already have a wakeup queued).
- Updated all 9 ownership transfer sites + the runner-side
  receiver type.

## Tests

F19: two new tests in `agent::tools::read::tests`:

- `read_strips_utf8_bom_from_first_line`: writes a file starting
  with `\u{FEFF}`, asserts the output has no BOM byte anywhere.
- `read_only_strips_bom_at_start_of_file`: BOM in line 2 stays
  intact — guards against the strip applying to wrong lines.

F20: no new tests (capacity-bound is a runtime contract; the
existing interjection-queue tests in ui already exercise the
try_send path).

681 pass (was 679). All build profiles clean.

Co-authored-by: Yogthos <yogthos@gmail.com>
allen-munsch pushed a commit to allen-munsch/dirge that referenced this pull request Jun 3, 2026
…irge-code#92)

All actionable Track F items now landed:

- F-CRITICAL (PRs dirge-code#76, dirge-code#77): ACP perm asks routed to Deny, find/glob/list_dir hide dotfiles by default
- F-HIGH (PRs dirge-code#78dirge-code#84): compress aligns cut-point, read streams large files, ACP parallel tool ids, bash pgid cleanup, symlink canonicalize, session schema version, quote-aware bash splitter
- F-MEDIUM (PRs dirge-code#85, dirge-code#86, dirge-code#87, dirge-code#89, dirge-code#90, dirge-code#91): interleaved bash output, compress net-savings, Retry-After parsing, plugin docs, relative-path normalize, BOM strip, bounded interject channel
- F-SKIP (F9, F11, F15): verified false positives or N/A; rationale documented inline

Status legend updated; ordering recommendation replaced with the
shipped-status section.

Co-authored-by: Yogthos <yogthos@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant