Skip to content

Dispatch Lua function keybindings from the menu - #11851

Open
vdvoorder wants to merge 1 commit into
omacom:quattrofrom
vdvoorder:keybindings-menu-lua-function-binds
Open

vdvoorder wants to merge 1 commit into
omacom:quattrofrom
vdvoorder:keybindings-menu-lua-function-binds

Conversation

@vdvoorder

@vdvoorder vdvoorder commented Sep 14, 2026 •

Copy link
Copy Markdown

Super + K lists Lua function bindings, but selecting one did nothing. For example, a user who zooms in, searches for Reset zoom, and presses Enter gets no reset or message; the script exits 1. Five of the 232 default bindings on Omarchy 4.0.2 are affected: Zoom in, Reset zoom, and the three universal clipboard actions. User-defined function binds have the same failure.

The menu replays the Lua config to recover each action, but a plain Lua function leaves no expression to replay. Hyprland reports these binds as __lua with a registry ref. When an expression is available from the source, the expression still wins. Otherwise, the menu records the bind's modifier mask, submap, key, keycode, and description. The record is stored base64-encoded, because later steps rewrite text in that field for display (key names for code:NN, the Omarchy bin path).

A config reload can assign the same registry ref to a different function. At dispatch time, the menu rereads hyprctl binds and requires exactly one __lua bind to match the recorded identity. The menu calls the ref currently attached to that bind through the existing hl.dispatch path, and refuses a blank or nonnumeric ref.

A reload also starts Hyprland's Lua state over. Before the lookup, each pick writes a mark of its own into a table in the Lua registry, and the call checks for that mark. A reload between the lookup and the call removes the mark, so the call raises an error and nothing runs. Overlapping picks keep separate marks, and a pick removes its own mark whether it is called or refused.

The picked row is now matched through the environment instead of awk -v, which reads a backslash in a description as an escape and then matches no row. This affected every bind kind. When two rows read the same and one of them is a function bind, the pick is refused, because the menu cannot tell which row was picked.

The cache version moves from v14 to v19 so cached rows with blank dispatcher fields are rebuilt. Open pull requests already use v15 to v18.

PR #11733 is a broader rewrite of the keybindings scan across 11 files. This PR keeps that work separate and fixes the current script.

