Skip to content

Enforce docstring coverage in lint gates#15

Merged
leynos merged 10 commits into
mainfrom
feat/interrogate-lint
Jun 15, 2026
Merged

Enforce docstring coverage in lint gates#15
leynos merged 10 commits into
mainfrom
feat/interrogate-lint

Conversation

@leynos

@leynos leynos commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

This branch adds interrogate to the generated template's development dependency set and wires docstring coverage into both generated and parent lint gates. The change makes missing docstrings fail during make lint, so rendered projects and the template repository enforce the same documentation standard.

There is no linked issue, roadmap task, or execplan for this branch.

Review walkthrough

Validation

  • make test: passed, 32 passed and 2 skipped.
  • make check-fmt: passed, 18 files already formatted.
  • make lint: passed, including interrogate at 100.0% coverage.
  • make typecheck: passed.

Notes

The rendered lint command targets the generated package name instead of a fixed package path, so projects using a package name other than lading receive the same docstring gate without a broken path.

Add `interrogate` to rendered project dev dependencies and wire it into
both rendered and parent `make lint` targets so docstring coverage is gated.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @leynos, you have reached your weekly rate limit of 2500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This pull request integrates the interrogate tool into the project's linting pipeline to enforce 100% docstring coverage. The change adds interrogate to development dependencies, configures it in template Makefiles and documentation, wires it into the root Makefile lint target, updates contract tests to validate the integration, adds an end-to-end integration test, and bumps the pyo3 dependency to 0.29.0.

Changes

Interrogate Docstring Coverage Enforcement

Layer / File(s) Summary
Template Dependencies and Interrogate Configuration
template/pyproject.toml.jinja, template/Makefile.jinja, template/AGENTS.md.jinja
Add interrogate to the development dependency group; configure lint-python target to run interrogate --fail-under 100 $(PYTHON_TARGETS) after ruff check; document the interrogate step in the lint-python workflow section.
Root Makefile Lint Target
Makefile
Extend the lint target to invoke interrogate --fail-under 100 tests/ via $(UV) --with interrogate.
Documentation Updates
docs/developers-guide.md, template/docs/developers-guide.md, template/docs/users-guide.md.jinja, docs/adr-001-template-quality-gates.md
Expand developer and user guides to explicitly document the lint pipeline: ruff check, then interrogate --fail-under 100 for docstring coverage, then pylint via the PyPy-backed shim installed by uv tool run; record the architectural decision in the quality gates ADR.
Contract Test Assertions
tests/helpers/agents_contracts.py, tests/helpers/pyproject_contracts.py, tests/helpers/makefile_contracts.py, tests/test_helpers.py
Assert that generated AGENTS.md and Makefiles include interrogate --fail-under 100 commands in lint targets; update pyproject contract to expect interrogate and pytest-timeout in dev dependencies; add docstring to normalise_target helper; assert parent Makefile lint includes interrogate invocation.
Integration Test
tests/test_interrogate_lint.py
Add end-to-end test that renders a generated project, runs make lint successfully with complete docstrings, appends an undocumented private function, re-runs make lint expecting failure, and validates interrogate failure markers and reduced coverage percentage.
Supporting Changes
template/{% if use_rust %}rust_extension{% endif %}/Cargo.toml.jinja, tests/test_github_actions_integration.py, tests/utilities.py
Bump pyo3 from 0.28.3 to 0.29.0; add docstrings to fake_run test helper and _resolved_socket_from_docker_host and _user_podman_socket socket utility functions.

Possibly Related PRs

  • leynos/cuprum#131: Adds interrogate --fail-under 100 to the lint/lint-python make target with equivalent dependency wiring and docstring coverage enforcement.
  • leynos/lading#109: Adds interrogate --fail-under 100 to the make lint workflow with identical tool integration immediately after the ruff check step.
  • leynos/stilyagi#13: Modifies the Makefile lint pipeline by appending additional linting steps to the lint target's command sequence.

Poem

