@@ -72,6 +72,19 @@ Grouped by arc. One line per capability; the tag is where it landed.
7272 switcher, settings overlay, LSP-ordered completions) and the
7373 ` multi-select ` component completing the form-input family.
7474
75+ ### Unreleased (on main, not yet tagged)
76+
77+ - Completion type-to-filter (` a128fa0 ` ): typing an identifier rune while
78+ the completion popup is open now narrows the visible list live against
79+ the trailing word prefix (case-insensitive subsequence, so "wg" keeps
80+ "WaitGroup") instead of dismissing the popup. Backspace widens back
81+ without a fresh server round-trip; deleting the whole prefix or typing a
82+ non-identifier rune dismisses and falls through to the buffer. This is
83+ the Zed/VSCode contract. ` complete.Popup ` retains the full sorted server
84+ set (` all ` ) so ` Narrow ` can widen without re-querying; the host arms a
85+ ` completeNarrowPending ` flag on the keystroke, lets the rune reach the
86+ buffer, then recomputes ` WordPrefix ` from the live line and narrows.
87+
7588## Standing constraints (do not regress)
7689
7790These are operator-stated DNA. They override convenience.
@@ -91,6 +104,23 @@ These are operator-stated DNA. They override convenience.
91104 components in v0.48.0 had to backfill entries into the release commit
92105 because they didn't; toggle did it right.
93106
107+ ## Harness note: host-view slices are testable headless
108+
109+ A recurring miscall in this file was tagging keystroke-routing plus
110+ live-render work as "wants a visual loop, not a blind hour." The
111+ completion type-to-filter slice disproved the blanket version of that:
112+ the host model is fully drivable in a unit test. ` newModel(dir) ` (or
113+ ` fixtureRepo(t) ` + ` newModel(root) ` ), set ` width ` /` height ` , ` m.resize() ` ,
114+ ` openBufferForTest(t, m, "a.go") ` , then feed ` m.Update(tea.KeyMsg{...}) `
115+ and assert on ` m.View() ` — the full rendered frame — or on sub-pane
116+ state. The narrow tests check exactly this: type 'i', assert the popup
117+ survives and the frame drops the filtered-out item. So a live-render
118+ change is a blind hour only when the thing being rendered is invisible to
119+ ` stripANSI ` assertions — the matched-highlight ANSI-bleed case above, or
120+ anything whose correctness is a color/background composition. Structural
121+ render changes (which rows appear, what text they carry) are verifiable
122+ headless; reach for the harness before deferring to a visual loop.
123+
94124## Release ritual (reusable)
95125
961261 . Release commit updating ` CHANGELOG.md ` (move ` [Unreleased] ` into the
@@ -132,12 +162,19 @@ shipped, so the remaining surface is narrower than it once was.
132162- ** Settings/themes surface** — config inheritance and theme hot-reload
133163 ship; a discoverable settings UI on top does not yet.
134164- ** Depth passes on shipped panes** — diagnostics presentation and
135- multibuffer ergonomics are each self-contained slices. Completion has a
136- concrete gap: the popup sorts by LSP SortText but has no type-to-filter
137- — typing any rune while it is open dismisses it (main.go, the "any
138- other key" branch) rather than narrowing the list live the way Zed and
139- VSCode do. Closing that is a host keystroke-routing plus live-render
140- change, so it wants a visual loop, not a blind hour.
165+ multibuffer ergonomics are each self-contained slices. Completion's
166+ type-to-filter gap is now closed (see Unreleased above). The next
167+ completion slice is ** matched-character highlighting** : bold or accent
168+ the runes in each label that the current prefix matched, the way Zed
169+ underlines the fuzzy hits. That one genuinely wants a visual loop, and
170+ for a specific reason — the row already renders through a lipgloss style
171+ that sets a ` Background ` (` rowStyle ` uses ` Surface ` , ` selStyle ` uses
172+ ` Primary ` ). Embedding a per-rune inner style inside that line emits an
173+ ANSI reset mid-line that clears the outer background for the rest of the
174+ row, a bleed a ` stripANSI ` -based headless test cannot see. The correct
175+ build composes the highlight into the same style pass (or pre-segments
176+ the row so no inner reset lands before the background is re-applied) and
177+ eyeballs the rendered frame. Do not ship it blind.
141178
142179Pick the smallest finishable slice that advances parity; one capability,
143180its tests, its CHANGELOG line, one commit.
0 commit comments