Skip to content

Upgrade dependencies, add paws CI, and specify the transcription/GPU roadmap - #22

Merged
mbround18 merged 12 commits into
mainfrom
chore/deps-ci-speckit
Sep 9, 2026
Merged

mbround18 merged 12 commits into
mainfrom
chore/deps-ci-speckit

Conversation

@mbround18

Copy link
Copy Markdown
Owner

Four independent commits: a dependency refresh, the repo's first CI workflow, Spec Kit init, and specs for the transcription/GPU work.

1. Dependency upgrades (39d6a2e)

Every direct crate bumped to its latest compatible release, both lockfiles refreshed.

Three majors needed source changes:

Crate Change
reqwest 0.12 → 0.13 rustls-tls feature renamed rustls
songbird 0.5 → 0.6 decode_sample_rate/decode_channels removed; both now live in a DecodeConfig carried by DecodeMode::Decode
poise 0.6 → 0.7 event_handler takes (FrameworkContext, &FullEvent) instead of four args

Two held back deliberately:

  • whisper-rs stays 0.15.1 — 0.16 requires whisper-rs-sys ^0.15, but vendor/whisper-rs-sys is 0.14.1 and patched in globally. Needs whisper.cpp re-vendored first.
  • symphonia stays 0.5.5 — songbird 0.6 pins symphonia ^0.5.2; 0.6 would duplicate the crate and break type sharing.

Verified locally: cargo check --all-targets, clippy -D warnings, cargo test, cargo fmt --check, uv lock --check.

2. paws CI workflow (d37a8e9)

The repo had no workflows at all. Scaffolded with paws workflow generate (detected rust + python + docker), then wired for real publishing to ghcr.io/mbround18/hammock.

Pushes on a push to main or a tag; every other build is build-only unless the PR carries the canary label.

3. Spec Kit init (004510f)

.specify/ scaffold committed. .claude/ is gitignored — the agent skills there are machine-local and the CLI warns agents may leave credentials in that directory. A fresh clone re-runs specify init --here --integration claude to restore the slash commands; the specs and templates travel with the repo regardless.

4. Constitution + specs (d77b03c)

Constitution ratified at v1.0.0, with principles drawn from how this codebase actually fails rather than generic best practice: the 20ms voice tick path must never block and must shed load explicitly; anything that can move transcript output requires a fixture comparison; CPU stays first-class and GPU unavailability falls back rather than failing startup; tunables are env vars with CPU-safe defaults; an error path that neither counts nor logs does not exist.

Four specs, in dependency order:

  • 001-gpu-accelerated-builds — the cuda feature exists but the published image is built without it, on a base with no GPU toolchain. The GPU path is currently unreachable code and WHISPER_USE_GPU defaults off.
  • 002-transcription-worker-throughput — chunks process strictly one at a time with a fresh decoder state each; a full queue blocks submission inside the voice event handler, losing audio for the whole channel.
  • 003-vad-utterance-segmentation — audio is cut at a fixed sample count regardless of speech, severing words and discarding context.
  • 004-transcription-decoding-quality — decoding runs at its least accurate settings (smallest model, greedy best-of-1, no fallback or thresholds).

Two requirements came out of checklist review rather than the original analysis, both cases where a feature could pass all its own criteria while silently regressing something else:

  • 002 FR-003 — reusing decoder state risks one speaker's residue leaking into another's transcript.
  • 004 FR-013 — confidence fallback re-decodes the same audio, so it needs a per-utterance bound or an accuracy win can push the pipeline permanently behind real time.

Reviewer notes

  • First CI run will be slow. whisper.cpp builds from scratch with no warm Dagger cache.
  • This PR does not push an image. Publishing is gated to main/tag pushes, so the docker step builds only here. The first real publish happens on merge — worth watching that one.
  • All four specs depend on an audio fixture set that doesn't exist yet. Creating it is assigned to 001 and flagged as an open dependency in every checklist. No spec is verifiable until it lands.
  • No behavior changes beyond the dependency upgrade; the specs are documents.

🤖 Generated with Claude Code

mbround18 and others added 4 commits September 8, 2026 15:24
Bump every direct crate to its latest compatible release and refresh both
lockfiles.

Major upgrades needing source changes:

- reqwest 0.12 -> 0.13: the `rustls-tls` feature was renamed `rustls`.
- songbird 0.5 -> 0.6: `decode_sample_rate`/`decode_channels` are gone;
  both now live in a `DecodeConfig` carried by `DecodeMode::Decode`.
