Skip to content

feat(web): open settings on overview with one save changes bar - #1560

Open
rodboev wants to merge 92 commits into
mainfrom
pr/redesign-2-settings
Open

rodboev wants to merge 92 commits into
mainfrom
pr/redesign-2-settings

Conversation

@rodboev

@rodboev rodboev commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Settings opens on Overview with feature status and setup actions. Seven categories group settings by task. Operations links to Overview. Contacts has one Sync now action. The daemon decides when it needs a full reconciliation.

Save changes covers ordinary settings, including Kata and task service keys, and says when a pending edit needs a restart. Leaving Settings or reloading with unsaved changes asks first. Provider keys, People lookups providers, contact accounts, and replacement inference keys still save at once with their own buttons.

settings-save-flow-dark.webm
View Before After
Overview, 1440x1000 Before After
Overview, 390x844 Before After
Server, 1440x1000 Before After
Server, 390x844 Before After
Search & AI, 1440x1000 Before After
Search & AI, 390x844 Before After
People lookups, 1440x1000 Before After
People lookups, 390x844 Before After
Tasks, 1440x1000 Before After
Tasks, 390x844 Before After
Contacts, 1440x1000 Before After
Contacts, 390x844 Before After
Contact sync, 1440x1000 Before After
Contact sync, 390x844 Before After
Sources, 1440x1000 Before After
Sources, 390x844 Before After
Advanced, 1440x1000 Before After
Advanced, 390x844 Before After
Feature setup, 1440x1000 Before After
Key dialog, 1440x1000 Before After
Build confirmation, 1440x1000 New in Overview After
Build confirmation, 390x844 New in Overview After
Contact test, 1440x1000 Before After
Contact test, 390x844 Before After
Pending contact roles, 1440x1000 Before After
Pending contact roles, 390x844 Before After
Index build with contact sync, 1440x1000 New in Overview After
Index build with contact sync, 390x844 New in Overview After
Named contact draft, 1440x1000 Before After
Named contact draft, 390x844 Before After
Contact account validation, 1440x1000 Before After
Contact account validation, 390x844 Before After
Leave warning, 1440x1000 New in Settings After
Leave warning, 390x844 New in Settings After
Restart notice before saving, 1440x1000 New in Settings After
Stale message index, 1440x1000 New in Overview After
Stale message index, 390x1000 New in Overview After

Refs #1552, slice 2 (Settings categories)

@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (aaee8da)

Verdict: Changes require fixes for 2 findings.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:424; web/src/lib/components/settings/SettingsWorkspace.svelte:432: Changing a provider endpoint to another origin while clearing its stored key leaves Save changes stuck. The endpoint write already deletes the credential, so the subsequent DELETE returns credential_not_found (404). The clear remains pending on every retry and blocks later account and inference-key saves.

    Fix: Reconcile pending credential clears after endpoint writes, settling clears whose credentials are already absent. Treat credential_not_found as a completed clear and add a regression test for the combined save.

  • web/src/lib/components/settings/CardDAVAccountSettings.svelte:162: An unchanged Google contact account produces no draft, and the separate account-save button has been removed. Test performs nonpersistent discovery, while Save changes never submits the unchanged account, preventing users from refreshing saved discovery URLs through the documented Test-and-save workflow.

    Fix: Provide an explicit rediscovery action, or allow a successful connection test to stage an unchanged account for saving.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 10s | Total: 18m15s

@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (42933f6)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/components/settings/CardDAVAccountSettings.svelte:50: After staging a disable or clearing a schedule on a saved named contact connection, leaving Contacts and returning can lose those edits. Selecting the pending connection before /carddav/connections finishes initializes its persisted baseline from blank fallback values. When the summary arrives, reconcileSettings treats false/empty drafts as untouched, restores saved values, and can delete the draft entirely.

    Fix: Retain the saved baseline with each account draft, or wait for the named connection summary before initializing its form. Add coverage with a delayed connections response and a pending disable or schedule clear.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 8s | Total: 23m33s

@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (e5fb31b)

Verdict: No findings at or above medium severity.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 6s | Total: 18m7s