Docstrings now have no escape,
Interrogate enforces shape,
100% coverage—or the build will fail,
Linting pipelines tell their tale,
Pure documentation—that's the holy grail.

Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Module-Level Documentation ❌ Error tests/test_interrogate_lint.py carries only a one-sentence module docstring ("Validate rendered docstring coverage lint behaviour.") that fails to clearly explain the module's purpose, utility, fun... Expand the module docstring in tests/test_interrogate_lint.py to document what the integration tests do, their strategy (rendering projects, running make lint, verifying Interrogate enforcement), and their role within the test suite, mat...
User-Facing Documentation ⚠️ Warning README.md does not document interrogate as a quality gate. Lines 14-16 and the mermaid diagram (lines 56-57) list tooling but omit interrogate, which is now mandatory. Update README.md lines 14-16 to include interrogate in the tooling list, and add an interrogate step to the mermaid diagram's Lint node to reflect the actual quality gates that generated projects execute.
✅ Passed checks (18 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the main change: enforcing docstring coverage in lint gates via interrogate integration, which aligns perfectly with the core changeset across template files, makefiles, and tests.
Description check ✅ Passed The description provides relevant context: interrogate addition to dev dependencies, lint gate wiring in templates and parent repo, documentation updates, validation results, and a design note about scope consistency.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Testing (Overall) ✅ Passed All new functionality is guarded by substantive, rigorous tests that would fail if the implementation were removed or bypassed. The test suite covers all five key areas: test_generated_make_lint_en...
Developer Documentation ✅ Passed Developer documentation adequately covers the new interrogate tooling requirement. The developers-guide documents both parent and generated lint gates, ADR-001 records the architectural decision, a...
Testing (Unit And Behavioural) ✅ Passed Tests comprehensively cover the feature: new end-to-end test exercises make lint workflow with real subprocess and validates both success (100% docstring coverage) and failure (missing docstrings)...
Testing (Property / Proof) ✅ Passed This PR adds tooling configuration (interrogate) and wiring into lint gates—deterministic, not a mathematical invariant. The test strategy (integration, contract, regression) appropriately validate...
Testing (Compile-Time / Ui) ✅ Passed The new integration test (test_interrogate_lint.py) avoids snapshot testing in favour of direct assertions on business logic (coverage percentage, failure status), aligning with AGENTS.md guidance...
Unit Architecture ✅ Passed Changes maintain clear separation: lint targets remain pure query operations; interrogate is injectable via $(PYTHON_TARGETS); no hidden state, globals, or implicit dependencies introduced; fallibi...
Domain Architecture ✅ Passed PR modifies only build tooling, linting infrastructure, and documentation. No domain logic, adapters, repositories, commands, or business invariants are touched. The check is not applicable to this...
Observability ✅ Passed This PR makes no changes to operational behaviour. It adds a development linting tool and updates build-time lint targets; no production code, logging, metrics, tracing, or alerting systems are alt...
Security And Privacy ✅ Passed No secrets, credentials, injection risks, unsafe permissions, or sensitive data exposure introduced. Interrogate is a safe read-only static analysis tool for docstring coverage with no security imp...
Performance And Resource Use ✅ Passed Pull request avoids performance regressions: interrogate runs on bounded PYTHON_TARGETS with fixed --fail-under 100; test contracts iterate over small constant sets; Makefile parsing is O(n) for bo...
Concurrency And State ✅ Passed The PR adds interrogate linting to the template build pipeline without introducing concurrency, shared state, locks, async execution, or ordering concerns—only sequential linting checks.
Architectural Complexity And Maintainability ✅ Passed PR integrates interrogate (maintained third-party docstring tool) directly into lint gates with proportional, no-abstraction changes: Makefile (+1 line each), pyproject.toml.jinja (+1 line), tests...
Rust Compiler Lint Integrity ✅ Passed Rust code changes preserve compiler lint integrity: no blanket #[allow(...)] suppressions present, the single #[expect(...)] attribute is properly justified and narrowly scoped to a PyO3 API constr...
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/interrogate-lint

Comment @coderabbitai help to get the list of available commands and usage tips.

`cargo audit` in the generated CI workflow fails on pyo3 0.28.3, which
is affected by RUSTSEC-2026-0176 (out-of-bounds read in `nth` /
`nth_back` for `PyList` and `PyTuple` iterators). This caused the
`Audit dependencies` step to fail in the act validation test before
the coverage step could run.

The advisory's fix is pyo3 >= 0.29.0. The rendered extension crate
compiles unchanged against 0.29.0 (the `Bound` module API is stable
across the bump), and `cargo audit` on the rendered lockfile is clean.
@pandalump pandalump marked this pull request as ready for review June 12, 2026 18:35

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/helpers/pyproject_contracts.py`:
- Around line 35-43: Add "pytest-timeout" to the required dev-dependency list
used in the for loop in tests/helpers/pyproject_contracts.py (the list iterated
by the variable dependency) so the contract asserts it exists; update the list
to include "pytest-timeout" alongside "pytest", "pytest-xdist", etc., ensuring
the contract fails if that dependency is missing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 403df03f-9968-49aa-9a19-ef1590422fb8

📥 Commits

Reviewing files that changed from the base of the PR and between 0f62dca and edb85d5.

📒 Files selected for processing (11)
  • Makefile
  • template/AGENTS.md.jinja
  • template/Makefile.jinja
  • template/pyproject.toml.jinja
  • template/{% if use_rust %}rust_extension{% endif %}/Cargo.toml.jinja
  • tests/helpers/agents_contracts.py
  • tests/helpers/makefile_contracts.py
  • tests/helpers/pyproject_contracts.py
  • tests/test_github_actions_integration.py
  • tests/test_helpers.py
  • tests/utilities.py

Comment thread tests/helpers/pyproject_contracts.py
Require `pytest-timeout` in the rendered pyproject contract so the
existing template dependency cannot be dropped without a failing test.
@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@template/Makefile.jinja`:
- Line 139: The interrogate command on line 139 of the lint-python target uses
{{ package_name }} as its target, which excludes tests from docstring coverage
measurement. This is inconsistent with the ruff check and pylint commands on the
same target, which both use $(PYTHON_TARGETS). Replace {{ package_name }} with
$(PYTHON_TARGETS) in the interrogate command to ensure consistent coverage
metrics across all linters and include test code in the docstring coverage
measurement.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ac278312-1511-41ef-aa60-a34b388ae17f

📥 Commits

Reviewing files that changed from the base of the PR and between 0f62dca and a44bfed.

📒 Files selected for processing (11)
  • Makefile
  • template/AGENTS.md.jinja
  • template/Makefile.jinja
  • template/pyproject.toml.jinja
  • template/{% if use_rust %}rust_extension{% endif %}/Cargo.toml.jinja
  • tests/helpers/agents_contracts.py
  • tests/helpers/makefile_contracts.py
  • tests/helpers/pyproject_contracts.py
  • tests/test_github_actions_integration.py
  • tests/test_helpers.py
  • tests/utilities.py

Comment thread template/Makefile.jinja Outdated
Update parent and generated project documentation for the Interrogate
coverage check, and add a rendered-project behavioural test proving
`make lint` passes with complete docstrings and fails when Interrogate
finds missing private docstring coverage.
@leynos

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

Run generated Interrogate linting against `$(PYTHON_TARGETS)` so its
coverage scope matches the Python lint target set. Update the generated
AGENTS guidance, user and developer docs, command contracts, and the
behavioural coverage expectation for the wider target set.
@leynos

leynos commented Jun 14, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai pause

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews paused.

Align the generated AGENTS contract with the rendered Python target list
and document the generated `lint-python` Interrogate scope in the parent
and template developer guides.
@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_interrogate_lint.py`:
- Around line 79-80: The assertion on line 79-80 hard-codes a specific coverage
percentage value of 83.3%, making the test brittle when baseline docstring
counts change. Instead of checking for the exact string "actual: 83.3%" in the
output, parse the percentage value from the output and assert that it is less
than 100.0 to verify that docstring coverage has been reduced while remaining
resilient to changes in the baseline counts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d418f781-7ba9-41b2-b9e5-298470ddad66

📥 Commits

Reviewing files that changed from the base of the PR and between a44bfed and fad9858.

📒 Files selected for processing (7)
  • docs/developers-guide.md
  • template/AGENTS.md.jinja
  • template/Makefile.jinja
  • template/docs/developers-guide.md
  • template/docs/users-guide.md.jinja
  • tests/helpers/agents_contracts.py
  • tests/test_interrogate_lint.py

Comment thread tests/test_interrogate_lint.py Outdated
@leynos

leynos commented Jun 14, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai pause

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews paused.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== template/Makefile.jinja: interrogate line ==="
grep -n "interrogate\|PYTHON_TARGETS\|package_name" template/Makefile.jinja | grep -i "interrogate"

echo ""
echo "=== tests/helpers/agents_contracts.py: interrogate references ==="
grep -n "interrogate\|python_targets\|package_name" tests/helpers/agents_contracts.py

echo ""
echo "=== template/docs/users-guide.md.jinja: interrogate references ==="
grep -n "interrogate\|PYTHON_TARGETS\|package_name" template/docs/users-guide.md.jinja

echo ""
echo "=== docs/developers-guide.md: interrogate and lint-python references ==="
grep -n "interrogate\|lint-python\|Ruff\|Pylint" docs/developers-guide.md

echo ""
echo "=== tests/helpers/makefile_contracts.py: interrogate references ==="
grep -n "interrogate\|PYTHON_TARGETS" tests/helpers/makefile_contracts.py

echo ""
echo "=== template/AGENTS.md.jinja: interrogate references ==="
grep -n "interrogate\|PYTHON_TARGETS\|package_name" template/AGENTS.md.jinja

Length of output: 2818



@leynos: All 6 checks are now fully resolved. Here is the verified status:

Check Status Evidence
Unit Architecture ❌ Resolved template/Makefile.jinja line 139 now reads $(UV_ENV) $(UV) run interrogate --fail-under 100 $(PYTHON_TARGETS)
Testing (Overall) ❌ Resolved tests/helpers/agents_contracts.py lines 101 and 103 both assert f"interrogate --fail-under 100 {python_targets}" where python_targets = f"{package_name} tests"
User-Facing Documentation ⚠️ Resolved template/docs/users-guide.md.jinja line 18 now references $(PYTHON_TARGETS)
Developer Documentation ⚠️ Resolved docs/developers-guide.md lines 54–55 describe lint-python as running Ruff, interrogate --fail-under 100 across $(PYTHON_TARGETS), and Pylint
Testing (Unit And Behavioural) ⚠️ Resolved Same root fixes as the two errors above
Architectural Complexity And Maintainability ⚠️ Resolved Same root fix as the two errors above

No further work is required. The scope of interrogate is now consistent with ruff and pylint across the Makefile template, contract tests, and both documentation files.

Parse the Interrogate actual coverage percentage and assert it drops below
100% instead of pinning the behavioural test to a specific rendered-project
baseline count.
@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

Update the template quality gate decision record so the Python lint tier
mentions Interrogate with `--fail-under 100` alongside Ruff and Pylint.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@template/AGENTS.md.jinja`:
- Line 85: On line 85 in the template file, replace the literal expansion `{{
package_name }} tests` with the variable reference `$(PYTHON_TARGETS)` to
maintain consistency with the established pattern used on lines 82, 84, and 87
throughout the file, which all reference variables rather than expansions.

In `@tests/helpers/agents_contracts.py`:
- Line 101: In the AGENTS.md contract definition, replace the f-string with
expanded variable `f"interrogate --fail-under 100 {python_targets}"` with a
plain string using makefile-style variable reference `"interrogate --fail-under
100 $(PYTHON_TARGETS)"` to maintain consistency with the ruff check contract
pattern that documents commands using variable references instead of Python
variable expansions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1be7eacc-604c-430b-890a-0f69f8a3b36e

📥 Commits

Reviewing files that changed from the base of the PR and between a44bfed and b766307.

📒 Files selected for processing (7)
  • docs/developers-guide.md
  • template/AGENTS.md.jinja
  • template/Makefile.jinja
  • template/docs/developers-guide.md
  • template/docs/users-guide.md.jinja
  • tests/helpers/agents_contracts.py
  • tests/test_interrogate_lint.py

Comment thread template/AGENTS.md.jinja Outdated
Comment thread tests/helpers/agents_contracts.py Outdated
@leynos

leynos commented Jun 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

leynos added 2 commits June 15, 2026 09:16
Keep generated AGENTS guidance consistent with the surrounding Makefile
command examples by documenting the Interrogate target as
`$(PYTHON_TARGETS)`, and update the AGENTS contract to assert that form.
Expand the Interrogate behavioural test module docstring and include the
Interrogate docstring gate in the README tooling list and generated quality
gate diagram.
@leynos

leynos commented Jun 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following failed checks now been resolved?

If further work is required, please provide an AI agent prompt for the remaining work to be done to address these failures.

Do not treat warnings as optional or aspirational. Where a change is out of scope for this PR, propose a GitHub issue unless one exists already. (Treat documentation and validation coverage as in scope).

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Module-Level Documentation ❌ Error tests/test_interrogate_lint.py carries only a one-sentence module docstring ("Validate rendered docstring coverage lint behaviour.") that fails to clearly explain the module's purpose, utility, fun... Expand the module docstring in tests/test_interrogate_lint.py to document what the integration tests do, their strategy (rendering projects, running make lint, verifying Interrogate enforcement), and their role within the test suite, mat...
User-Facing Documentation ⚠️ Warning README.md does not document interrogate as a quality gate. Lines 14-16 and the mermaid diagram (lines 56-57) list tooling but omit interrogate, which is now mandatory. Update README.md lines 14-16 to include interrogate in the tooling list, and add an interrogate step to the mermaid diagram's Lint node to reflect the actual quality gates that generated projects execute.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== tests/test_interrogate_lint.py: module docstring ==="
head -20 tests/test_interrogate_lint.py

echo ""
echo "=== README.md: lines 10-65 ==="
sed -n '10,65p' README.md

echo ""
echo "=== README.md: full interrogate references ==="
grep -n "interrogate\|Interrogate" README.md

Length of output: 3611



@leynos: Both checks are fully resolved.

Check Status Evidence
Module-Level Documentation ❌ Resolved tests/test_interrogate_lint.py now carries a nine-line module docstring covering purpose, strategy (clean render then mutation), and role within the test suite — well beyond the original single sentence
User-Facing Documentation ⚠️ Resolved README.md line 17 documents Interrogate as a 100% docstring-coverage gate in prose, line 36 lists it alongside the other generated-project tooling, and line 60 adds Lint --> Interrogate[interrogate --fail-under 100] to the Mermaid quality-gate diagram

No further work is required on this PR.

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