- poise 0.6 -> 0.7: `event_handler` takes `(FrameworkContext, &FullEvent)`
  instead of four arguments; ctx and data come off the framework context.

Held back deliberately:

- whisper-rs stays at 0.15.1. 0.16 requires whisper-rs-sys ^0.15, but
  vendor/whisper-rs-sys is 0.14.1 and is patched in globally, so the bump
  needs whisper.cpp re-vendored first.
- symphonia stays at 0.5.5. songbird 0.6 pins symphonia ^0.5.2, so 0.6
  would duplicate the crate and break type sharing.

uv.lock refreshed as well (torch 2.9.1 -> 2.14.0, CUDA 12 -> 13 wheels).

Verified with cargo check --all-targets, clippy -D warnings, cargo test,
cargo fmt --check, and uv lock --check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The repo had no workflows at all. Scaffolded with `paws workflow generate`,
which detected the rust, python, and docker ecosystems, then wired up for
real publishing:

- builds and tests both the Rust and Python halves via `paws ci`
- publishes the image to ghcr.io/mbround18/hammock, authenticating with
  the workflow's own github.token
- tags with --with-latest, --tag-rollup, --tag-branch and --tag-pr, and
  passes PR labels through so the canary-label gate works

Pushes happen on a push to main or a tag; every other build is build-only
unless the PR carries the `canary` label.

Image name taken from compose.yml, pointed at GHCR.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ran `specify init --here --integration claude`, which scaffolds .specify/
with the spec/plan/tasks/checklist templates, the helper scripts those
commands call, and the workflow registry.

The agent skills it installs under .claude/ are machine-local tooling, and
the CLI warns that agents may leave credentials in that directory, so
.claude/ is gitignored rather than committed. .specify/feature.json is
likewise excluded, by the .gitignore the CLI ships, since it is a
per-checkout pointer to whichever feature you are currently working on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ratify the constitution at v1.0.0. Its five principles are drawn from how
this codebase actually fails rather than from generic best practice: the
20ms voice tick path must never block and must shed load explicitly;
anything that can move transcript output requires a fixture comparison;
CPU stays a first-class target and GPU unavailability falls back rather
than failing startup; tunables are env vars with CPU-safe defaults; and an
error path that neither counts nor logs does not exist.

Specify the four transcription upgrades, in dependency order:

- 001-gpu-accelerated-builds: the cuda feature exists but the published
  image is built without it on a base with no GPU toolchain, so the GPU
  path is unreachable code. Publish an accelerated variant, keep the CPU
  variant first-class, make fallback diagnosable.
- 002-transcription-worker-throughput: chunks are processed strictly one
  at a time with a fresh decoder state each, and a full queue blocks
  submission inside the voice event handler, losing audio for the whole
  channel. Concurrent workers, reused state, non-blocking submission with
  counted load shedding.
- 003-vad-utterance-segmentation: audio is cut at a fixed sample count
  regardless of speech, severing words and discarding context. Derive
  boundaries from speech activity instead.
- 004-transcription-decoding-quality: decoding runs at its least accurate
  settings. Larger model, multi-candidate decoding, confidence fallback,
  context carryover, vocabulary hinting.

Each spec carries a validated requirements checklist recording what failed
review and what changed. Two requirements came out of that review rather
than the original analysis: 002 FR-003, because reusing decoder state
risks one speaker's residue leaking into another's transcript while every
throughput criterion still passes; and 004 FR-013, because confidence
fallback re-decodes the same audio and needs a per-utterance bound or an
accuracy win can push the pipeline permanently behind real time.

All four specs depend on an audio fixture set with reference transcripts
that does not exist yet. Creating it is assigned to 001 and flagged as an
open dependency in every checklist.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 8, 2026 22:28
The first CI run failed immediately:

    Error: provisioning failed for: python: failed to spawn `uv`
    — is it installed and on PATH?

`paws ci` provisions a host toolchain for every ecosystem it detects in
the repo, not only the one named by --toolchain. This repo has both a
Cargo.toml and a pyproject.toml, so `paws ci --toolchain rust` provisions
python too, which shells out to `uv`. ubuntu-latest ships rustup but not
uv, so the rust step failed before building anything and both later steps
were skipped.