@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (8557c4d)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/components/settings/CardDAVAccountSettings.svelte:164: Successful connection tests only stage unchanged Google accounts. An unchanged Microsoft account with missing discovery, a missing credential binding, or unavailable runtime is therefore never submitted by Save changes, blocking account recovery.

    Fix: Stage unchanged Microsoft accounts after successful connection tests and cover the recovery paths.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 10s | Total: 15m40s

@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (92788d7)

Verdict: No findings at or above medium severity.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 6s | Total: 16m23s

@rodboev
rodboev marked this pull request as ready for review October 29, 2026 05:15
@rodboev
rodboev marked this pull request as draft October 29, 2026 14:28
@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (0cae3f6)

Verdict: Changes require fixes for 2 findings.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.test.ts:312: The test 'Overview shows a contacts sync action error' duplicates 'keeps a failed Overview action error on Overview' at line 143. Both reject the Contacts sync action and assert its alert; the earlier test also checks persistence across navigation.

    Fix: Delete 'Overview shows a contacts sync action error'.

  • web/src/lib/operations/actions.test.ts:14: The test 'reports contacts sync conflict' duplicates the existing end-to-end test at web/tests/e2e/operations.spec.ts:24, which exercises the real controller with HTTP 409 and verifies the conflict alert. The new test adds only exact wording checks.

    Fix: Delete 'reports contacts sync conflict'; retain the distinct partial and failed result tests.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 11s | Total: 16m6s

@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (4ec5909)

Verdict: No findings at or above medium severity.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 10s | Total: 14m59s

@rodboev
rodboev marked this pull request as ready for review October 29, 2026 16:51
@rodboev
rodboev requested a review from wesm October 29, 2026 16:51
@rodboev
rodboev force-pushed the pr/redesign-2-settings branch from 4ec5909 to 22043a0 Compare October 29, 2026 17:03
@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (22043a0)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/settings/overview.test.ts:38: The initializing/available:true case uses a coverage response the daemon cannot produce: initializing responses set fullBuildAvailable=false, so searchCoverageActions cannot advertise build_index. SettingsWorkspace.test.ts:406 repeats this impossible combination in its concurrent-action journey.

    Fix: Delete the initializing/available:true table case; the next case already covers the Initializing chip. Preserve the concurrency journey using reachable responses, such as unavailable with build_index before completion, followed by ready without that action.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 10s | Total: 18m11s

@rodboev
rodboev marked this pull request as draft October 29, 2026 17:41
@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (147abc4)

Verdict: Changes require fixes for 3 findings.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:119: After Back is held on a history entry without exploreIndex, clicking another workspace and then Stay leaves Settings displayed at the popped URL. The second leave request overwrites the original stay callback with undefined, losing holdPop's restoration callback. Subsequent navigation can overwrite the prior history entry.

    Fix: Retain and correctly settle the original history-restoration callback when replacing a pending leave request. Cover Back → workspace click → Stay and Discard.

  • web/src/lib/settings/overview.test.ts:33: The incomplete coverage fixture advertises build_index, an impossible daemon response: usable non-stale generations set fullBuildAvailable=false, and incomplete coverage reporting preserves that flag.

    Fix: Set available=false for the incomplete case. Keep its Incomplete text and warning-tone assertions; unavailable and stale cases already cover advertised builds.

  • web/src/lib/operations/actions.test.ts:8: The failed fixture combines aggregate status failed with a succeeded personal connection. CardDAVController.Sync reports partial whenever failures coexist with any success, making this response unreachable.

    Fix: Keep the successful personal connection only in the partial case. Make the failed case contain only failed connections while preserving failure-reporting and safe-name coverage.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 9s | Total: 17m59s

@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (15df179)

