Bundled fix wave for six findings from the sub-category-granularity
whole-branch review:
- config-settings: reset in_subcat on Tab/Shift-Tab so up/down keep
routing to cur_row instead of freezing on the Sponge/Paths pages
after a drill-down
- verify-manual: _parsed_components() now delegates to
generate_component_registry.collect_components() instead of a
lossy dict.update() merge, closing a taxonomy-check blind spot on
identity collisions
- verify-manual: add test_committed_registry_matches_headers to
catch the committed registry drifting from current # COMPONENT
headers
- build-docs workflow: trigger on conf.d/** and config.fish edits,
not just functions/**
- __config_settings_draw_subcat: show (Universal)/(Session) in the
drill-down title so the persistence scope is visible before toggling
- __config_settings_draw / config-settings: mention the Enter
sub-category drill-down in the on-screen hint and --help text
- generate_component_registry: send the "wrote ..." progress line to
stderr so it no longer corrupts --concat's stdout output
Two bugs invisible to single-frame rendering, only reachable via the
interactive event loop:
- right/l and left/h resolved the sub-category variable name with
"$toggle_vars[(math ...)]"_(...) inside a quoted string -- fish
cannot expand a command-substitution index there ("Invalid index
value"), so the set never ran and varname silently kept the parent
category variable. Every arrow-key press on a sub-category row
toggled the parent category instead. Fixed by hoisting the category
variable into a plain local first, the same technique the down/j
case already used for its page index.
- __cs_dispatch_draw left panel_h fixed at 16 regardless of what it
actually drew, but the new sub-category page is n+7 lines (9-13,
always < 16). Every redraw/cleanup erase computed its height from
the stale constant, erasing too many rows and corrupting whatever
was above the panel. Fixed by having the dispatcher record the
actual printed height into panel_h after every draw, including
resetting it back to 16 on the value pages even when in_subcat is
stale from a Tab away without an intervening Escape.
Adds __config_settings_draw_subcat.fish, rendering a category's own
toggle plus its sub-category rows, sized dynamically from
__config_settings_subcats instead of the fixed 6-row category layout.
Wires the real per-category row count into config-settings.fish's
up/down handling (replacing Task 17's stub) and adds the
hyphen-to-underscore sub-category variable resolution to the
left/right toggle handlers, mirroring the translation the guard
function already applies.
Two box-drawing bugs surfaced while adapting the design doc's draft to
the real static sub-category data and were fixed rather than
transcribed: the title-dashes offset was off by 5, and several real
sub-category labels/descriptions (e.g. "Notifications", 13 chars;
several descriptions past 30 chars) exceed the narrower width tiers'
fixed field widths, so both fields are now defensively truncated
before padding to keep every row exactly iw+2 wide regardless of
content length.
overrides-tricks conflated two distinct C3 concerns under one shared site
(overrides/environment), so __fish_config_op_overrides_key_bindings off
left tricks.fish's bang-bang bindings active while abbr.fish/puffer.fish/
config.fish's equivalent sites correctly disabled -- a half-dismantled
bang-bang system per docs/manual's own atomic-gating claim. Split into
tricks-manpager (overrides/environment, matches PAGER/EDITOR/CDPATH) and
tricks-bang (overrides/key-bindings, matches abbr.fish/puffer.fish/
config.fish's bang-related sites, per
docs/manual/08-components-reference/03-c3-key-and-environment-overrides.md).
Also fixes stale prose in config.fish's top-of-file comment: the guard
signature is now <identity> [<site>], not <category>.
The site was mistagged aliases/filesystem in the prior commit. The original
code's own comment above the guarded block ("Surgically overriding the
distro config is opinionated (C3 overrides): skip it entirely when
overrides are disabled") documents this as an overrides decision, and it
gated __fish_config_op_overrides pre-migration. Retag to
overrides/environment (matching tricks.fish's own sibling site for the
equivalent action) so aliases=on/overrides=off keeps skipping
tricks.fish/ls/lt/cleanup/copy, as originally documented -- no silent
user-facing behavior change.
Adds multi-site `# COMPONENT` headers and converts every guard call site in
conf.d/tricks.fish, conf.d/abbr.fish, functions/smart_exit.fish,
conf.d/yay-wrapper.fish, conf.d/paru-wrapper.fish, conf.d/wakatime.fish,
conf.d/first_run.fish, and config.fish (9 sites across 3 categories) to the
self-identifying `(status current-function|basename) <site>` calling
convention. Regenerates conf.d/__fish_config_op_registry.fish.
__fish_config_op_enabled built the sub-category override variable name by
concatenating the tag's slug verbatim, e.g. __fish_config_op_integrations_window-mgmt.
Fish variable names cannot contain hyphens, so any hyphenated sub-category
slug (14 of the 24 in the taxonomy) silently could never be overridden --
an unset such variable safely fell through via set -q, but attempting to
set it always errored with "invalid variable name", masking the defect
since no prior smoke test exercised an explicit sub-category-level toggle.
The registry tag itself (as authored in # COMPONENT headers and the
taxonomy docs) stays hyphenated; only the derived fish variable name is
translated.
collect_components() used dict.update(), which let conf.d silently
overwrite functions/ (or vice versa) when the same bare identity
appears in both, e.g. functions/auto-pull.fish and
conf.d/auto-pull.fish. The runtime guard can only ever look up the
bare status current-function/basename string, so both call sites
genuinely share one identity and their raw COMPONENT lines must be
concatenated, not replaced.
At the default 1em (16px) it read as noticeably smaller than the
other header controls, especially next to the logo. Bumped to a fixed
1.5rem — well within the nav bar's existing content height, so the
header itself doesn't grow.
logo.svg was 56KB of unminified, high-precision path data with no
embedded raster. Running it through SVGO (default preset, multipass)
cuts it to ~20KB with no visual difference.
perf(docs-site): further minify header logo SVG. Cut to ~8.9KB with no visual difference.
The header social link used Starlight's generic `code-branch` icon.
Wires up starlight-plugin-icons + UnoCSS (Iconify) and overrides
SocialIcons to render `pajamas:gitea` for the Gitea link instead, while
falling back to Starlight's default icon set for anything else. Sidebar
and codeblock icon support are enabled but unused for now.
Explains that a matched command is actively deleted from history and
force-saved within about one prompt cycle by default, not deferred to
shell exit, and calls out sponge_purge_only_on_exit as the setting that
would change that (a killed/crashed session never triggers fish_exit).
Also hyperlinks the Fisher-managed and bundled plugin names to their
upstream repos on the Starlight site.
Reworks fish-deps' dependency classification from three tiers to five:
Required, Recommended, Optional, Terminal Emulators, and Integrations.
- Add an Optional tier for single-purpose wrapper conveniences that only
matter if you already use that specific tool (btop, dust, duf,
prettyping, go, lazygit, lazydocker, docker, yt-dlp, screen). Skipped by
`fish-deps install`/`sync` by default.
- Split kitty/wezterm into their own Terminal Emulators tier, since only
the one matching $TERM is ever relevant to a given user.
- Add --optional, --terminals, and --all flags to `install`/`sync` to
opt back into the skipped tiers, with a summary of how many were
skipped and which flag restores them.
- Fix `_fish_deps_status` marking missing Integrations as critical (red)
the same as Required — only Required is red now; Recommended stays
yellow, everything else renders as a neutral dim note.
Also fixes two bugs surfaced during dependency testing on a fresh
install:
- `fish_right_prompt` called `docker context show` on every prompt with
no `type -q docker` guard, unlike every other optional integration in
this config — on a system without docker this printed a visible
"Unknown command: docker" block on every single prompt render. Added
the missing guard, and hardened the `ld` wrapper with explicit
docker/lazydocker presence checks.
- `ov`'s catalog entry offered `cargo install ov` as its preferred
install method, but crates.io's `ov` is an unrelated crate, not the
noborus/ov pager — cargo would silently install the wrong package.
Removed the cargo path; `ov` now prefers `go install
github.com/noborus/ov@latest` (ahead of the system PM) when go is
available, since not all distros package `ov` in their base repos,
and falls back to the system PM otherwise.
The EXIT STATUS block used a single space before the ">0" row's
description, which falls below the doc pipeline's 2-space column
threshold and silently degrades the rendered site page from a table
(like rm's) to a plain indented block. Pad it to match. Also strip
trailing whitespace from two DESCRIPTION lines and add --wraps='mv'
so fish inherits real mv's completions, matching the bash/top wrapper
convention.
Add the starlight-llms-txt plugin so the docs build emits llms.txt,
llms-full.txt, and llms-small.txt alongside the regular pages, making
the manual queryable by MCP-compatible agents without depending on a
third-party indexing service.
Also bump js-yaml, nanoid, and sharp in docs/site to clear three
high-severity advisories (quadratic YAML omap parsing, a zero-size
nanoid loop, and inherited libvips CVEs) flagged by npm audit while
touching the same lockfile.