Testing

  • bash test/shell.d/keybindings-menu-test.sh: all 33 passed (16 existing and 17 new). The stubbed hyprctl dispatch runs the dispatched expression in lua, so the tests assert which function was called.
  • Each new test fails against a version of the script with the matching defect: no mark check, one shared mark, no mark cleanup, a cleanup that empties the table, a lookup that ignores the submap or accepts two matches, awk -v for the picked row, the first of two identical rows dispatched, and a picked row that is not dispatched.
  • bash test/shell.d/bin-style-test.sh: passed.
  • git diff --check: passed.
  • Live on Omarchy with Hyprland 0.56.2, running the script with only the picker stubbed: Reset zoom changed zoom_factor from 1.5 to 1, Zoom in changed it from 1 to 2, and two menus started together both exited 0. No mark was left in the Lua registry afterwards.
  • ./test/shell: 279 of 290 test files passed. The 11 failures also fail on the unchanged base commit 821ae589; four of them require an omarchy-pkgs checkout that is not present on this machine.
  • ./test/cli: one check fails, "vscode generated theme references current theme file". It fails the same way on 821ae589 (test/cli vscode assert expects a symlink that 977e0fcd replaced with a real file #13131).

Not included

  • A reload between writing the mark and reading hyprctl binds refuses that pick once. Nothing runs, and picking again works.
  • A reload while the menu is open keeps the row valid as long as one bind still has the same chord, submap, and description. The menu calls whatever function that bind has now, as the key press would.
  • Function binds whose rows read the same are refused: the same chord and description in two submaps, or a press and a release bind. The picker returns only the row text. Telling such rows apart needs a row id carried through the picker, which is a separate change.
  • A function that returns { ok = false } still makes the script exit 0, because hyprctl dispatch prints ok for it.
  • The source cache is keyed by modifier mask, description, and key. A function bind that shares all three with a bind the source resolves takes that bind's expression. That keying predates this PR.
  • The comma-delimited binding record format remains unchanged. A description or key containing a comma already breaks the row for every bind kind, and none of the shipped defaults has one. Reworking the record framing would also require changes to parse_binding_records, static_bindings, and every test that reads rendered rows, so that belongs in a separate change.

@llstrk

llstrk commented Sep 30, 2026

Copy link
Copy Markdown

Automated AI review

Community review: Independent automated community review, unaffiliated with the Omarchy team, intended to help prepare PRs for their review.

Outcome: Merged into current quattro, the PR's v14 cache bump matches the version quattro already uses, so caches written by current quattro are reused and Reset zoom and other function binds can still do nothing.

Cache version v14 is already used on quattro

quattro moved keybindings_cache_key from v13 to v14 in #13521. This PR makes the same one-line change, so the merge is silent and the merged script computes the same cache file name as current quattro. Impact: an install that opened the menu on a post-#13521 build keeps cached rows with blank dispatcher fields, so selecting a function bind still exits 1 until the binds, keymap or cache change.

Suggested change: after rebasing, bump to a version no other open PR uses (v15 and v16 are taken by other open PRs), for example v17.

Reproducer

The PR's v14 cache version is the same value quattro already has since #13521, so after merging, a cache written by current quattro is reused and Reset zoom still does nothing. This is a merge interaction: it does not show on the PR head alone (its own base is v13), so it is a standalone script rather than a test case.

Needs bash, gawk, lua, xkbcli and jq (the menu's own dependencies). No Hyprland session: hyprctl and the menu picker are stubbed and put first on PATH.

git clone https://github.com/omacom/omarchy.git && cd omarchy
git fetch origin pull/11851/head
git worktree add --detach ../quattro 8b4eae66da2938ba9559f103b18dbf85cdf28a70
git worktree add --detach ../merged 8b4eae66da2938ba9559f103b18dbf85cdf28a70
git -C ../merged -c user.name=r -c user.email=r@example.invalid merge --no-edit 677ba24a4b5f8394bd4f36160a015076a17b7f3d
bash cache-version-repro.sh ../quattro ../merged

cache-version-repro.sh:

#!/bin/bash
# Usage: cache-version-repro.sh <quattro checkout> <quattro with #11851 merged>
# Stubs hyprctl (one Lua function bind, as Hyprland 0.56.2 reports it) and the
# menu picker, lets quattro write the keybindings cache, then opens the menu
# on the merged tree with the same cache directory and picks Reset zoom.
set -u
ulimit -c 0
old=$1 new=$2
work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT
mkdir -p "$work/bin" "$work/home/.config"
cp -r "$new/config/hypr" "$work/home/.config/hypr"

cat >"$work/bin/hyprctl" <<'STUB'
#!/bin/bash
printf '%s\n' "$*" >>"$LOG"
case "$1" in
  binds) printf 'bindd\n\tmodmask: 76\n\tsubmap: \n\tkey: Z\n\tkeycode: 0\n\tcatchall: false\n\tdescription: Reset zoom\n\tdispatcher: __lua\n\targ: 264\n\n' ;;
  devices) echo "active keymap: English (US)" ;;
  dispatch) echo ok ;;
esac
STUB
cat >"$work/bin/omarchy-menu-select" <<'STUB'
#!/bin/bash
grep -m1 -- '→ Reset zoom$'
STUB
chmod +x "$work/bin/hyprctl" "$work/bin/omarchy-menu-select"

menu() {
  : >"$work/log"
  env -i PATH="$work/bin:$1/bin:/usr/bin:/bin" HOME="$work/home" \
    XDG_CACHE_HOME="$work/cache" OMARCHY_PATH="$1" LOG="$work/log" \
    bash "$1/bin/omarchy-menu-keybindings" >/dev/null
  echo "exit status: $?"
  grep '^dispatch' "$work/log" || echo "nothing dispatched"
}

echo "== quattro opens the menu and writes the cache"
menu "$old"
ls "$work/cache/omarchy"
echo "== quattro + #11851 opens the menu with that cache"
menu "$new"
ls "$work/cache/omarchy"
rm -rf "$work/cache"
echo "== quattro + #11851 with the cache cleared"
menu "$new"

Output (quattro 8b4eae66da, PR head 677ba24a4b):