Verdict: Changes require fixes for 3 findings.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:119: After Back reaches an unindexed history entry, clicking another workspace replaces the pending leave request and loses its history-restoration callback. Choosing Stay leaves Settings displayed at the popped workspace URL, and subsequent navigation can overwrite that history entry.

    Fix: Preserve and settle the original restoration callback when replacing a pending leave request. Cover Back → workspace click → Stay and Discard.

  • web/src/lib/settings/overview.test.ts:33: The incomplete coverage fixture advertises build_index, an unreachable daemon response: usable, non-stale generations set fullBuildAvailable=false, and incomplete coverage preserves that flag.

    Fix: Set available=false for the incomplete case while preserving its Incomplete text and warning-tone assertions. Use unavailable and stale cases to cover advertised builds.

  • web/src/lib/operations/actions.test.ts:8: The failed aggregate sync fixture includes a succeeded connection. CardDAVController.Sync returns partial whenever failures coexist with success, making this fixture unreachable.

    Fix: Include the succeeded personal connection only in the partial case. Use only failed connections in the failed case while preserving failure-reporting and safe-name assertions.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 14s | Total: 14m28s

@roborev-ci

roborev-ci Bot commented Oct 29, 2026

Copy link
Copy Markdown

roborev: Combined Review (92870e5)

Verdict: No findings at or above medium severity.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 7s | Total: 14m43s

@rodboev
rodboev marked this pull request as ready for review October 29, 2026 21:52
@rodboev
rodboev marked this pull request as draft October 30, 2026 00:09
@roborev-ci

roborev-ci Bot commented Oct 30, 2026

Copy link
Copy Markdown

roborev: Combined Review (745724c)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.test.ts:151: The restart-cue test treats log.sql_trace as a live setting, but the daemon always publishes restartRequired=true for it. The cue-absent assertions therefore depend on a response production cannot emit.

    Fix: Use a real live setting such as web.theme, retain that draft while navigating to Server, then toggle restart-required log.enabled to preserve the cue appearance/removal checks.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 8s | Total: 15m56s

@roborev-ci

roborev-ci Bot commented Oct 30, 2026

Copy link
Copy Markdown

roborev: Combined Review (19f35c7)

Verdict: No findings at or above medium severity.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 8s | Total: 13m46s

@rodboev
rodboev marked this pull request as ready for review October 30, 2026 00:45
@rodboev
rodboev marked this pull request as draft October 30, 2026 01:07
@roborev-ci

roborev-ci Bot commented Oct 30, 2026

Copy link
Copy Markdown

roborev: Combined Review (54f15c6)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:150: With dirty Settings, pressing Back to an unindexed history entry and then Forward before answering the leave prompt leaves pendingLeave intact. Clicking Discard and leave executes the old callback, displaying the previous workspace while the URL still points to Settings.

    Fix: Invalidate pending leave callbacks on every committed history navigation, including returns to the same category. Cover Back followed by Forward before answering the prompt.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 7s | Total: 16m27s

@roborev-ci

roborev-ci Bot commented Oct 30, 2026

Copy link
Copy Markdown

roborev: Combined Review (4c5b927)

Verdict: No findings at or above medium severity.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 8s | Total: 12m59s

@rodboev
rodboev marked this pull request as ready for review October 30, 2026 01:43
Settings now uses fixed categories rather than daemon groups as rail
entries. The old layout test waited for a category heading that no longer
exists, so it could no longer check the scrollbar regression.

Keep the short-to-long category transition and its position checks with
settings the daemon can actually return.
@rodboev
rodboev force-pushed the pr/redesign-2-settings branch from 1f29209 to fac6511 Compare October 31, 2026 18:06
@roborev-ci

roborev-ci Bot commented Oct 31, 2026

Copy link
Copy Markdown

roborev: Combined Review (fac6511)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/explore/state.svelte.ts:896: After indexed Back navigation is held for unsaved changes, clicking the global Settings tab again pushes another history entry without cancelling the held leave when the category is unchanged. “Discard and leave” then executes the old relative history.go(delta), potentially landing on the wrong entry and remaining in Settings after discarding edits.

    Fix: Cancel the held leave whenever another navigation commits, including navigation to the same Settings category. Add coverage for this indexed-history sequence.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 11s | Total: 17m9s

Clicking Settings while a leave warning is open can leave its old action
active after browser history has moved. Discarding then uses a stale
history distance and can land on the wrong page.

Settle held leaves for every in-app navigation so returning to Settings
closes the warning and preserves the expected Back path.
Repeated navigation scenarios made the Settings tests harder to maintain
without protecting another outcome. Keep each leave decision covered once,
preserve the provider-card checks in their existing scenario, and make every
coverage state check its displayed tone.

