Skip to content

πŸ”€ chore(release): merge dev β†’ main for v0.8.0#202

Merged
kbrdn1 merged 213 commits into
mainfrom
dev
Jun 1, 2026
Merged

πŸ”€ chore(release): merge dev β†’ main for v0.8.0#202
kbrdn1 merged 213 commits into
mainfrom
dev

Conversation

@kbrdn1
Copy link
Copy Markdown
Owner

@kbrdn1 kbrdn1 commented Jun 1, 2026

Description

Release merge: promote dev into main for the v0.8.0 stable release.

Bundles the full 0.8.0 train (rc.1 β†’ rc.5) plus the stable cut (#201): version bump to 0.8.0, consolidated changelogs/0.8.0.md, reset [Unreleased], and the ROADMAP refresh to v0.8.0.

Type of change

  • πŸ”§ Chore / CI / build (release merge)

Changes

  • 211 commits of 0.8.0 work merged from dev.
  • Stable cut: Cargo.toml/Cargo.lock β†’ 0.8.0, changelogs/0.8.0.md, ROADMAP v0.8.0.

Tests

  • cargo test green locally (1080 tests, 0 failures) and on the CI matrix (ubuntu/macos/windows).
  • cargo fmt --check + cargo clippy --all-targets -- -D warnings pass.
  • gwm doctor green (8/8).

Notes for reviewers

After this merges, v0.8.0 is tagged on main to trigger release.yml (gh-CLI publish, #146 path). git2 0.21 (#157) stays deferred to #169.

kbrdn1 and others added 30 commits May 23, 2026 12:34
Addresses Copilot review on PR #148: ensure the GH_TOKEN assertion inspects the stable publish step rather than matching later workflow jobs.\n\nrefs #146
πŸ‘· ci(release): publish stable releases with gh
Add the `aliases` module backing issue #86 β€” string-substitution CLI
aliases expanded before clap parses argv.

- `src/aliases.rs` β€” `ResolvedAliases` (built-in / repo / user chain),
  `load()`, `expand_argv()`, `validate_aliases()`. Static
  `BUILT_IN_ALIASES` slice mirrors every clap `visible_alias` declared
  on `Command` so the shadow gate stays in lockstep with `src/cli.rs`.
- `src/config.rs` β€” new `Config.aliases: BTreeMap<String, String>`
  field; `Config::load_for_repo` now calls `validate_aliases()` so a
  shadowed or shell-piped declaration fails at load time.
- `tests/aliases_tests.rs` β€” 21 unit tests covering: empty default,
  TOML round-trip, refusal of built-in shadow (subcommand + visible
  alias), refusal of shell metachars (`&&`, `||`, `|`, `;`, backticks),
  refusal of empty value, repo > user precedence, user-only fallback,
  missing user file is no-op, expansion respects trailing args,
  positional vs subcommand slot, no recursion, global flags
  pre-alias preserved, built-in-subcommand-always-wins defence in depth.

No CLI surface changes yet β€” the next commit wires expansion into
`main.rs` and adds the `gwm aliases list` subcommand.

refs #86
Addresses Copilot review on PR #149: use explicit mktemp templates for the pre-release changelog duplicate guard.\n\nrefs #147
πŸ‘· ci(release): reject duplicate rc changelog entries
Implement issue #86's user-visible surface on top of the `aliases`
module landed in the previous commit.

- `src/main.rs` β€” expand argv via `aliases::load()` +
  `aliases::expand_argv()` BEFORE `Cli::parse_from(...)`. A failure to
  load the alias chain prints a warning and falls back to the raw
  argv, so a typo in `[aliases]` doesn't lock the user out of `gwm
  doctor` / `gwm aliases list`.
- `src/cli.rs` β€” new `Aliases { action: AliasesAction }` subcommand
  with a single `List` action. `cmd_aliases_list()` discovers the
  current repo (gracefully degrades outside a git tree), loads the
  resolved chain, and prints three grouped sections (`built-in`, `repo
  (.gwm.toml)`, `user (~/.config/gwm/aliases.toml)`). Entries in the
  user section that are shadowed by a repo declaration are flagged
  inline `(shadowed by repo)`.
- `tests/cli_binary.rs` β€” extend the `help_prints_subcommands`
  canary with the `aliases` row, add 6 `aliases_list_*` end-to-end
  tests (built-in section outside a repo, repo section, user
  section, repo-overrides-user precedence, shadow error surfaced),
  and 3 `alias_*` expansion tests (built-in subcommand reached
  through alias, trailing args preserved, shadow refusal at runtime).

All tests are env-isolated (XDG_CONFIG_HOME + HOME pointed at the
TempDir) so a contributor's real `~/.config/gwm/aliases.toml` never
contaminates the suite.

refs #86
Addresses Copilot review on PR #150: check OS tokens independently so YAML formatting or ordering changes do not hide real Windows coverage.\n\nrefs #112
…ce rules

Add user-facing documentation for issue #86, closing the changeset.

- `CHANGELOG.md` β€” Unreleased entry under Added describing the alias
  chain, expansion semantics, and the `gwm aliases list` subcommand.
- `examples/gwm.toml.example` β€” commented-out `[aliases]` block with
  the resolution chain, the no-shell-pipeline rule, the canonical
  examples (`wip`, `ll`, `sync`), and a pointer to `gwm aliases list`.
- `docs/4.configuration/1.gwm-toml.md` β€” full `[aliases]` section
  with the validation table (shadow + shell metachar rules) and a
  row added to the defaults summary table.
- `docs/3.cli/1.reference.md` β€” `gwm aliases list` subcommand
  reference with sample output, resolution order, and the inline
  shadowing flag.

closes #86
Fixes the windows-latest CI compile failure: NoSymlink is only used by Unix-gated bootstrap tests.\n\nrefs #112
Fixes the windows-latest CI TOML parse failures when test TempDir paths contain backslashes.\n\nrefs #112
Fixes windows-latest config tests by using Windows absolute path literals when the suite runs on Windows.\n\nrefs #112
The `aliases_list_prints_built_in_section_outside_repo` test asserted
`contains("s")` for the built-in `s β†’ switch` row, which matched
incidental letters in `aliases`, `users`, `built-ins`, and other prose
in the output. The test would have passed even if the `s` row was
missing or malformed.

Assert the full formatted row `  s  β†’ switch` (width-2 padding from
`cmd_aliases_list`) and `  cd β†’ path` instead, so the predicate
actually pins the built-in alias rendering. Also tighten `built-in:`
(colon-terminated) so the section header is anchored to its full
label rather than the substring shared with `built-ins` prose.

Addresses Copilot review comment on PR #151.

Refs #86
Preserve Windows backslashes for {path} and {diff} placeholders before shell_words tokenizes command templates.

Refs #112
`main` collected argv via `std::env::args()` and handed a
`Vec<String>` to clap, which panics on the first non-UTF-8 argv
entry. This was a regression vs. clap's default `args_os` handling
and could abort the binary on a perfectly valid OS argv (Unix and
Windows both allow non-UTF-8 bytes in argv).

Switch to `std::env::args_os()` + `Cli::parse_from(Vec<OsString>)`,
and add an OsString-native alias expander `aliases::expand_argv_os`
that only attempts UTF-8 decoding on the alias-slot token (alias
keys are `String` by construction, so a non-UTF-8 token cannot
match β€” argv flows through unchanged and clap surfaces the unknown
subcommand verbatim).

Flag detection uses `OsStr::as_encoded_bytes` and looks for a
leading ASCII `-`, which is unambiguous in both UTF-8 (Unix) and
WTF-8 (Windows) and avoids decoding the rest of the token.

The existing `expand_argv` (String surface) is preserved for unit
tests and as a stable internal API β€” `expand_argv_os` is the new
entry point from `main`.

Tests added:

- `binary_tolerates_non_utf8_argv` (Unix integration) β€” pins that
  the binary does NOT die on a signal (SIGABRT) when argv contains
  invalid UTF-8 bytes (`0xff 0xfe 0x80`). Without the fix this
  reproduces the libstd panic `called Result::unwrap() on an Err
  value: "\xFF\xFE\x80"`.
- `expand_argv_os_matches_expand_argv_for_utf8_inputs` β€” sanity
  check that the OsString and String surfaces stay in lockstep on
  valid UTF-8 input.
- `expand_argv_os_passes_non_utf8_token_through_unchanged` β€”
  documents the contract: non-UTF-8 tokens in the alias slot flow
  through, no panic, no coercion.
- `expand_argv_os_expands_alias_after_non_utf8_flag_value` β€” pins
  the conservative behaviour when a non-UTF-8 byte sequence lands
  in the would-be alias slot.

Addresses Copilot review comment on PR #151.

Refs #86
Avoid hard-coded Unix separators in naming path assertions now that the suite runs on windows-latest.

Refs #112
Keep RC changelog duplicate tests portable on windows-latest by invoking the shell script through bash instead of as a native executable.

Refs #112
Copy the RC changelog duplicate checker into the temp fixture and execute it by relative path so Git Bash does not need to translate a Windows drive path.

Refs #112
The RC changelog checker is a Bash workflow helper exercised by Unix CI jobs; keep Windows focused on workflow structure so windows-latest is not blocked on Git Bash path semantics.

Refs #112
Avoid dead-code failures on windows-latest after gating the Bash-only RC changelog duplicate tests.

Refs #112
Keep TUI bootstrap-gate fixtures parseable on windows-latest by escaping backslashes in temporary paths.

Refs #112
πŸ‘· ci(test): add windows test matrix row
✨ feat(cli): CLI aliases ([aliases] in .gwm.toml + user fallback)
Red phase of the TDD loop for issue #85. Adds:

- `tests/gitmoji_tests.rs` β€” built-in branch_type β†’ shortcode map,
  `.gwm.toml` `[gitmoji]` overrides merged on top of defaults,
  prefix resolution in both `:shortcode:` and unicode forms,
  unknown-type fallback (`:question:` / ❓), and a sweep that
  every default shortcode has a matching unicode entry.
- `tests/hooks_tests.rs` β€” `install_commit_msg(repo, force)` creates
  an executable `.git/hooks/commit-msg`, refuses to clobber an
  existing hook without `--force`, replaces on `--force`, and the
  generated script carries the gwm marker + shell-out to `gwm
  commit-prefix --unicode`.
- `tests/cli_binary.rs` β€” end-to-end coverage for `gwm commit-prefix
  [--branch <name>] [--unicode]`, the new `--gitmoji` flag on `gwm
  types`, and `gwm hooks install commit-msg` (with / without
  `--force`). `help_prints_subcommands` is updated with the two new
  subcommand rows β€” the canary contract from CONTRIBUTING.md.

refs #85
Internal plumbing for issue #85 (turns the new tests green; the CLI
surface lands in the next commit).

src/gitmoji.rs
  - `DEFAULT_GITMOJI` β€” the ten built-in `branch_type β†’ :shortcode:`
    pairs baked into the binary so a stock repo (no `[gitmoji]`
    block) works out of the box.
  - `GitmojiMap` wrapper around a `BTreeMap` for deterministic
    iteration (load-bearing for `gwm types --gitmoji` byte
    stability).
  - `default_map()` materialises the built-in table.
  - `load(repo_root)` reads `.gwm.toml`'s `[gitmoji]` block via a
    local deserialisation envelope and merges it on top of the
    defaults β€” overriding `feat` doesn't wipe the other nine
    built-ins.
  - `resolve_prefix(map, branch, unicode)` renders
    `✨ feat(#41):` (or `✨ feat(#41):` with `unicode=true`),
    falling back to `:question:` / ❓ for unknown branch types so
    the surface is safe to call on any branch.
  - `shortcode_to_unicode` is a small `match` (eleven entries: ten
    built-ins + `:question:`) β€” no `gh-emoji`-style dep for so few
    keys; user-defined shortcodes round-trip verbatim.

src/hooks.rs
  - `install_commit_msg(repo_root, force)` writes
    `.git/hooks/commit-msg` (chmod 0o755 on Unix), refuses to
    overwrite an existing hook without `--force`, and rejects
    non-git directories.
  - `commit_msg_script()` returns a self-contained POSIX `sh`
    script that shells out to `gwm commit-prefix --unicode` and
    prepends the resolved prefix when the first line of the commit
    message doesn't already start with either a `:shortcode:` or a
    unicode emoji glyph. Degrades to no-op when `gwm` isn't on
    `$PATH` so the hook never blocks a commit because of itself.

refs #85
Surfaces the gitmoji + hooks plumbing through three CLI entry points
(issue #85). Diff on src/main.rs deliberately empty β€” the new
subcommands ride the existing `cli::run` dispatch, so the merge
surface against PR #151 (issue #86 aliases) stays minimal.

`gwm types [--gitmoji]`
  Extends the existing two-column branch-type list with two more
  columns (unicode emoji + `:shortcode:`) when `--gitmoji` is set.
  Without the flag the output is byte-identical to the pre-#85
  surface β€” scripted consumers don't regress. Shortcode width is
  aligned on the widest entry so the description column stays put.

`gwm commit-prefix [--branch <name>] [--unicode]`
  Resolves to `:sparkles: feat(#41):` (or `✨ feat(#41):` under
  `--unicode`). Two resolution paths:
   - `--branch <name>` β€” no repo required; useful for scripted
     contexts and AI assistants composing a commit message
     out-of-band.
   - default β€” reads HEAD from the current repo via libgit2.
  A branch that doesn't match `<type>/#<N>-<slug>` exits non-zero
  with a pointer to the convention rather than silently rendering
  a bogus prefix.

`gwm hooks install commit-msg [--force]`
  Installs `.git/hooks/commit-msg` via `hooks::install_commit_msg`.
  Opt-in (off by default), non-destructive (refuses to overwrite
  without `--force`), executable on Unix (mode 0o755). Wired
  through `HooksAction::Install` + `HookKind::CommitMsg` so future
  hooks drop in without breaking the CLI surface.

tests/cli_binary.rs
  Adds end-to-end coverage for all three surfaces (9 new tests),
  including the canary update to `help_prints_subcommands` per
  CONTRIBUTING.md.

closes #85
kbrdn1 and others added 27 commits June 1, 2026 15:13
✨ feat(tui): polish confirm + help modals (buttons, loader, key badges)
✨ feat(config): user-level global config merged under .gwm.toml (#190)
`KeyStroke::from_event` kept the SHIFT modifier verbatim, so on terminals
that report a shifted letter as `Char('V') + SHIFT` (Ghostty / Kitty /
WezTerm) β€” or as the base key `Char('v') + SHIFT` under the kitty keyboard
protocol β€” the runtime keystroke never compared equal to a bound chord like
`"V"` (`Char('V')`, no modifier). The lookup missed and the action silently
did nothing, not even a status-bar update. This affected every uppercase
binding (`G`, `R`, `F`, `O`, `L`), but only surfaced now because #188's
`V` / `H` were the first uppercase keys actively exercised on such a terminal.

Canonicalise any `Char` keystroke carrying SHIFT to its uppercase form with
the SHIFT bit dropped, in `KeyStroke::new` β€” so `from_event` and the config
parser (`"V"`, `"Shift+v"`) all converge on the same `Char('V')` with no
modifier, independent of how the terminal encodes shift. Non-`Char` codes
(`Shift+Tab` β†’ `BackTab`) are untouched.

refs #188
✨ feat(tui): borderless styled header + claude-dark preset (#185)
…onsive

# Conflicts:
#	CHANGELOG.md
#	src/tui/ui.rs
… global config

After #190 added the user-level global config layer, every test that loads
config through `Config::load_for_repo` β€” directly, or via `aliases::load` /
`App::new_at` β€” merged the runner's real `~/.config/gwm/config.toml`. On any
machine whose global config diverges from the built-in defaults the suite
failed: a global `[theme] preset` unknown to the checked-out build (e.g.
`claude-dark`, only added on an unmerged branch) made `theme.resolve()` reject
the merged config, panicking `aliases_tests.rs` (10 tests) and
`tui_theme_integration_tests.rs` (2 tests) on `.unwrap()`. CI stayed green only
because it exports `GWM_NO_GLOBAL_CONFIG=1` (#191); local `cargo test` had no
such guard.

Root cause: #190 added the `Config::load_layered(repo, global)` seam for
hermetic tests but did not propagate it to the call sites built on top of
`load_for_repo`. Complete the pattern:

- `aliases::load_layered(repo, global, user)` β€” repo step reads via
  `Config::load_layered`, user step takes the path literally (no implicit
  `default_user_path` fallback). `aliases::load` resolves the real
  global/user paths then delegates, so runtime behaviour is unchanged.
- `App::new_at_layered(start, global)` β€” same seam for the TUI app builder;
  `App::new_at` delegates with the real `global_config_path()`.
- The leaking tests now inject `None` global (and explicit/`None` user paths),
  so the whole suite passes deterministically without `GWM_NO_GLOBAL_CONFIG`,
  regardless of the contributor's `~/.config/gwm/`.

closes #194
πŸ› fix(config): hermetic config-loading seams so tests ignore the real global config
✨ feat(tui): responsive sidebar β€” stacked fallback + left/right position
…red seams

Completes the hermeticity work from #194 / #195. Those added the
`Config::load_layered` / `aliases::load_layered` / `App::new_at_layered` seams
and converted `aliases_tests.rs` + `tui_theme_integration_tests.rs`, but the
rest of the suite still called the environment-reading entry points
(`Config::load_for_repo`, `App::new_at`, `App::new_picker_at`), so `cargo test`
without `GWM_NO_GLOBAL_CONFIG=1` still failed on a machine with a divergent
global config (e.g. `[tui] sidebar_position = "left"` broke
`config_tests::tui_sidebar_position_absent_keeps_right`).

- Add `App::new_picker_at_layered(start, global)` (mirrors `new_at_layered`;
  `new_picker_at` delegates with the real global path).
- Convert every remaining test site to inject `None` global:
  `config_tests.rs` (68), `bootstrap_tests.rs` (2), `doctor_tests.rs` (1),
  `tui_app_tests.rs` (5), `tui_chord_tests.rs` (2), `tui_state_palette_tests.rs` (1).

The whole suite now passes **without** `GWM_NO_GLOBAL_CONFIG=1`, verified
against a real `~/.config/gwm/config.toml` carrying `claude-dark` +
`sidebar_position = "left"`. No runtime behaviour change β€” production entry
points still read the real global config.

closes #196
πŸ› fix(config): sweep all config-loading test sites onto the load_layered seams
Largest RC of the 0.8.0 series β€” the personalisation + polish wave on top of
rc.4's quick wins (global config #190, responsive sidebar #188, claude-dark +
header #185, modal polish #187, statusline #180, working-tree colours #179,
PR auto-detection #181, {repo_path}/{repo_parent} #175), plus the test-
hermeticity sweep (#194 / #196).

- Cargo.toml / Cargo.lock: 0.8.0-rc.4 -> 0.8.0-rc.5.
- changelogs/pre-releases/0.8.0-rc.5.md: new per-RC file with the delta against
  rc.4 (merged PRs #176, #178, #182, #183, #184, #186, #189, #191, #192, #195,
  #197).
- CHANGELOG.md: reset [Unreleased] to the placeholder (bullets move into the
  rc.5 file) and add 0.8.0-rc.5 above rc.4 in the index.
- ROADMAP.md: add the rc.5 shipped-highlights row.

Reconciliation: open PRs accounted for (only #157 git2 0.21, deferred to #169,
left open). Local guards green:

  cargo build  (Cargo.lock synced to rc.5)
  cargo fmt --check
  cargo clippy --all-targets -- -D warnings
  cargo clippy --all-targets -- -W clippy::incompatible_msrv
  ./.github/scripts/check-rc-changelog-dupes.sh v0.8.0-rc.5
  cargo test  (green without GWM_NO_GLOBAL_CONFIG=1 after the #194/#196 sweep)

refs #188
- Version line: note 0.7.0 stable + the 0.8.0-rc.5 feature set on dev (global
  config, aliases/gitmoji, config CLI + hooks, templates, sync, binstall, TUI
  personalisation incl. claude-dark + responsive sidebar).
- Keymap table: correct the `v` sidebar row (narrow terminal stacks, not
  hidden) and add `V` (cycle layout) / `H` (toggle position).
- Details sidebar section: document the responsive orientation + left/right
  position and the `[tui] sidebar_position` knob.

refs #188
Copilot review on PR #198: the `V` sidebar-layout cycle is
`auto β†’ side-by-side β†’ stacked β†’ auto`, but SKILL.md's keymap table and Details
sidebar section omitted the wrap back to `auto`. Align both with the actual
behaviour (and with the CHANGELOG / rc.5 notes, which already showed the wrap).

refs #188
πŸ—οΈ build: cut v0.8.0-rc.5
Add the subcommands that shipped across the 0.8.0 RC series but were
still missing from the reference: commit-prefix, hooks install
commit-msg, undo, history, theme list/show, tui keys. Extend types
with --gitmoji and remove/prune with --dry-run, complete the
create/bootstrap flag tables (--reuse-branch / --skip-hooks / --force),
and add sync to the dynamic completers. Fix a stale completions anchor.

refs #199
Add the s (sidebar stashes mode) and : (command palette) list-view
keys, note that the keymap is now configurable via [tui.keys] with
chord support, and fix the focused-border colour wording (theme focus
role, default Cyan). Add two pages β€” Themes (roles, presets, value
formats) and Keymap & command palette ([tui.keys] remap, gwm tui keys,
palette flow) β€” plus an rc.5 chrome section (single-line statusline,
borderless header, shared modal frame).

refs #199
Add the [theme] (presets, roles, named/indexed/hex value formats) and
[tui.keys] (chord grammar, rebindable action table, validation) blocks
with #theme / #tui-keys anchors, the [tui].sidebar_position knob, and
the {repo_path} / {repo_parent} placeholders. Add a User-level global
config page (~/.config/gwm/config.toml deep-merge, GWM_NO_GLOBAL_CONFIG)
and document when: predicates for [[hooks.*]] phases.

refs #199
Document the 8th gwm doctor check ([tui.keys] keymap resolves), add a
cargo-binstall packaging section, and flesh out the PR auto-detection
provenance (LinkSource::Detected, the (detected) TUI marker).

refs #199
Add cargo binstall to the install channels and fix the MSRV to 1.82;
refresh the testing story (ubuntu/macos/windows matrix, ~990 tests, the
new integration files, the mandatory TDD loop) and the contributing
commit helpers (commit-prefix / commit-msg hook). Add the v0.8.0-rc.5
personalisation+polish bullet to the roadmap and refresh the landing
page feature bullets + 30-second tour.

refs #199
Complete French mirror of the docs/ tree (33 pages incl. the three new
v0.8.0 pages), structured for Nuxt Content i18n. English under /docs
stays canonical; prose is translated with full diacritics while code,
commands, flags, TOML keys, identifiers and proper nouns are kept
verbatim, and internal links are rewritten to the /fr/ prefix.

refs #199
Addresses the review on the docs v0.8.0 PR:
- gwm doctor runs 8 checks, not 7 (EN + FR CLI reference; doctor.md and
  the integrations index already said 8).
- Reword the "no git CLI dependency" claim (EN landing + getting-started,
  FR landing): worktree ops run on vendored libgit2, but a few features
  (gwm sync, the review-diff launcher, the sidebar git status/log) do
  shell out to the user's own git.
- i18n: translate the leftover English section headings on the FR pages
  (rΓ΄les, prΓ©rΓ©glages, rΓ©solution de la base, en-tΓͺte, mode stashes, …)
  and localize the getting-started navigation.title to "DΓ©marrage".
- Align every internal anchor link with the real heading slug on both
  trees: drop the {#tui-keys} / {#theme} id pins (they render literally
  on GitHub) in favour of the natural slugs (#tuikeys, #tuiopen,
  #bootstrapcommand), and fix the FR anchors to the French heading slugs
  (incl. the double-hyphen "issue / pr" cases). Verified: 0 dangling
  page or anchor link across docs/ and docs/fr/.

refs #199
πŸ“ docs: refresh docs/ to the v0.8.0 surface + French i18n mirror
Promote 0.8.0-rc.5 to the 0.8.0 stable release.

- Bump Cargo.toml / Cargo.lock to 0.8.0.
- Add changelogs/0.8.0.md consolidating the rc.1β†’rc.5 deltas plus the
  stable-only docs refresh (#199 / #200), per the release-notes-are-
  per-version house rule.
- Reset CHANGELOG.md [Unreleased] and index 0.8.0 under Past releases.
- Refresh ROADMAP.md Current state to v0.8.0 (config CLI, hooks, aliases,
  gitmoji, templates, TUI personalisation, global config, sync, binstall,
  8 doctor checks, gh-CLI publish with #146 resolved).

git2 0.21 (#157) stays deferred to #169.
πŸ—οΈ build: cut v0.8.0 stable
Copilot AI review requested due to automatic review settings June 1, 2026 19:18
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@kbrdn1 kbrdn1 merged commit 4e5d2a7 into main Jun 1, 2026
17 checks passed
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.

2 participants