== quattro opens the menu and writes the cache
exit status: 1
nothing dispatched
keybindings-c35e00b023d9f6dc5b6709d373139d8a9d31b0a4206a261969db138343abc781.records
== quattro + #11851 opens the menu with that cache
exit status: 1
nothing dispatched
keybindings-c35e00b023d9f6dc5b6709d373139d8a9d31b0a4206a261969db138343abc781.records
== quattro + #11851 with the cache cleared
exit status: 0
dispatch debug.getregistry()[264]

Same script, with the merged tree's printf 'v14\n' changed to printf 'v15\n' (the only diff):

== quattro opens the menu and writes the cache
exit status: 1
nothing dispatched
keybindings-c35e00b023d9f6dc5b6709d373139d8a9d31b0a4206a261969db138343abc781.records
== quattro + #11851 opens the menu with that cache
exit status: 0
dispatch debug.getregistry()[264]
keybindings-9fdee32b8ee0601f492dc3583d995cb12a8d24463319a700a8adf4b1931739c8.records
== quattro + #11851 with the cache cleared
exit status: 0
dispatch debug.getregistry()[264]
Verified
  • debug.getregistry()[<ref>] through hyprctl dispatch calls the same function, with the same zero arguments, that a key press calls on Hyprland 0.56.2 (source reading).
  • The recorded identity survives scan, cache, menu selection and the reread for code:, mouse: and submap binds; a ref moved by a reload dispatches the new ref.
  • Source-resolved rows such as Close window keep their expressions.
  • The PR's tests pass on the head (22) and on the merged tree (23), and the first new assertion fails against the base and quattro scripts.
Optional notes

Review information

Test scope: Hyprland 0.56.2 and main source, plus sandbox tests with stubbed hyprctl at 677ba24 and merged onto quattro 8b4eae6; no live Hyprland session.

AI process: Opus 5.5 Medium coordination and synthesis, Opus 5.5 Xhigh technical review and final fact check, GPT 6 Sol Xhigh search for related issues, Opus 5.5 Medium editorial check.

Opt out: To stop receiving these reviews, reply to this comment saying so.

@omarchybot omarchybot added the verified Omarchy Triage has verified that this issue is ready for final review label Oct 1, 2026
@omarchybot

Copy link
Copy Markdown
Collaborator

Reviewed and run on a disposable Omarchy worker with Hyprland 0.56.2. The fix works, and I pushed three commits to your branch.

Reproduction. With the zoom set to 2, picking Reset zoom from the menu through a stubbed picker exits 1 and leaves the zoom at 2 on quattro (8b4eae6). On this branch it exits 0 and resets the zoom to 1. With your script changes taken out, it fails again.

What I pushed:

  • 486dfa6 merges quattro into the branch. The merge had no conflicts, but quattro already moved the cache key to v14 in Hand the terminal launcher the focused window's pid from Lua #13521, the same bump this PR made. Merged as it was, a cache written by quattro kept being served, and Reset zoom still did nothing on the worker until the cache was cleared.
  • dc147a3 moves the cache version to v17, since open pull requests already use v15 and v16. With it, the cache quattro wrote is rebuilt and Reset zoom works straight away.
  • 59e8ede passes the bind identity to awk through ENVIRON instead of -v, which reads backslashes as escapes. A function bind whose description or submap contains a backslash was recorded literally, never matched afterwards, and dispatched nothing. A new test covers it: it fails without the change and passes with it.

Tests on the worker: keybindings-menu-test.sh 24/24 and bin-style-test.sh pass. ./test/cli fails one check, "vscode generated theme references current theme file", which fails the same way on unchanged quattro, so it is not from this change.

Second opinion: Codex Medium reviewed the branch over two rounds. It found the awk -v problem fixed above, and on the final head it had nothing open against this change. Separately, it judged this the right fix for this bug over #11733, which mainly fixes the scanner hang (#7025) and would replace this mechanism only if it lands. It also pointed out a pre-existing case this PR doesn't touch: the menu finds the selected row with awk -v selection=, so any bind with a backslash in its description still can't be selected, whatever its kind.

Waiting on: the maintainer. It is verified at 59e8ede, but not marked ready until the ./test/cli failure on quattro is resolved.

@greptile-apps

greptile-apps Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

[Medium risk] Adds Lua function keybinding dispatch to the menu system.

The PR appears safe to merge; no new actionable failure or outstanding prior finding was identified.

Summary

The PR makes menu selections dispatch Lua function bindings by retaining an encoded bind identity, resolving its current registry reference, and guarding the call against a Lua-state reload.

  • It also refuses ambiguous function-binding rows and matches selected text without awk -v escape handling.
  • The tests cover execution, reloads, overlapping selections, failed lookups, and menu picks.

Reviews (7) · Last reviewed commit: "Dispatch Lua function keybindings from t..."

Comment thread bin/omarchy-menu-keybindings Outdated
Comment thread test/shell.d/keybindings-menu-test.sh
@vdvoorder

Copy link
Copy Markdown
Author

Pushed 8316867 for the two review findings.

Reload between the lookup and the call. A reload starts Hyprland's Lua state over. Checked on 0.56.2: a value set through hyprctl dispatch is gone after hyprctl reload. The menu now leaves a mark in the Lua registry before it reads hyprctl binds, and the call checks for the mark. If a reload lands in between, the mark is gone, the call raises an error and nothing runs.

Tests that run the function. The dispatch stub now runs the dispatched expression in lua, with a recording function behind every ref that hyprctl binds reports. The tests assert which ref was called, and that nothing was called in the refused cases. A new test covers a reload between the lookup and the call. It fails on 59e8ede and passes with this commit.

keybindings-menu-test.sh passes 25/25 and bin-style-test.sh passes. On a live session with the zoom at 1.5, Reset zoom through dispatch_binding puts it back at 1.

The ./test/cli failure is #13131, and #13133 has a fix open for it.

Comment thread bin/omarchy-menu-keybindings Outdated
@omarchybot omarchybot removed the verified Omarchy Triage has verified that this issue is ready for final review label Oct 2, 2026
Comment thread bin/omarchy-menu-keybindings Outdated
Comment thread test/shell.d/keybindings-menu-test.sh Outdated
A bind given a plain Lua function, like Reset zoom, leaves no expression for the menu to replay, so picking it did nothing. The menu now records which bind the row is, looks that bind up again when it is picked, and calls the function through the registry ref Hyprland reports for it.

A reload can hand that ref to another function between the lookup and the call. Each pick leaves a mark in the Lua state before the lookup and the call checks for it, so a reload in between is refused instead of running another function.

The picked row is matched through the environment instead of awk -v, which reads a backslash in a description as an escape and then matches no row.

The cache version moves to v19 so rows cached without a dispatcher are rebuilt.
@vdvoorder
vdvoorder force-pushed the keybindings-menu-lua-function-binds branch from 15ee388 to 03cbacb Compare October 2, 2026 09:55
@omarchybot

Copy link
Copy Markdown
Collaborator

I've seen 03cbacb: one commit rebased onto quattro 821ae58 that folds in the earlier fixes and adds the reload mark, the ENVIRON match for the picked row, and the cache move to v19.

This head has not been re-verified yet. Every item here gets a second opinion, and today's budget for those is used up, so Codex Medium did not run on this head. Without it, the classification at this head can't be confirmed by a second model, and the review stopped there. Nothing was run on a worker for 03cbacb, and the verified label from 59e8ede came off when the head moved. I read the diff and found nothing against it, but that is one model reading the change, not a test.

Waiting on: the maintainer, or a fresh pass once the second opinion is available again.

@omarchybot omarchybot removed the bug Something isn't working label Oct 2, 2026
buger added a commit to probelabs/omarchy that referenced this pull request Oct 5, 2026
…evidence as known_issue_not_reproduced (fixed by omacom#11851) (box)

pocs/crs-260930-jvx8-c02.sh exits 1 (defect fixed) on this tree; evidence recaptured with --green-tripwire --accept-flip --revision <tree HEAD> on the Linux audit box.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
buger added a commit to probelabs/omarchy that referenced this pull request Oct 5, 2026
…tro-proof 1e43373)

Mirror of omacom#11851 at head 03cbacb: the upstream change applied onto
quattro-proof 1e43373, followed by the proof work for the review. This
commit changes no file; it records the mirror at the branch tip, where the
review pipeline reads it (Proof-* trailers).

Proof-Change-Key: pr/11851
Proof-Upstream-Repo: github.com/omacom/omarchy
Proof-Mirror-Of: refs/pull/11851/head
Proof-Upstream-Head: 03cbacb
Proof-Head-Ref: keybindings-menu-lua-function-binds
Proof-Change-Base: 821ae58
Proof-Base-Ref: quattro
Proof-Baseline: 1e43373
Proof-Baseline-Ref: quattro-proof
@buger

buger commented Oct 8, 2026

Copy link
Copy Markdown

TL;DR: Stubbed picks on this head (03cbacb8), merged onto quattro 035ce29f, dispatch all six shipped function binds and new user command binds. Same-chord/same-description rebinds still use the cached default until #7564 is applied; the combined run dispatches the user's command.

This adds a stubbed execution check to the current-head review. Hyprland and the picker were stubbed; it does not repeat the earlier head's Reset zoom check with real Hyprland and a stubbed picker.

Dispatch comparison, integration and existing tests
  • Six shipped function binds on the tested base. quattro at 035ce29f also has Select all (SUPER + A), next to the universal clipboard binds. The description's five refers to Omarchy 4.0.2. @llstrk's #13276 review already lists the six; the picks here check their dispatch.
  • New command binds in the user's own bindings.lua run too, not only function binds. In Hyprland 0.56.2 every Lua bind is reported as __lua with a registry ref, plain functions and hl.dsp.* dispatchers alike (LuaBindingsToplevel.cpp#L154-L156). On quattro the Lua replay stops at qconsole.lua, so no bind declared in bindings.lua has a source expression. Each of them now gets a working row through its ref.
  • One case still needs Make the keybindings menu's Lua bind scan safe against load-time config reads #7564: a rebind that keeps the shipped chord and description. This is the keying limit your "Not included" section describes, and it is the symptom @alinuxfan reported on #7564: with o.rebind("SUPER + SHIFT + F", "File manager", { launch = "flea" }), this head still runs omarchy-launch-nautilus. The replay stops before bindings.lua, so the shipped bind's expression is the one cached under that chord and description, and the expression wins over the ref. With Make the keybindings menu's Lua bind scan safe against load-time config reads #7564 also applied, the same pick runs flea. The tested combined tree conflicts only on the cache-version line, resolved to v20. Whichever fix lands second must invalidate caches produced by the first. Together they fix this tested rebind case.
  • Tests. keybindings-menu-test.sh passes 33/33 on the head and on the merge (16/16 on quattro). I re-ran three of the mutants the description lists (no mark check, awk -v for the picked row, first of two identical rows), and each fails a test.
What a pick from the menu runs, per tree (stubbed)