Separate stored search choices from saving them so both behaviors have a
clear assertion path within the existing test count.
@roborev-ci

roborev-ci Bot commented Oct 31, 2026

Copy link
Copy Markdown

roborev: Combined Review (d110519)

Verdict: No findings at or above medium severity.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 13s | Total: 15m47s

@rodboev
rodboev marked this pull request as ready for review October 31, 2026 19:38
@roborev-ci

roborev-ci Bot commented Nov 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (ceef781)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/settings/people-inference-controller.svelte.ts:35: After another tab or a manual edit changes a People profile, a shared-settings conflict reload advances the ETag without refreshing the cached profile status. Returning to People lookups skips loading because status already exists. Confirming removal then sends the new ETag while displaying the old profile, allowing the updated policy and its stored key to be deleted without a conflict.

    Fix: Refresh the profile snapshot when advancing its configuration revision, and invalidate pending confirmations or checks when the corresponding profile changes.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 11s | Total: 19m32s

@rodboev
rodboev marked this pull request as draft November 1, 2026 17:17
A shared-settings conflict reload could let removal delete a profile and
its stored key after another tab changed the policy. The confirmation
still showed the old profile while the request used the newer revision.

Keep People writes tied to the revision returned with their profile data
so the existing conflict response requires a reload before removal.
Saving another settings category advances the config revision while the
workspace keeps its People controller alive. Returning with cached profile
status then causes an avoidable conflict on the next People write.

Reload on each mount so the displayed profile and its revision arrive
together, including after an ordinary settings save.
@roborev-ci

roborev-ci Bot commented Nov 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (3c294ec)

Verdict: Changes require fixes for 3 findings.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:399: Saving ordinary settings or an enrichment provider while People lookups remains open updates the shared configuration revision but leaves the People controller using its old ETag. Subsequent profile checks, creation, selection, or removal receive HTTP 412 and require a manual reload.

    Fix: Refresh the People profile snapshot and revision together after shared or provider configuration saves, invalidating checks and confirmations tied to the previous snapshot.

  • web/src/lib/components/settings/SettingsWorkspace.svelte:169: A failed coverage refresh silently retains the previous status and actions. Overview can therefore show stale Message search status or continue offering a full index rebuild after the index has completed, even when operations status refreshes successfully.

    Fix: Preserve previous coverage while refreshing, but expose an error or unavailable state and suppress stale actions when the request fails.

  • web/src/lib/explore/state.svelte.ts:645: Browser Back from dirty Settings opens the leave confirmation, but AppShell runs restoreHistoryFocus for both the held popstate and its restoring traversal. This moves focus from Stay to the navigation button and disrupts keyboard access to the confirmation.

    Fix: Coordinate history focus restoration with the leave guard so held and restoring traversals preserve focus on the confirmation.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 13s | Total: 18m21s

Saving shared settings while People lookups stays open leaves its profile
snapshot and configuration revision stale. Cover ordinary settings and
provider saves, including clearing the prior check and checking again.

Keep this regression failing because refreshing after each save would
lengthen the existing save functions, which this change's scope forbids.
A held Back navigation restores Settings through a second history traversal.
The shell moves focus to navigation during that traversal, disrupting
keyboard access to the leave confirmation.

Keep this regression failing because guarding history focus restoration
would lengthen its existing function, which this change's scope forbids.
Back from dirty Settings opens the leave confirmation, then restores the
Settings entry with a second history traversal. The shell restored history
focus on both, moving focus from Stay to the navigation.

Leave focus where it is when Settings is still showing and already holds it.
A real Back into Settings unmounts the previous workspace, so navigation
still receives focus then.
Saving ordinary settings or an enrichment provider advances the shared config
revision. People lookups stayed on its old profile snapshot and revision, so
the next People write failed with a conflict.

Reload People after each successful save so its profiles and revision arrive
together.
A failed coverage refresh kept the last answer, so Overview still offered a
Build index action for coverage it could no longer confirm. Show Message
search as Unavailable instead. Other feature rows stay, since they come from
operations status.
@roborev-ci

roborev-ci Bot commented Nov 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (77a85ac)

