Milestones
List view
The 0.8.0 audit. Every issue here was found by driving termlens 0.8.0 under a real PTY, reproduced against the 0.8.0 release worktree, and re-checked by an independent pass before filing — each carries its own transcript, and where the second pass corrected the first the correction is in the issue rather than in a comment. The theme is the silent pass. A required MSRV gate that has never once compiled at the MSRV; two policy scripts that report OK on a commit range git could not read; a matcher that finds text the screen does not contain; an emulator thread that dies on an 80x1 terminal while cargo prints 'ok'; a README example that blesses a torn snapshot; invalid bytes that leave no trace and shift every column after them. Around those sit the places the crate disagrees with itself — find's rustdoc against contains, DESIGN rule 5 against convert_cell, current_dir's rustdoc against portable-pty's fallback, rect_text's axis-order warning against five column-first mouse APIs. Cheap to fix, easy to leave, and each one currently teaches a reader something false. Design bar: no issue closes on a doc edit alone where a test could pin the behaviour instead; every behaviour change names the option it chose and says why the others stay open; every coverage gap names the CI job that would have caught it. Where a document is wrong, the document changes even if the behaviour does not. Out of scope for this milestone, deferred rather than dropped: a frame barrier or wait_frame_after (wait_frame's documentation fix lands here, the API does not); a Signal-typed or numeric exit accessor; modelling bold+faint as separate bits, which belongs with the open #150 shadow-parser question; changing the mouse APIs' argument order, which is breaking; running the default feature set on the macOS leg; propagating the child's status through the inspect example's exit code; and Windows (#149). Two issues carry a behaviour half that may reasonably slip past this release — find/contains trailing padding, and the default working directory — but their documentation halves may not.
No due date•18/18 issues closedScrollback stops being a transcript. Reproduced against 0.6.0. v0.4 added history because an application that hands finished output *back* to the terminal — a pager, a log view, a TUI that commits completed blocks and keeps a small live region — otherwise ceases to exist the moment it scrolls. What v0.4 added was text: a scrolled-off row has no styles, no cell addressing, and is not reflowed by a resize. That costs more than convenience. v0.4's own headline was that a masked-password test must fail against an application that prints the secret in clear, and on the visible grid it does — at the price of a second full parse of every byte. The moment that row scrolls off, the same assertion silently degrades to text-only: `full_text()` still finds the secret, and whether it was *masked* becomes unanswerable. For precisely the subjects history was added for, the security-relevant assertion evaporates as the screen fills. Design bar: history is bounded and must stay bounded, and the cost of a snapshot is load-bearing — it is taken on every wait evaluation, which is why history is shared `Arc<str>` rows today. Styles in history must not make a snapshot O(history). Alongside that, three small items carried here because they are good places to start rather than because they share the theme — the same way v0.7 carried `Key::Insert` and the `#[non_exhaustive]` change. All three were reproduced against 0.7.0: a mouse wheel cannot carry a modifier, so `Ctrl`-wheel zoom is untestable; a rejected terminal size is reported as "input not receivable", which describes something else entirely; and mouse coordinates are never checked against the grid, where `u16::MAX` panics in debug and silently reports column 0 in release.
No due date•22/22 issues closedWhat a `Screen` still cannot say. Every item reproduced against the 0.6.0 release rather than inferred from reading the source. The arc since v0.4 has been closing one gap repeatedly: behaviour that leaves the grid identical and is therefore invisible to every content predicate — repaints, bells, `OSC 52`, focus events, and in 0.6 inline graphics. Two ordinary things a modern TUI does are still missing from it. An `OSC 8` hyperlink renders its label and puts its URL nowhere on the snapshot, so "did it link the right place?" is unanswerable and a test asserting a link passes identically against an application that emitted none. The cursor's *shape* — what an editor switches to a bar for insert mode — is not reported by `cursor()`, which returns position and visibility only. Plus one defect the feature matrix hid rather than found: the crate does not compile with its default features off, a configuration the README explicitly offers, because no CI job has ever built it. Design bar, unchanged from v0.2: extend `Screen` before inventing new types; a fact is captured only where a real terminal would hold it; nothing is guessed, and anything unanswerable is named rather than invented. Out of scope as inherent: stdout and stderr are one stream.
No due date•6/6 issues closedThe gaps that remain after v0.4.0, every one reproduced against the 0.4.0 release rather than carried forward from an older study. Most were found by applying termlens 0.4.0 to a real subject end to end — xai-org/grok-build's pager, driven in a PTY through 12 passing tests. v0.4 cleared the three blockers that made that subject untestable; what is left is what its own harness still does things termlens cannot. **Observability a real harness needs** — a frame counter, per-frame timing, graphics detection. grok asserts that a wheel burst does not amplify frames and gates CI on p99 frame time; termlens publishes frames but never counts or times them. **Queries and events still unanswerable** — XTGETTCAP, focus events (mode 1004), BEL. **Fidelity** — needle matching is codepoint-exact, so an NFC needle misses NFD text a terminal draws identically; a drag emits one motion event where a terminal emits one per cell crossed. **Robustness and API consistency** — send/send_str/paste cannot fail while click/drag/scroll return Result; no upper size bound (5000x5000 is accepted and costs 15.6s on the first wait); query replies are still dropped past REPLY_QUEUE_DEPTH=64; no send_after for the Esc/Alt wire ambiguity; two small papercuts in rect_text and signalled exit status. Considered and excluded: HTML/styled-JSON export (with_styles already covers style regressions; HTML is an artifact concern, not a testing capability). Out of scope as inherent: stdout and stderr are one stream; Unix only.
No due date•17/17 issues closedWhat termlens cannot do, and where it quietly does the wrong thing. **Blockers** (#80–#82) — each makes a whole category of subject untestable. Found by testing against a real hard subject (xai-org/grok-build, a Rust TUI coding agent whose own harness had to build all three): no scrollback, so content an app hands back to the terminal ceases to exist; no strikethrough/blink/conceal, so a masked-password test passes against an app that prints the secret in clear; no OSC 52 capture, so "did it copy the right thing?" is unanswerable. **Defects found by adversarially probing 0.3.0** (#83–#86) — every one reproduced against the release commit, never inferred from reading the source. Two of them undercut the frame guarantee that is the crate's headline: `wait_frame` matches frames from before the call and never consumes them, and `screen()` is torn mid-frame even for an application that brackets every repaint. One is a self-inflicted loop where DECRQM tells an app the mouse modes are unsupported and `click()` then blames the app. One lets a stray `?2026l` in an ordinary defensive reset suppress the diagnosis that tells you to use `wait_until`. Reproducers: ~/termlens-probes-0.3.0 (diagnostic printers; converting each into a failing regression test belongs in the PR that fixes it). Deferred to a later milestone: XTGETTCAP, focus events, BEL, NFC/NFD needle matching, send_after, an upper size bound, reply backpressure past REPLY_QUEUE_DEPTH=64, send/paste/click returning Result. Out of scope as inherent: stdout and stderr are one stream; Unix only.
No due date•17/17 issues closedFrames, mouse, and honest diagnostics. The coverage study's three ranked asks (per-call timeouts on wait_frame/wait_idle, a fuller mouse API, frame history), plus query-recognizer gaps found probing 0.2.0 - including answering DECRQM, which unblocks applications that gate synchronized output behind a probe - a configurable OSC 10 answer, and a deadline on user writes so a child that stops reading its input fails instead of hanging.
No due date•6/6 issues closedCorrectness patch. Cases where the harness silently does the wrong thing, panics inside a dependency, or hangs itself: a self-inflicted drain deadlock, zero-size panics, silent current_dir fallback, paste fidelity (terminator and newline), misattributed query diagnostics, and mouse bytes a 1005 application cannot parse. A test harness must fail loudly, never quietly run the wrong test.
No due date•9/9 issues closedTheme: the emulator already knows the terminal's modes — v0.2 uses that knowledge on the input path and exposes it on the output path, so tests get easier to write and impossible to write flakily. Scope comes from the verified coverage study in vyncint/termlens-demo (docs/TERMLENS-COVERAGE.md): 12 real gaps, each pinned by a passing test in tests/limits.rs. Design bar for every item (non-negotiable): - User experience first: the obvious call must be the correct call. - Zero-config defaults: mode-aware behavior and the query responder are ON by default, like a real terminal. - Minimalism: extend existing types (Key, Screen, TerminalBuilder) before inventing new ones; no options nobody asked for. - Definition of done: the matching pinning test in termlens-demo tests/limits.rs flips from documenting the workaround to asserting the feature; DESIGN.md updated in the same PR; stress-gated if it touches wait paths.
No due date•11/11 issues closed