Real bin/omarchy-menu-keybindings, the shipped config/hypr plus three user binds (a new function bind, a new command bind, and the File manager rebind above). hyprctl binds is stubbed in the 0.56.2 shape: dispatcher: __lua, arg: <ref> for every Lua bind (HyprCtl.cpp#L1048). The hyprctl dispatch stub runs the dispatched Lua and records which bind's ref was called, or which command hl.dsp.exec_cmd got.

Row picked quattro 035ce29f this PR #7564 this PR + #7564
Reset zoom, Zoom in nothing (exit 1) its ref nothing (exit 1) its ref
Select all, Universal copy / paste / cut nothing (exit 1) its ref nothing (exit 1) its ref
Terminal omarchy-launch-terminal same same same
new user function bind nothing (exit 1) its ref nothing (exit 1) its ref
new user command bind nothing (exit 1) its ref personal-cmd personal-cmd
File manager, rebound to flea omarchy-launch-nautilus omarchy-launch-nautilus uwsm-app -- flea uwsm-app -- flea

In the same setup, quattro caches 8 of 228 rows with no dispatcher (the six shipped function binds and the two new user binds). This head caches none. No two rows read the same, so the new refusal for identical rows does not touch the shipped config. When it does apply, it exits 1 with no message, like any failed dispatch already does on quattro.

Our audit's reproducer for this bug

We track this as KI-MENU-KEYBINDINGS-FUNC-BIND-NO-DISPATCH. Its reproducer, pocs/crs-260930-jvx8-c02.sh, runs the real dynamic_bindings against a stubbed hyprctl binds. It now prints the shape Hyprland 0.56.2 prints (arg: 264 on the Select all bind); with the empty arg: it printed before, a fix that dispatches through the ref still read as broken. On Linux:

quattro-proof 1e433732: SUPER,A,Select all,,                              -> SYMPTOM ... (defect present), exit 0
this PR (merged):       SUPER,A,Select all,__lua,NjQfH1NVUEVSICsgQR8wH1NlbGVjdCBhbGw=
                        -> PASS-REFUTED: every __lua row kept a dispatchable action - defect fixed, exit 1

A description containing a comma still shifts the fields on both trees (SUPER,B,Copy, then paste,…). That is the separate framing issue the description already leaves out of scope.

A test for the new-bind case: passes on this head, fails with quattro's script

This drops in after the existing function-bind tests and uses their stub_hyprctl_dispatch, lua_function_bind, pick_from_menu and called helpers. This is a synthetic cache-miss fixture: an unconditional error() prevents the following bind from registering in a real load of this file. The stub independently supplies its ref to exercise fallback dispatch; this does not demonstrate that real-world registration sequence. The explicit error still stops this module if the replay gets past qconsole.lua.

# Synthetic cache miss: the replay has no expression for this bind.
# The hyprctl stub independently supplies its ref to check fallback dispatch;
# a real load of this file would stop before registering the bind.
cat >>"$home/.config/hypr/bindings.lua" <<'LUA'
error("a personal module that fails to load")
o.bind("SUPER + ALT + P", "Personal bind", "true")
LUA
stub_hyprctl_dispatch <<BINDS
$(lua_function_bind 72 "P" "Personal bind" 300)
BINDS
pick_from_menu "Personal bind"
called 300 ||
  fail "a bind declared after a config error is called through its ref" "$(cat "$tmpdir/hyprctl.log")"
pass "a bind declared after a config error is called through its ref"

Saved results: 34/34 on this head, and not ok - a bind declared after a config error is called through its ref with quattro's script. With #7564 applied, the saved run shows the existing 33 checks passing; it does not establish this extra check on the combined tree. One existing lua_function_bind call—the failed-lookup test—passes an empty ref (lua_function_bind 76 "Z" "Reset zoom" ""). A numeric ref would match Hyprland 0.56.2's output; that fixture adjustment would need its own test run.

Thanks @vdvoorder for the careful reload and overlap handling, @omarchybot for the cache-version and ENVIRON fixes on the earlier head, and @llstrk for catching the v14 collision. Greptile's five points (a reload between lookup and call, tests that actually run the function, overlapping picks, marks left behind, and which mark survives) are covered by tests on this head, as its last pass on 03cbacb8 also says.

The evidence page lists two compatibility findings for the same test evidence under a new name. The engine mistook type( in a Lua heredoc for a shell function name; each finding has a note explaining this naming artefact. These are not two product behavior changes.


Independent verification: the evidence for this PR comes from a full proof audit of 03cbacb merged onto quattro at 035ce29 (evaluated merge 90cbb43): test report 68 passed · 0 failed · 0 skipped. Rechecked on quattro b83d3df (2026-10-08): the script and its tests are unchanged but the shipped Hyprland Lua configuration changed, and rerunning this head and its #7564 integration on that tip preserves every stubbed pick above (33/33 keybinding checks on each). Checked by running this head's script and tests with Hyprland and the picker stubbed; not a formal proof.

@vdvoorder

Copy link
Copy Markdown
Author

Status at 03cbacb8 (unchanged since 2026-10-02):

  • It merges into quattro without conflicts. quattro is still on cache version v14 and the other open pull requests on this script use v15 to v18, so v19 is still free.
  • @buger, thanks for the stubbed run on the merge. The count of five in the description is for Omarchy 4.0.2; Select all is the sixth on quattro and takes the same path. The rebind that keeps the shipped chord and description is the cache keying listed under "Not included", which Make the keybindings menu's Lua bind scan safe against load-time config reads #7564 fixes. The empty ref in lua_function_bind 76 "Z" "Reset zoom" "" is deliberate: that test checks that a bind without a numeric ref is refused.
  • I am leaving the head where it is so the runs on it stay valid. The test for a bind declared after a config error can go in a follow-up.

@omarchybot this head has had no worker run yet. Can it get a fresh pass?

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.

4 participants