`paws provision` cannot fix this itself — it uses uv to install a python
version, so uv has to already exist. Confirmed by reproducing both the
failure and the fix locally against a PATH matching the runner's.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The new CI workflow references PR-only context (github.event.pull_request.labels) on push/tag events and can fail those runs unless guarded.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR refreshes the Rust dependency set, introduces the repo’s first GitHub Actions CI workflow (via paws), and adds Spec Kit scaffolding plus a set of roadmap specs for GPU/transcription improvements.

Changes:

  • Bump direct Rust crates (notably reqwest/songbird/poise majors) and update src/main.rs for the new APIs.
  • Add a paws-generated CI workflow to run Rust/Python checks and build/publish images to GHCR.
  • Initialize Spec Kit project scaffolding and add feature specs/checklists for the transcription/GPU roadmap.
File summaries
File Description
src/main.rs Updates Songbird decode config and Poise event handler signature for upgraded dependencies.
Cargo.toml Refreshes direct crate versions and reqwest feature flags.
.github/workflows/paws.yml Adds CI workflow for Rust/Python + docker build/publish via paws.
.gitignore Ignores .claude/ and normalizes .venv/ entry.
specs/001-gpu-accelerated-builds/spec.md Adds spec describing publishable GPU-capable image variant requirements.
specs/001-gpu-accelerated-builds/checklists/requirements.md Adds requirements-quality checklist for spec 001.
specs/002-transcription-worker-throughput/spec.md Adds spec for throughput/concurrency + load shedding constraints.
specs/002-transcription-worker-throughput/checklists/requirements.md Adds requirements-quality checklist for spec 002.
specs/003-vad-utterance-segmentation/spec.md Adds spec for speech-aware segmentation and associated metrics.
specs/003-vad-utterance-segmentation/checklists/requirements.md Adds requirements-quality checklist for spec 003.
specs/004-transcription-decoding-quality/spec.md Adds spec for decoding-quality improvements (fallbacks, thresholds, context).
specs/004-transcription-decoding-quality/checklists/requirements.md Adds requirements-quality checklist for spec 004.
.specify/workflows/workflow-registry.json Registers bundled Spec Kit workflow metadata.
.specify/workflows/speckit/workflow.yml Adds the “Full SDD Cycle” workflow definition (specify→plan→tasks→implement).
.specify/templates/tasks-template.md Adds Spec Kit tasks template.
.specify/templates/spec-template.md Adds Spec Kit spec template.
.specify/templates/plan-template.md Adds Spec Kit plan template.
.specify/templates/constitution-template.md Adds Spec Kit constitution template.
.specify/templates/checklist-template.md Adds Spec Kit checklist template.
.specify/scripts/bash/setup-tasks.sh Adds Spec Kit helper for tasks setup and template resolution.
.specify/scripts/bash/setup-plan.sh Adds Spec Kit helper for plan setup.
.specify/scripts/bash/resolve-template.sh Adds Spec Kit helper for resolving templates (with JSON mode).
.specify/scripts/bash/create-new-feature.sh Adds Spec Kit helper to create numbered/timestamped feature directories.
.specify/scripts/bash/common.sh Adds shared Spec Kit bash utilities (repo root detection, template stacking, JSON escape, etc.).
.specify/scripts/bash/check-prerequisites.sh Adds consolidated Spec Kit prerequisites checker (paths/docs/templates).
.specify/memory/constitution.md Adds the project constitution (principles + CI/quality gates + governance).
.specify/memory/.constitution-template.json Records constitution template provenance hash/source.
.specify/integrations/speckit.manifest.json Records installed speckit integration file hashes/metadata.
.specify/integrations/claude.manifest.json Records installed claude integration file hashes/metadata.
.specify/integration.json Stores Spec Kit integration selection/settings.
.specify/init-options.json Stores Spec Kit init options (integration/version/etc.).
.specify/.gitignore Ignores machine-local Spec Kit state (feature.json) and local extension overrides.
Review details
  • Files reviewed: 31/34 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/workflows/paws.yml
Comment thread .github/workflows/paws.yml
Copilot AI review requested due to automatic review settings September 8, 2026 22:33
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
mbround18 and others added 2 commits September 8, 2026 15:36
`astral-sh/setup-uv@v10` does not resolve — the action publishes only
exact version tags (v10.0.1, v10.0.0, v9.0.0, ...) with no floating major
alias, so the workflow failed during "Set up job" before running a step:

    Unable to resolve action `astral-sh/setup-uv@v10`,
    unable to find version `v10`