Verdict: Changes require fixes for 2 findings.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:354: After a shared-settings save returns HTTP 412, conflict recovery reloads general settings but leaves the mounted People controller with stale profiles and an old config ETag. Subsequent profile actions fail with another 412 and require a manual reload.

    Fix: Refresh the People profile snapshot and ETag after shared-settings conflict reloads, including provider conflict callbacks, and invalidate checks tied to the previous snapshot.

  • web/src/lib/components/settings/SettingsWorkspace.svelte:404: Saving an enrichment provider while a People status read is pending requests inference.load(), but run() silently skips the refresh while busy. The pending response can then install an obsolete ETag, causing subsequent profile actions to fail with HTTP 412 despite the successful save.

    Fix: Queue a follow-up refresh when load() is requested while busy, or serialize provider saves with People requests.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 12s | Total: 17m58s

Conflict recovery reported that the latest settings were loaded while People
lookups still showed an older profile snapshot. The next profile action then
failed with another config conflict.

Refresh People alongside general settings so users can review the current
profiles and continue without a second reload.
@roborev-ci

roborev-ci Bot commented Nov 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (e390f40)

Verdict: Changes require fixes for 2 findings.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:621: When an enrichment provider save or creation returns HTTP 412, conflict recovery reloads only general settings. The mounted People controller retains stale profiles and ETag, causing subsequent profile actions to fail with another 412 until manual reload.

    Fix: Refresh the People profile snapshot and ETag in both provider conflict callbacks, invalidating checks tied to the previous snapshot.

  • web/src/lib/components/settings/SettingsWorkspace.svelte:404: If a provider save succeeds while a People status request is pending, inference.load() silently skips the refresh because run() returns while busy. The pending response can install an obsolete ETag, causing subsequent profile actions to fail with HTTP 412.

    Fix: Queue a follow-up refresh when load() is requested while busy, or serialize provider saves with People requests.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 14s | Total: 14m12s

An enrichment provider conflict loaded the latest general settings while
People lookups kept an older profile and config revision. The next People
action could then fail with another conflict.

Conflict recovery needs the same complete snapshot regardless of which
settings write triggered it.
@roborev-ci

roborev-ci Bot commented Nov 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (435a4f4)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:404: Saving or adding an enrichment provider while a People status request is pending can drop the refresh because inference.load() returns while busy. The older response can install stale profiles and a pre-save ETag, causing subsequent profile actions to fail with HTTP 412 until manually reloaded. Provider conflict callbacks can lose their refresh the same way.

    Fix: Queue a follow-up People status reload when busy, or serialize provider mutations with People requests. Add a regression test with a delayed status response spanning a provider save.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 9s | Total: 13m29s

The first build has counts for its pending generation before any generation
becomes active. Overview should show that progress while the build runs.
A network failure left Overview showing counts from the previous status read.
Message and visual search should fall back to their operation state when
fresh counts are unavailable.
@roborev-ci

roborev-ci Bot commented Nov 1, 2026

Copy link
Copy Markdown

roborev: Combined Review (b01acb7)

Verdict: Changes require fixes for 1 finding.

Medium

  • web/src/lib/components/settings/SettingsWorkspace.svelte:404: Saving or adding an enrichment provider while a People status request is pending drops the requested refresh because run() returns immediately when busy. The pending response can install a pre-save ETag, causing subsequent People actions to fail with HTTP 412 until manually reloaded. Provider conflict recovery has the same race.

    Fix: Queue a follow-up People status refresh after the pending request finishes, or serialize provider mutations with People requests. Add a regression test with a delayed People response spanning a provider save.


Reviewers: 2x codex, codex (security), codex (test-value) | Synthesis: codex, 7s | Total: 12m0s

@rodboev

rodboev commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

Risk accepted: People lookups can miss a refresh when a provider save lands while its profiles are still loading.

You'd have to save a provider in the few milliseconds while People lookups is loading from the local daemon. If that happens, the next profile action says the settings changed on disk and asks you to reload. Clicking Reload fixes it, and nothing is lost or written with old data. Preventing it means queuing or serializing requests, which adds new state for a window normal use doesn't hit.

@rodboev
rodboev marked this pull request as ready for review November 1, 2026 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants