Research — DropTerm’s decision records
Every non-trivial DropTerm feature started as a research record in this directory: a peer survey with the evidence, a recommendation graded by precedent, and the alternatives that were rejected and why. The records are the project’s ADRs — this index is their status layer.
The rules
- Records are immutable. A record captures what was known and decided on its date; it is never edited to match later reality. When a decision is reversed, a new record supersedes the old one and both stay.
- Status lives here, not in the records. The table below is the only place that tracks whether a verdict shipped, stalled, or was overtaken — the records’ “What DropTerm has today” sections are period snapshots and are allowed to go stale.
- A new record follows the house format: a question for a title, a date, a TL;DR with the verdict in the first sentence, numbered findings with line-level citations into the surveyed sources, a “what DropTerm has today” grounding section, a recommendation with rejected alternatives spelled out, and sources pinned by repo, commit, and fetch date. Add its row here when the verdict lands.
Decision log
Ordered by record date. “Shipped as” names the code or doc that carries the verdict today.
| Record | Date | Verdict | Status | Shipped as |
|---|---|---|---|---|
| panel-visibility | 2026-10-01 | The panel can stay visible beside the overlay: an exclusive zone of 0 reserves space, so a respect_panel config knob beats forcing layer: Top (rejected — doesn’t achieve the goal) |
Shipped | respect_panel key + the Behavior toggle (src/config.rs, src/settings.rs) |
| terminal-de-integration | 2026-10-02 | How drop-down terminals integrate with the desktop, and what fits COSMIC: desktop notifications, single-instance D-Bus, and cwd inheritance in; shell-integration injection, OSC 133, portals, and Flatpak out — the 13-entry rejection ledger | Shipped (the seeded parts) | src/notify.rs, src/dbus_state.rs, new-tab cwd inheritance; the narrower records below descend from it |
| settings-trigger | 2026-10-02 | The right-click context menu carries the “Settings…” item; gear and grab-bar buttons rejected; preferences-system is the icon that actually exists in Pop’s theme |
Shipped | src/context_menu.rs |
| terminal-theming | 2026-10-02 | Color schemes live in config as a named registry (not directory-scanned), the Application-theme pin drives light/dark, and the per-scheme licensing audit governs what may ship; terminal-colors.d(5) ruled out |
Shipped | src/terminal/theme_source.rs, Theming |
| settings-sidebar | 2026-10-03 | cosmic-term’s settings UI is a libcosmic context drawer, not a sidebar widget; DropTerm adopts the overlay drawer (side-by-side rejected — it would resize the PTY on every open) and deletes the second window | Shipped | src/settings.rs, the drawer in src/app.rs, Settings drawer |
| remote-control-commands | 2026-10-03 | Fire-and-forget tab verbs over the single-instance seam; move-tab and query verbs rejected — the seam structurally cannot offer replies | Shipped (a superset) | ToggleAction in src/app/remote.rs, CLI reference |
| v3-panel-applet | 2026-10-03 | An out-of-process COSMIC panel applet (desktop-file discovery, read-only D-Bus state) over an SNI tray icon; a dedicated crate dodges wgpu feature unification on panel surfaces | Shipped | applet/ crate, src/dbus_state.rs, Applet |
| tab-title-generation | 2026-10-04 | A tab_title_mode enum over a template mini-language (rejected as overkill); a user rename wins in every mode, and an empty report resets the title |
Shipped (a superset) | TabTitleMode in src/config.rs — five modes, Profile beyond the recommended three |
| settings-tabs | 2026-10-05 | The drawer navigates by libcosmic segmented_button tabs; vertical nav, segmented controls, context pages, and reusing the tab strip were all rejected; src/settings.rs stays one file |
Shipped (grown to five tabs) | SettingsTab pages in src/settings.rs |
| terminal-profile-settings | 2026-10-05 | Profiles take the named-model core from Windows Terminal and iTerm2 without GUIDs; GNOME Terminal’s inherit-on-new-tab default is a known fork, deliberately not adopted | Shipped | src/profile.rs, the Profiles tab in src/settings.rs |
| tab-context-menu | 2026-10-08 | A six-item per-tab menu graded by peer precedent; terminal-scoped verbs excluded (zero precedents), Pin kept as the one extension beyond the peer norm | Shipped | the per-tab menu in src/tab_bar.rs |
| packaging-and-release | 2026-10-10 | Native deb/AUR/nix following the System76 release convention; Flathub for the applet only — the main app is blocked until COSMIC exposes layer-shell to sandboxes; cargo-dist rejected as wrong-shaped | Withdrawn (flatpak leg, 2026-11-09 — the store listing offered less than the native install; the record and its layer-shell negative result stand) | the GitHub-release path (just release, release.yml) |
| status-bar-ux | 2026-10-11 | Keep the glance bar and its fixed height; resist CPU/memory/network segments; never auto-hide, but degrade gracefully per segment | Shipped — iterating | src/status_bar.rs |
| terminal-autocomplete | 2026-10-17 | Terminal-side fish-style history ghost text: the tcgetpgrp idle check detects the prompt (no OSC, no injection), per-tab history scraped from the grid feeds prefix suggestions, a dim overlay in draw() renders them, and acceptance writes the suffix through input_no_scroll; Warp-style input-editor replacement, shell-emits-candidates protocols, and a vte [patch] for OSC 133 all rejected (Ghostty/kitty “completions” premises corrected — neither has the feature) |
Shipped — stage 1 of the provider seam (paths from the filesystem, command names from the spawn-time $PATH behind the same shell gate); the 2026-10-21 pass added the history seed (spawn-time read of the shell’s own histfile), common-prefix path completion, and the single-quote escape tier; stage 2’s flag-specs module shipped 2026-10-22 (the curated subcommand/long-flag table for git/cargo/docker/systemctl/npm, the fourth provider behind the same shell gate), and its ghost-fit module shipped the same day (fish’s clip: … at fit-minus-two, nothing drawn below three free columns, the accept always whole) — stage 2 complete |
src/terminal/suggest.rs |
| status-bar-capability | 2026-10-17 | The band’s next tier is command lifecycle (live elapsed while running, frozen duration after finish) from the tcgetpgrp transition machine suggest.rs already runs, plus a scroll-position chip, an ssh-destination stand-in for the path, and selection idioms; every OSC-fed segment (133 D exit codes, 9;4 progress, 7 remote cwd, 7501 status) is blocked by the alacritty_terminal event seam — rejected until upstream grows an OSC passthrough (the named revisit trigger) |
In progress — the tier shipped whole: command-lifecycle, command-notify, and the three band modules (status-hover/-activity/-exit, 2026-11-03); the record’s named revisit trigger fired via the status-exit forks, and initiative 6 opened the OSC-fed tier on it — the tier complete: osc7-cwd (OSC 7 remote cwd) and osc94-progress (OSC 9;4 progress chip) shipped 2026-11-04, osc7501-status (OSC 7501 program status on the disc and name) shipped 2026-11-06, its RIS edge carried by a maintainer-sanctioned fork FullReset event |
src/status_bar.rs, the timer in src/terminal/engine.rs |
| autosuggest-stage2-crosscheck | 2026-10-21 | The stage-2 rulings against primary sources: fish’s autosuggest pipeline read from source (history-first with completions fallback, one ranked completion on ambiguity — not a common prefix, not nothing; strict prefix only, no fuzzy), fish never truncates a ghost plainly (3.7.1 clips to fit − 2 with … and hides below ~3 columns; 4.x soft-wraps with …), accept-whole-despite-clip is fish’s exact behavior, and every flag-knowledge peer (fish’s 1,097 completion scripts, Fig’s open specs repo, Warp’s bundled specs) externalizes its data; the terminal-side no-integration architecture re-verified as still unshipped by Ghostty, kitty, and Tabby |
Complete — seven of nine rulings stand; the two contradictions applied before build (the ghost clips with an ellipsis at fish’s threshold, and the flag-specs table keeps a nameable path to a loadable data file) | src/terminal/suggest.rs |
| documentation-improvement | 2026-10-23 | DropTerm’s docs already exceed every pop-os and cosmic-ext peer and match the gold standards on reference depth; the five gaps that matter are zero screenshots/demos, a packaging section behind its own ruling, a complete-but-unreachable Pages site, no task-oriented how-to layer (Diátaxis), and no FAQ/changelog/sample config — eleven ranked recommendations, none breaking the two docs gates | In progress — the how-to/FAQ layer, the releases page, and the generated sample config are the first three to build | the docs additions it seeds (each page carries its own row as it ships) |
| autosuggest-display-mode | 2026-10-24 | A display-timing knob yes, Zed’s eager/subtle semantics no — verified from Zed source at a pinned commit, “subtle” is hold-alt-to-preview with a popover fallback DropTerm has no analog for (and Alt is already the word-accept modifier), not a delay; the vocabulary that fits a terminal ghost is the idle-delay knob proven twice at this exact layer (VS Code’s editor.inlineSuggest.minShowDelay, default 0, range 0–10000, explicit-trigger bypass; ble.sh’s complete_auto_delay, default 1, README tip 300) — one numeric key autosuggestions_delay_ms, default 0 (fish parity, today’s behavior bit-for-bit), ghost withheld until typing is idle N ms, accept keys unchanged; min-prefix-chars (zero precedents, kills gi→git), Clink’s list-first surface split, and an eagerness enum as the primary knob all rejected; the accuracy claim kept honest — no vendor frames display timing as a correctness fix |
Shipped — the idle-delay key it seeded, autosuggestions_delay_ms (default 0), landed 2026-10-24 with the engine’s typed-stability clock and the app’s one-shot reveal tick; the record’s named next lever, the provider-side no-information floors, shipped alongside 2026-11-02 (suggest-accuracy: the catalog silent below 2 typed chars, the specs flag seat silent at bare --) |
the record; the gate in src/terminal/suggest.rs, the engine clock in src/terminal/engine.rs, the reveal tick in src/app.rs |
| shell-presence | 2026-10-24 | The switcher/dock entry is the clipboard anchor’s mapped xdg toplevel (winit cannot unmap on Wayland, and COSMIC’s toplevel-info listings are toplevel-only by protocol); no skip request exists anywhere, so the anchor gains a second body — a never-destroyed 1×1 layer surface with an empty input region that no listing can see — behind a show_in_dock key, default hidden, with the panel applet as the persistent handle |
Shipped | show_in_dock key, surface::anchor, the Anchor swap in src/app.rs |
| clipboard-ownership | 2026-11-02 | Every clipboard write was focus-coupled below DropTerm (smithay-clipboard’s wl_data_device store drops on !has_focus and zeroes the serial on Leave — silent at every layer), proven live: 6/6 fresh instances copy, a 9-hour instance fails every visible-but-unfocused copy and lands inside a focused re-map, and the OSC 52 query reply was computed then discarded; the fix is DropTerm owning its terminal clipboard I/O over the data-control protocol (src/clipboard.rs, focus-free, serial-free, per-copy serving thread) with a warn-and-fallback to the iced clipboard, the band’s widget-layer writes inverted to an app-side Copied report, and the OSC 52 reply delivered to the asking tab’s PTY by id — patching smithay-clipboard, queueing writes until focus, and waiting on upstream all rejected (the coupling is the protocol, not a bug) |
Shipped | src/clipboard.rs, the nine routed sites in src/app/tab_actions.rs + src/app.rs, the Copied report in src/status_bar.rs |
| release-orchestration | 2026-11-01 | The gated skill already matches the survey’s best pattern (cargo-release’s dry-run-by-default, per-step [y/N] confirms, verify-before-tag); adopt its five cheap sharpenings — behind-remote pre-flight, no-op-release warning, spec-exact Phase 1 derivation with a !/BREAKING CHANGE scan, tests in release CI (alacritty), naming release.yml’s dispatch dry-run as the rehearsal — plus an optional “Next (unreleased)” accumulator (changesets’ capture-early idea); release-please/changesets/cargo-release adoption, RC and nightly channels, and -dev version-on-master all rejected (npm/crates.io-shaped, team-shaped, or breaking DropTerm’s tag↔Cargo.toml guard); no AI-agent release skill exists in anthropics/skills or addyosmani/agent-skills to copy — the gates are novel, validated only by cargo-release’s CLI analog |
Complete | .agents/skills/release-orchestration/SKILL.md |
| autosuggest-warp-parity | 2026-11-02 | Close the Warp delta with a second surface, not a ghost rewrite: an explicit-trigger completion menu (Ctrl+Space, fuzzy-filterable, descriptions, Tab/Enter accepting only while the menu is open — VS Code’s scoped-keybinding mechanism, which leaves bare Tab the shell’s) supersedes the 2026-10-17 “menus deferred” rejection on that record’s own condition (the prompt layer is proven); spec breadth grows down the stage-2-named loadable-file path, eventually a one-time MIT conversion from withfig/autocomplete (715 specs, dormant since 2025-05 — the one source Warp and VS Code both build on; carapace runtime dependency and Warp AGPL code rejected, carapace’s license verified MIT not GPL); dynamic values split — file-derived allowed (git branches from .git/refs in the tab’s live cwd), spawn-based generators rejected (no session env: Warp runs them through its session, VS Code through shell-integration-reported env; DropTerm has neither) with the revisit priced; alias resolution rejected on the same grounds; AI rejected, confirmed even Warp’s completions are spec+generator lookups with no model; ghost stays single-choice strict-prefix (fish turns fuzzy and descriptions off in autosuggestion mode by construction) |
Shipped — its first module (suggest-menu, 2026-11-02): the Ctrl+Space menu with every provider’s full candidate sets, Warp’s prefix-then-subsequence ranker, the scoped Tab/Enter accepts, the overlay panel, autosuggestions_menu_enabled (default true) and the auto-popup opt-in (default false, the record’s own pricing); its second module (suggest-aliases, 2026-11-02 — the alias-resolution supersession) shipped the user-declared alias map; its third module (suggest-generators, 2026-11-03 — the dynamic-generators supersession) shipped the spawn-based git generators under the stricter-than-any-peer contract; and its fourth module (suggest-specs-data, 2026-11-03) shipped Phase B — the loadable completions.toml beside the config (deny_unknown_fields on every schema tier, the script boundary made structural; the built-in five the fallback, byte-equivalent with no file), descriptions into the menu’s dim column with the ghost untouched, and the audited withfig seed (the completions-seed-audit record) — the record’s four modules all shipped |
src/terminal/suggest.rs (the menu model), the scoped routing and overlay in src/terminal/widget.rs, the seam in src/terminal/engine.rs, the keys in src/config.rs + src/settings.rs, the user truth in Autosuggestions |
| autosuggest-dynamic-generators | 2026-11-02 | The owner-ordered supersession of the spawn rejection: DropTerm-defined generator programs only (read-only argv constants — VS Code’s git discipline copied verbatim: --no-optional-locks, warning/fatal post-filtering), scrubbed minimal env, the tab’s /proc/{shell_pid}/cwd, 5s timeout + kill + silence, stale-while-revalidate caching, the standing shell gate — the “unreproducible environment” objection answered by reducing the env to two reproducible inputs (the spawn-time PATH snapshot and the /proc cwd); the Fig format’s spec-authorable script fields stay rejected permanently (data imports, scripts never do); git first, docker/systemctl later; autosuggestions_generators_enabled default true |
Shipped (suggest-generators, 2026-11-03): the fifth source SuggestionSource::Generator reading post-processed, already-escaped branch/tag/file sets through the observation — the model still spawn-free and clock-free, the async-machinery line superseded for its inputs only; the runner engine-side: the three argv constants verbatim (--sort=-committerdate — the spec’s commercedate was its typo, git rejects unknown sort atoms), env scrubbed to HOME + LANG=C (pinned C so the fatal:/warning:/error: markers stay the English bytes the post-filter matches under any desktop locale), the spawn-PATH absolute binary, the /proc cwd, the 5s recv_timeout→SIGKILL deadline, stale-while-revalidate keyed (argv, cwd) with menu-open and the spawn-onset as the only triggers (typing never spawns — the spawn counter’s own pin), a landed fetch nudging one Wakeup, and every failure cached as silence (no TTL, no wall clock — OQ-1’s serve-forever leaning, decided); autosuggestions_generators_enabled default true shipped whole; docker/systemctl stay later slices, the script fields stay rejected |
the fifth source + the seat carve in src/terminal/suggest.rs, the runner (GeneratorRunner, argv constants, the deadline) in src/terminal/engine.rs, the key in src/config.rs + src/settings.rs, the user truth in Autosuggestions |
| autosuggest-alias-resolution | 2026-11-02 | The owner-ordered supersession of the alias rejection: a user-declared [autosuggestions.aliases] config map (WT sendInput’s terminal-owned-data precedent) re-targets the specs/catalog providers at the expansion — gc --dr ghosts git’s flag — history still outranking always, the shell gate still holding, and the 2026-10-02 no-injection verdict surviving whole; shell-state extraction rejected (carapace’s rc-wrapper + env protocol is the verdict’s exact shape), rc-file heuristics rejected (zero precedents, wrong-suggestion failure mode — Warp’s own alias resolution shipped broken for fish per issue #2281), passive grid observation priced as a later pre-seed only |
Shipped (suggest-aliases, 2026-11-02): autosuggestions_aliases — one serialized map field (OQ-1, the custom_key_binds grain) live-flipping through the toggles’ own options path — and resolve_alias at the specs_context carve (expansion’s command re-targeted, seats judged on the typed line, depth cap 3, cycle-safe, unmapped = today; the catalog’s command-position completion is suffix-bound to the typed word and needed no change); the priced later add-ons stay priced (the pre-seed, the drawer editor) |
resolve_alias + the carve in src/terminal/suggest.rs, the observation seam and live swap in src/terminal/engine.rs, the key in src/config.rs, the user truth in Autosuggestions |
| completions-seed-audit | 2026-11-03 | The per-content licensing audit for the spec table’s seed (the terminal-theming precedent): fourteen commands converted from withfig/autocomplete @ aef52acff84c (MIT, notice preserved in the shipped file), data only — generators, templates, and script fields structurally excluded by the destination schema; ffmpeg and ssh rejected as single-dash-shaped, tar’s modes carried as flags not subcommands |
Shipped (suggest-specs-data Task 4, 2026-11-03): the audited seed at data/completions.toml, its regeneration rules named in the record, its no-shrink invariant pinned by test |
data/completions.toml, the format reference in Configuration |
| terminal-images | 2026-11-05 | Implement the iTerm2 inline-images protocol (OSC 1337 File) first through the existing OSC fork arm — vte already delivers OSC, and imgcat/wezterm imgcat/timg/viu/chafa speak it with env/XTVERSION-based (or no) detection — storing images as cells in the scrollback grid via alacritty_terminal’s own CellExtra precedent (WezTerm’s per-cell ImageCell model, drawn with the renderer.draw_image primitive already in the pinned libcosmic); then the query-capable kitty graphics subset (f=32/f=100, t=d only, m chunking, a=t/T/p/q/d, i/p/z) through the fork’s one genuinely new parser surface — vte 0.15 drops APC payload bytes in SosPmApcString today — reusing the same cells and a 320 MB-class budget; Sixel deferred (DA1 simply omits ;4) until sixel-only demand shows; rejected: Sixel-first, kitty-first, overlay-only placements (Konsole/Ghostty’s model — more bookkeeping against the borrowed grid), external ueberzug-style overlays, Alacritty’s ship-nothing stance, and kitty t=f/t/s file/shm reads (uniform-error refusal); DropTerm must also be findable — its own TERM_PROGRAM, an XTVERSION answer, and the 1337 Capabilities reply |
Shipped (iterm-images: OSC 1337 both wire forms through the fork arms, the CellExtra image seat with Term::place_image, decode under the four ceilings, the store with renderer handles, and images_enabled default-on; kitty-images: the vte APC accumulation + Perform::apc_dispatch, the transmission subset — t=d only with the uniform EBADF refusal, f=24/32/100, o=z inflated through the sanctioned flate2, m chunking keyed by i — placements reusing pixels across moves, byte-exact a=q/e= replies on the PTY path, the d= deletion subset, and the two z-layer draw passes; detection remains the last module) |
the record |
| suggest-menu-layering | 2026-11-06 | with_layer is the proven fix, not a workaround: iced_wgpu renders a layer by primitive kind (quads → triangles → shader → images → text, verified in the pinned pop-os fork), so the menu quad could never paint above the grid’s text primitive in one layer however ordered or opaque; a child layer renders wholly after its parent (merge is guarded to be order-preserving) and clips to its bounds — and this is iced’s own mechanism, the one overlay::Nested::draw wraps every Overlay-trait widget in, iced 0.14’s first-class float widget’s shadow-quad-plus-content recipe, and libcosmic’s menu’s inner draw verbatim; the Overlay-trait route is the same z-order plus event routing — the right next step when the menu wants mouse, not the right first fix; cosmic-term avoids the class by never floating anything inside the terminal widget, alacritty/wezterm/kitty by owning their renderers; one correction: the fix’s comment understates tiny_skia, which also batches by kind per layer — the explicit layer is load-bearing on both backends; ranking (light): every shell’s explicit-completion surface lists scope without history while ghosts stay history-first (zsh-autosuggestions’ default), so the menu’s scope-above-history amendment matches the Tab-surface norm, the combined list being DropTerm’s own uncontested hybrid |
Complete — verdict for the uncommitted fix: keep with_layer; the tiny_skia comment sentence should be corrected at commit time |
the with_layer draw site in src/terminal/widget.rs:1147, menu_panel_style at src/terminal/widget.rs:2861 |
| bare-word-path-completion | 2026-11-06 | Bare argument words complete as paths as a fallback — fish (ghost included: FileCompletionPolicy::Inherit default), zsh (_default→_files), bash (documented filename fallback), Warp (CompletionsFallbackStrategy::FilePaths default), VS Code (no-items files-and-folders fallback) unanimous, with cd directories-only everywhere it is declared; DropTerm adopts the same carve for both provider twins — bare-word path answers ghost and menu-list only when specs/generator don’t own the seat, directories-only for cd/pushd, riding the standing shell gate and autosuggestions_paths_enabled, no new key — menu-only rows (splits the twins, leaves the flagship cd sr ghost unsolved), a curated path-command allowlist (no peer gates on an allowlist; duplicates filesystem truth), and unconditioned fish-parity ghosting all rejected (the merge ranks Path above Specs, so git co over a cwd configure would ghost the file; fish avoids this with per-command --no-files, not rank); CDPATH stays out on the shell-state rejection’s grounds |
Proposed | the record; the carve would land in src/terminal/suggest.rs + src/terminal/engine.rs |
| completions-breadth | 2026-11-07 | Scale the specs table from withfig/autocomplete’s static corpus — measured at the seed’s own pinned commit aef52acf (715 specs, 440 purely static = 61.5% by key grep, MIT with one uniform notice, descriptions first-class, frozen since 2025-05-05 with 105 unmerged PRs — priced as a snapshot DropTerm owns) — grown from the fourteen-command seed in maintainer-run tranches, embedded in the binary, zero seat changes needed for breadth; the parser to reimplement in Rust is microsoft/inshellisense’s runtime (the one live MIT engine on the format, pinned 9ba441d3), the field’s only knowledge source being these specs (Warp and VS Code both stand on them; Amazon deleted its TS engine 2025-07-03; WT is shell-integration history, Tabby bundles Clink, Wave/Ghostty/kitty/WezTerm ship nothing); ranked below it: carapace’s newly checked-in man/cmd/ YAML (755 commands, serde-trivial, but verbatim man-page text with a per-command licensing tail and GPL-2 pages that cannot ship in GPL-3.0-only), fish’s 1,097 files (94% described, uniform grammar, but GPL-2 and 51% fish-code conditions holding the subcommand tree; license-clean only as an opt-in runtime read of the user’s install), history-learned flags (a menu enrichment, not a source); zsh compsys and bash-completion closed as programs with pinned files |
Shipped — all four modules 2026-11-07: the recursive deny-unknown-fields tree (suggest-schema), the pinned-2.692.3 extractor emitting the 92-command core floor and the 532-command extended data file (suggest-corpus), the lexer-and-walker model (suggest-walker), and the consolidation (suggest-embed: the gzip-compressed embedded floor, the extended tier installed behind the generous default); the dictionary publishes as release artifacts over the same files (maintainer tooling), the settings update facility deferred behind the network Never | the schema and corpus in src/terminal/suggest.rs + data/completions*.toml*; the walker in src/terminal/suggest/walker.rs; the embed in the compressed BUILTIN_SPECS, the XDG extended loader, and the autosuggestions_completions_extended key |
| completions-engine-rea | 2026-11-07 | The breadth record’s REA target executed: inshellisense’s spec engine (pinned 9ba441d3, parsed by REA as inert TypeScript, 0 failures, both graphs retained) is a 154-line four-state lexer (= closes a flag token, so --emit=asm is --emit + its argument; only a space-followed token is complete, the trailing one is the partial) plus three mutually recursive walker functions (runSubcommand/runOption/runArg) whose whole rule set is: option-args consume the next token, isVariadic loops, isOptional re-tries as option/subcommand, isPersistent options ride into children, isCommand restarts on a nested command’s spec, an unknown flag silences; the stop point lists subcommands + options (minus already-typed and exclusiveOn) + arg suggestions, prefix-filtered case-insensitively, sorted by priority with spec order preserved, deduped, hidden dropped — descriptions straight from the spec; the field census shows the engine never reads requiresSeparator/requiresEquals/optionsMustPrecedeArguments/parserDirectives/isRepeatable/dependsOn, so a port honoring only isPersistent/isOptional/isVariadic/isCommand/hidden/exclusiveOn is the live engine’s own model; every generators:/script:/template: key in mkdir/rustc/node/gh/kubectl/docker/cargo/git sits on an Arg, never on a name, so dropping them keeps the whole tree with descriptions (rustc and mkdir carry zero to begin with); the Rust port is a recursive SpecCommand/SpecOption/SpecArg schema, a ~100-line lexer and ~200-line walker rendering into the existing MenuCandidate under the deny-unknown-fields boundary, adding per-subcommand options, option-arguments, nesting, persistence, variadics, and the sudo shape to today’s two flat seats |
Shipped — its field census is the schema’s own field set and its lexer/walker/stop-point model is the shipped walker’s, both pinned by test (2026-11-07: suggest-schema, suggest-walker, and the suggest-embed consolidation that seated the corpus beneath them) | src/terminal/suggest.rs (the census’s field set, deny_unknown_fields at every depth) and src/terminal/suggest/walker.rs (the lexer, the three walker functions, the stop point’s dressing) |
| paste-image-ux | 2026-11-08 | The paste-image presentation rides the maintainer’s proposal (candidate C): the pasted path stays the grid’s only trace (OQ-5’s bare-path ruling stands — the path is the terminal member of VS Code’s inserted-reference/Claude Code [Image #N]-chip marker family), the full-size auto-render leaves the paste handler (the one behavior none of the ten surveyed terminals ships; pixels evict to blank cells while the file survives; viewport displacement by image height), a per-tab images panel (iTerm2 Toolbelt’s Paste History/Recent Directories lists, CopyQ’s and Klipper’s per-item-action history rows) lists that tab’s pastes with thumbnails and open/copy-path/copy-image/re-paste/remove actions, and a conditional band count chip (the Scrolled chip’s conditional-click-verb shape, the exit chip’s hidden-at-zero rule, DROP_ORDER seating) opens it with the paste pulse riding the Copied report; OSC/kitty program-driven rendering untouched (terminal-images intact); a bounded inline preview deferred behind user demand (xterm.js’s placeholder-on-eviction the honest-edges model); placeholder-only without a panel rejected (an XDG cache path is undiscoverable) |
Shipped — 2026-11-08: the handler’s place_pasted_image call removed and the per-tab pasted_images ledger landed (PastedImage in src/tabs.rs, the existence-prune), the panel is the images context drawer with all five verbs incl. write_image_png (src/app.rs, src/clipboard.rs), and the chip is SegmentId::Pasted with the click-verb and the ✓ pulse (src/status_bar.rs); the config gate and retention (PI-3/PI-4) remain |
src/tabs.rs (PastedImage, the ledger and prune), src/app.rs (the handler, the drawer, the five verbs), src/clipboard.rs (write_image_png), src/status_bar.rs (SegmentId::Pasted, click_jumps, the pulse) |
| paste-uri | 2026-11-09 | The paste’s first read prioritizes text/uri-list (verified live on cosmic-comp: the priority read answers text/uri-list verbatim in every offer shape — exact match settles the spec’s OQ-1; the plain Text read answers the compositor’s text/plain;charset=utf-8 conversion of the list, so today’s file-copy paste is the list text, which the fallback reproduces by making the same request) and a qualifying list — exactly one URI, file scheme, empty-or-localhost host — names the one file the terminal opens, admitted by its own first bytes alone (regular-files-only metadata gate so a FIFO never blocks the paste, one bounded open so the sniffed bytes are the pasted bytes, 32 MiB refused whole, never the extension or the URI’s claim — the terminal-images record’s no-program-named-file-reads ethic, extended to the user’s own paste gesture); the sniffed formats name the cache extension and the panel Copy-image’s offered mime; PNG-only, reading x-special/gnome-copied-files (it carries a cut verb), multi-image copies, and quoted path-pasting all rejected |
Shipped (paste-uri, 2026-11-09): the whole road in src/clipboard.rs — TextWithPriority cascade, RFC 2483 qualification, the file gate, sniff-named cache writes, sniffed-mime copy offers — with the cascade-level manual check automated as the live_uri_paste_smoke #[ignore] test (serves real offers on a COSMIC session; five roads green 2026-11-09) |
src/clipboard.rs, the paste section in Inline images, the file-copy rows in testing |