Pinned to the v10.0.1 commit instead. A SHA is the right pin for a
third-party action that installs a toolchain, and Renovate tracks the
trailing version comment to keep it current.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Keeps the Copilot Autofix's goal — PR label names are attacker-controlled
on a fork PR and must not be interpolated into a run script — while fixing
two problems with how it got there.

The canary gate could never fire. The collect step wrote PAWS_PR_LABELS to
$GITHUB_ENV, but the docker step also declared `PAWS_PR_LABELS: ""` in its
own env block, and a step's env takes precedence over anything a previous
step exported through $GITHUB_ENV. The variable was therefore always empty
at the point it was read, so --labels received nothing and a `canary`
label would have been silently ignored.

The injection was moved rather than removed. The collect step still
expanded ${{ join(...) }} inside a double-quoted `echo`, where a label
named `$(...)` or containing backticks is still command-substituted by the
shell before echo runs.

Setting the value directly in the docker step's env fixes both: the
expansion happens when the environment is built rather than inside a
shell, nothing overrides it, and the run script only references
"$PAWS_PR_LABELS". The separate collect step is no longer needed — on a
non-PR event `join` yields an empty string, which is what the `if` guard
was there to produce.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The CI workflow references a mutable @main branch for a third-party action and should be pinned to a tag/SHA for reproducibility and supply-chain safety.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/paws.yml:20

  • The workflow pins mbround18/paws/actions/paws-up to the main branch, which is mutable and can change CI behavior (or be compromised) without any change in this repository. Pinning to a tag or commit SHA makes CI runs reproducible and reduces supply-chain risk.
  • Files reviewed: 31/34 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 8, 2026 22:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

CI uses a floating GitHub Action ref (@main) for a third-party action, which should be pinned to a tag or commit SHA to avoid supply-chain drift.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/paws.yml:20

  • This workflow uses a floating ref for a third-party action (mbround18/paws/actions/paws-up@main). Using a branch ref means the CI behavior can change without any change in this repo, and it also weakens supply-chain guarantees compared to pinning to a tag or (preferably) a commit SHA.
  • Files reviewed: 31/34 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

`paws ci --toolchain rust` cannot build this project. It runs the pipeline
in a bare rust:1-bookworm container with no system packages, and the build
died in libopus_sys' build script:

    cargo:info=`pkg_config` could not find `Opus`.
    cargo:info=Building Opus via CMake.
    failed to execute command: No such file or directory (os error 2)
    is `cmake` not installed?

Both native dependencies need a C/C++ toolchain that image lacks:
libopus_sys builds Opus via CMake when pkg-config can't find it, and
whisper-rs-sys needs cmake plus libclang for bindgen. These are exactly
the packages this repo's own Dockerfile installs.

paws offers no hook for a consumer repo to add system packages to the ci
pipeline — the only alternate image it can use is the embedded
builders/rust one behind --coverage, which is the same base plus
cargo-llvm-cov and no closer to what this project needs.

So the Rust gates run natively on the runner: the same four checks paws
would have run (fmt --check, clippy -D warnings, build, test), with
--locked added, which also closes the lockfile-drift gap the constitution
asks for and paws' pipeline does not cover. Python and docker still go
through paws, and the docker step continues to compile the release binary
inside the project's own Dockerfile.

Worth raising upstream: paws' rust pipeline can only build projects with
no native dependencies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 8, 2026 22:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The CI workflow likely breaks on push/tag events due to join(github.event.pull_request.labels.*.name, ',') being evaluated when pull_request is absent.

Review details

Suppressed comments (3)

Previously missed (1) — in code that hasn't changed since the last review.

.github/workflows/paws.yml:13

  • Workflow-level packages: write applies to all events (including pull_request). To follow least-privilege, consider splitting image publishing into a separate job that runs only when publishing is intended (push to main/tags and/or explicitly labeled canary) and grant packages: write only to that job.

This issue also appears in the following locations of the same file:

  • line 20
  • line 64

.github/workflows/paws.yml:64

  • ${{ join(github.event.pull_request.labels.*.name, ',') }} is evaluated on push/tag events too, where github.event.pull_request is absent; join() expects an array and can error on null/non-array values, which would break main/tag CI runs.
          PAWS_PR_LABELS: ${{ join(github.event.pull_request.labels.*.name, ',') }}

.github/workflows/paws.yml:20

  • mbround18/paws/actions/paws-up@main is pinned to a moving ref. If that action changes unexpectedly (or is compromised), CI behavior can change without any change in this repo; prefer pinning to a tag or full commit SHA.
      - uses: mbround18/paws/actions/paws-up@main
  • Files reviewed: 31/34 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

That release includes "provision only the toolchain that was actually
asked for", which fixes the failure from the first CI run: `paws ci
--toolchain rust` was provisioning python as well, purely because a
pyproject.toml exists, and dying when uv was not on PATH.

The setup-uv step stays, but for its own reason now rather than as a
workaround for the rust step: `paws ci --toolchain python` genuinely needs
uv on the host, and paws cannot bootstrap it, since it uses uv to install
a python version. Comment updated to say that instead.

This release does not affect the cmake failure. It changes only
paws-cli-core and paws-provision; paws-rust still runs the pipeline in a
bare rust:1-bookworm with no C/C++ toolchain, so the native Rust gates
added in the previous commit stay as they are.

Pinned to the exact prerelease rather than the action's `latest` default,
so a future paws release cannot change this repo's CI without a commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 8, 2026 22:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The dependency-related code updates match the described upstream API changes, CI gates are in place, and the added Spec Kit/spec documents do not introduce runtime behavior changes.

Review details
  • Files reviewed: 31/34 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

`paws ci --toolchain python` runs `uv sync --frozen`, `uv build`, then
`uv run pytest`. The first two passed; the third failed:

    error: Failed to spawn: `pytest`
      Caused by: No such file or directory (os error 2)

That pipeline is for a Python distribution, and this repo is not one.
pyproject.toml exists only to pin openai-whisper into the runtime venv, so
there is no pytest dependency and no Python test suite — adding pytest
would just move the failure to exit code 5, "no tests collected".

`uv build` was a symptom of the same mismatch: it packaged src/, which is
the Rust source tree, into a hammock-0.1.0-py3-none-any.whl that means
nothing and nothing consumes.

What is worth gating is that uv.lock still agrees with pyproject.toml,
which `uv lock --check` verifies in about a second. Real installability is
already covered by the Docker build, which runs `uv sync --locked` against
the same lockfile.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 8, 2026 23:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The CI workflow references a third-party GitHub Action via a mutable @main ref, which should be pinned (preferably to a commit SHA) to avoid supply-chain and reproducibility risk.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 31/34 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines +20 to +22
- uses: mbround18/paws/actions/paws-up@main
with:
version: v0.0.1-prerelease.43
`paws docker` builds through Dagger, and Dagger could not convert this
Dockerfile at all:

    failed to convert Dockerfile LLB to Dagger ID: llbtodagger:
    unsupported op "file.mkdir": mkdir without makeParents is unsupported

Bisected to one construct — a cache mount carrying uid=/gid=:

    cache mount with uid=/gid=          FAIL
    same mount without uid=/gid=        OK
    USER bot + mount without uid=/gid=  OK
    pre-created dir, then uid=/gid=     FAIL

BuildKit emits a file.mkdir without makeParents to set up an
ownership-scoped cache mount, and Dagger's converter cannot represent that
op. The uid=/gid= were there because the step runs as `bot`, who otherwise
cannot write to a root-owned mount. The two apt cache mounts are fine —
they have no uid=/gid=.

Removing it does not change the image. Cache mounts never become part of
the result, so this only forgoes partial uv download reuse on builds where
uv.lock itself changed; when the lockfile is unchanged the whole step
still hits the layer cache.

Verified locally: `dagger core host directory --path=. docker-build
--dockerfile=./Dockerfile sync` reproduced the failure with the identical
op hash beforehand, and exits 0 after.

Worth reporting upstream to Dagger — an ownership-scoped cache mount is
ordinary Dockerfile usage for any image that builds as a non-root user.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 8, 2026 23:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The CI workflow uses a third-party action pinned to @main rather than an immutable ref, which is a supply-chain/reproducibility risk.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 32/35 changed files
  • Comments generated: 1
  • Review effort level: Lite

steps:
- uses: actions/checkout@v7

- uses: mbround18/paws/actions/paws-up@main
@mbround18
mbround18 merged commit 4a2bdae into main Sep 9, 2026
2 checks passed
@mbround18
mbround18 deleted the chore/deps-ci-speckit branch September 9, 2026 00:13
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