Skip to content

Every public record keeps a read-only copy of its own of the arrays it holds, however it was built - #948

Merged
jmrplens merged 1 commit into
fix/subscripts-follow-the-standardfrom
fix/records-copy-at-construction
Oct 7, 2026
Merged

jmrplens merged 1 commit into
fix/subscripts-follow-the-standardfrom
fix/records-copy-at-construction

Conversation

@jmrplens

@jmrplens jmrplens commented Oct 7, 2026

Copy link
Copy Markdown
Owner

The library's functions already copy the arrays a result keeps, but a record built by hand, by calling its class directly (room.ImpulseResponseResult(ir=measured, ...), or aircraft.AnpNpdCurves(...) filled from your own NPD data), still kept the array you handed it, so editing that array afterwards edited the record. With this change every one of the 428 public records that can hold an array copies it at construction, whoever builds it.

They all inherit one private base, OwnsArrays in phonometry._internal.frozen. When the record is built it replaces every array it was given, also inside a tuple, a list or any mapping, by a read-only C-ordered copy of its own, and only then runs the class's own __post_init__, which is composed around the copy rather than replaced, so the checks and normalisations a class already had read the record's copy. Your array keeps its writeable flag and nothing you do to it afterwards reaches the record. A mapping that holds an array comes back as a plain dict (a MappingProxyType as one), never as your own container.

A record held whole inside another one is left as it is and answers for its own arrays, and an io.Signal is no exception. The seven results that hand a waveform back as a Signal (filters.OctaveFilterResult, signals.EnvelopeResult, signals.ResampledSignalResult, signals.AlignedImpulseResponseResult, signals.SynchronousAverageResult, environment.DirectSoundSubtraction and underwater.PileStrikeResult) hold one of their own when the library builds them, whose samples stay writeable like any Signal's, and hold your own when you build them by hand around it. A Signal handed to a field that takes an array is copied like any array, and its own samples stay writeable.

The functions of the library no longer copy an array they hand to such a record, and the records' own checks no longer copy one either, so no array is copied twice: 340 read_only_copy, 199 .copy() and 10 .astype calls are gone.

What breaks, and how to migrate. Every array a result holds, apart from the samples of a Signal it holds, now refuses in-place writes, the arrays it computed as well as the ones it was given; writing into one raises ValueError, so copy it first (edited = result.levels.copy()), as the migration guide shows. A record you build by hand no longer follows later edits of the array you gave it, so fill the array before you build the record. A mapping field that held arrays comes back as a plain dict rather than your OrderedDict, defaultdict or own mapping class. A record built from a Fortran-ordered or broadcast array holds a C-ordered copy. The migration guide (docs/start/upgrading.md and its two site twins) and the changelog say all of this, and the sentence the previous change wrote about hand-built records now says they copy too.

The cost. The copy takes no time worth the name beside the computation: 43 ms for the 269 MB that a 400 by 600 cell FDTD run with a snapshot every ten steps holds, out of 7 s. While the record is being built the solver's arrays and the record's copy are both alive, though, so the peak memory of the largest results grows by their size: from 587 to 855 MB for that FDTD run, from 202 to 333 MB for a 20 km underwater parabolic equation on 4096 depths in 5 m steps, from 207 to 287 MB for an elastic FDTD run on 200 by 500 cells with its snapshots, and from 112 to 139 MB for a 1 kHz atmospheric GFPE field 3 km long and 100 m high. Those are the places where the copy is large.

The gate. make array-aliasing and its CI job now also fail on a public record that can hold an array and does not inherit the base, and on a copy written around an array handed to one (read_only_copy, np.copy, .astype, read_only around a copy, or .copy() on a field that only holds an array) or made first into a local name that is only read before it is handed over. Run against the tree before this change it fails on 428 records without the base. CONTRIBUTING, the Makefile and the CI job describe the rule.

How it was verified. tests/test_owns_arrays.py (42 tests) builds 11 public records by hand from a writeable array, writes into the array and checks the record did not move: before this change all 11 shared memory with the caller, now none does. It also covers the base itself on purpose-built records: tuples, lists, named tuples and every kind of mapping, an InitVar argument, a class's own and an inherited __post_init__, read-only and strided views of a writeable array, C order, and a Signal held whole or handed to an array field. tests/test_check_array_aliasing.py (81 tests, 35 new) covers the new rules of the gate, including a helper that writes into its argument through an augmented assignment. Four existing tests expected an array a result computed (a default band axis, a band importance table) to be writeable, two of them by writing into it; they now check that it shares no memory with the published table it came from and refuses writes. The full suite passes on Python 3.13 (26904 passed, 69 skipped), the 7483 documentation snippets over 730 pages run, the site type-checks, builds and validates, the conformance report is unchanged (1893 of 1893 checks), the API reference regenerates with no change, and ruff, ruff format, mypy (688 files) and bandit are clean.

@jmrplens
jmrplens added this pull request to stack #950 October 7, 2026 15:17
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 217 files, which is 117 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration
  • Configuration used: Repository: jmrplens/phonometry/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 0ada1739-64f8-482f-8c60-0b474fd5e295
📥 Commits

Reviewing files that changed from the base of the PR and between e88a846 and 835d8e1.

📒 Files selected for processing (217)
  • .github/workflows/python-app.yml
  • CHANGELOG.md
  • CONTRIBUTING.md
  • Makefile
  • docs/start/upgrading.md
  • llms-full.txt
  • scripts/check_array_aliasing.py
  • site/public/llms/llms-start.txt
  • site/src/content/docs/es/start/upgrading.mdx
  • site/src/content/docs/start/upgrading.mdx
  • src/phonometry/_internal/frozen.py
  • src/phonometry/aircraft/airport_noise.py
  • src/phonometry/aircraft/anp_fleet.py
  • src/phonometry/aircraft/atmospheric_absorption.py
  • src/phonometry/aircraft/certification.py
  • src/phonometry/aircraft/measurement_system.py
  • src/phonometry/aircraft/npd_atmosphere.py
  • src/phonometry/aircraft/rotorcraft_noise.py
  • src/phonometry/aircraft/rotorcraft_propagation.py
  • src/phonometry/broadcast/program_loudness.py
  • src/phonometry/broadcast/quasi_peak.py
  • src/phonometry/building/measurement/flanking_transmission.py
  • src/phonometry/building/measurement/floor_covering_improvement.py
  • src/phonometry/building/measurement/heavy_impact.py
  • src/phonometry/building/measurement/insulation.py
  • src/phonometry/building/measurement/intensity_insulation.py
  • src/phonometry/building/measurement/joint_insulation.py
  • src/phonometry/building/measurement/lab_improvement.py
  • src/phonometry/building/measurement/lab_insulation.py
  • src/phonometry/building/measurement/low_frequency.py
  • src/phonometry/building/measurement/rainfall_sound.py
  • src/phonometry/building/measurement/ratings.py
  • src/phonometry/building/measurement/service_equipment.py
  • src/phonometry/building/measurement/structure_borne_power.py
  • src/phonometry/building/measurement/survey_insulation.py
  • src/phonometry/building/prediction/aperture_transmission.py
  • src/phonometry/building/prediction/ceiling_plenum.py
  • src/phonometry/building/prediction/detailed_model.py
  • src/phonometry/building/prediction/facade.py
  • src/phonometry/building/prediction/installed_structure_borne.py
  • src/phonometry/building/prediction/masonry_cavity_wall.py
  • src/phonometry/building/prediction/panel_transmission.py
  • src/phonometry/building/prediction/resilient_layers.py
  • src/phonometry/building/regulation/spain.py
  • src/phonometry/electroacoustics/distortion.py
  • src/phonometry/electroacoustics/frequency_response.py
  • src/phonometry/electroacoustics/headphones.py
  • src/phonometry/electroacoustics/induction_loop.py
  • src/phonometry/electroacoustics/induction_loop_components.py
  • src/phonometry/electroacoustics/intermodulation.py
  • src/phonometry/electroacoustics/loudspeaker.py
  • src/phonometry/electroacoustics/microphone.py
  • src/phonometry/electroacoustics/piston.py
  • src/phonometry/electroacoustics/programme_signal.py
  • src/phonometry/electroacoustics/swept_sine.py
  • src/phonometry/emission/free_field_qualification.py
  • src/phonometry/emission/intensity.py
  • src/phonometry/emission/intensity_compliance.py
  • src/phonometry/emission/reference_sound_source.py
  • src/phonometry/emission/sound_power.py
  • src/phonometry/emission/sound_power_anechoic.py
  • src/phonometry/emission/sound_power_hard_walled.py
  • src/phonometry/emission/sound_power_high_frequency.py
  • src/phonometry/emission/sound_power_in_duct.py
  • src/phonometry/emission/sound_power_in_situ.py
  • src/phonometry/emission/sound_power_intensity.py
  • src/phonometry/emission/sound_power_intensity_points.py
  • src/phonometry/emission/sound_power_plant.py
  • src/phonometry/emission/sound_power_reverberation.py
  • src/phonometry/emission/sound_power_special_room.py
  • src/phonometry/emission/turbine_noise.py
  • src/phonometry/emission/vibration_sound_power.py
  • src/phonometry/emission/workstation.py
  • src/phonometry/environment/assessment/exposure_distribution.py
  • src/phonometry/environment/assessment/impulsive_sound.py
  • src/phonometry/environment/assessment/soundscape.py
  • src/phonometry/environment/assessment/spain.py
  • src/phonometry/environment/assessment/wind_turbine_modulation.py
  • src/phonometry/environment/assessment/wind_turbine_receptor.py
  • src/phonometry/environment/propagation/air_absorption.py
  • src/phonometry/environment/propagation/barrier_in_situ.py
  • src/phonometry/environment/propagation/barrier_reflection.py
  • src/phonometry/environment/propagation/ground_barriers.py
  • src/phonometry/environment/propagation/noise_reducing_devices.py
  • src/phonometry/environment/propagation/outdoor_propagation.py
  • src/phonometry/environment/propagation/refraction.py
  • src/phonometry/environment/propagation/software_quality.py
  • src/phonometry/environment/sources/acoustic_roughness.py
  • src/phonometry/environment/sources/cnossos_rail.py
  • src/phonometry/environment/sources/cnossos_road.py
  • src/phonometry/environment/sources/rolling_stock_noise.py
  • src/phonometry/environment/sources/statistical_pass_by.py
  • src/phonometry/environment/sources/track_decay.py
  • src/phonometry/environment/sources/wind_turbine.py
  • src/phonometry/filters/compliance.py
  • src/phonometry/filters/core.py
  • src/phonometry/filters/equalizer.py
  • src/phonometry/filters/time_invariance.py
  • src/phonometry/filters/weighting.py
  • src/phonometry/filters/weighting_compliance.py
  • src/phonometry/hearing/active_noise_reduction.py
  • src/phonometry/hearing/audiometry.py
  • src/phonometry/hearing/earmuff_insertion_loss.py
  • src/phonometry/hearing/hearing_protectors.py
  • src/phonometry/hearing/noise_induced_hearing_loss.py
  • src/phonometry/hearing/real_ear_attenuation.py
  • src/phonometry/hearing/sound_field_audiometry.py
  • src/phonometry/hearing/threshold.py
  • src/phonometry/io/_signal.py
  • src/phonometry/materials/absorbers/biot.py
  • src/phonometry/materials/absorbers/four_microphone.py
  • src/phonometry/materials/absorbers/impedance_tube.py
  • src/phonometry/materials/absorbers/layered.py
  • src/phonometry/materials/absorbers/porous.py
  • src/phonometry/materials/absorbers/rating.py
  • src/phonometry/materials/absorbers/slow_sound.py
  • src/phonometry/materials/absorbers/sound_absorption.py
  • src/phonometry/materials/absorbers/uncertainty.py
  • src/phonometry/materials/diffusers/design.py
  • src/phonometry/materials/diffusers/metadiffuser.py
  • src/phonometry/materials/diffusers/reverberation_room_scattering.py
  • src/phonometry/materials/diffusers/scattering_diffusion.py
  • src/phonometry/materials/surfaces/road_absorption.py
  • src/phonometry/metrology/comparison_calibration.py
  • src/phonometry/metrology/data_qualification.py
  • src/phonometry/metrology/free_field_corrections.py
  • src/phonometry/metrology/random_incidence.py
  • src/phonometry/metrology/reciprocity_calibration.py
  • src/phonometry/metrology/reciprocity_coupler.py
  • src/phonometry/metrology/reciprocity_free_field.py
  • src/phonometry/metrology/uncertainty.py
  • src/phonometry/noise_control/cabin_insulation.py
  • src/phonometry/noise_control/duct_modes.py
  • src/phonometry/noise_control/duct_path.py
  • src/phonometry/noise_control/enclosure_insulation.py
  • src/phonometry/noise_control/enclosures.py
  • src/phonometry/noise_control/hvac.py
  • src/phonometry/noise_control/room_to_room.py
  • src/phonometry/noise_control/screen_in_situ.py
  • src/phonometry/noise_control/silencer_in_situ.py
  • src/phonometry/noise_control/silencer_measurement.py
  • src/phonometry/noise_control/silencers.py
  • src/phonometry/noise_control/valves.py
  • src/phonometry/noise_control/valves_hydrodynamic.py
  • src/phonometry/psychoacoustics/loudness/contours.py
  • src/phonometry/psychoacoustics/loudness/ecma.py
  • src/phonometry/psychoacoustics/loudness/moore_glasberg.py
  • src/phonometry/psychoacoustics/loudness/moore_glasberg_time.py
  • src/phonometry/psychoacoustics/loudness/zwicker.py
  • src/phonometry/psychoacoustics/quality/fluctuation_strength.py
  • src/phonometry/psychoacoustics/quality/fluctuation_strength_ecma.py
  • src/phonometry/psychoacoustics/quality/roughness_ecma.py
  • src/phonometry/psychoacoustics/quality/tonality_ecma.py
  • src/phonometry/psychoacoustics/quality/tone_audibility.py
  • src/phonometry/room/acoustics.py
  • src/phonometry/room/auditorium.py
  • src/phonometry/room/crowd_noise.py
  • src/phonometry/room/enclosed_space_absorption.py
  • src/phonometry/room/image_source.py
  • src/phonometry/room/impulse_response.py
  • src/phonometry/room/modes.py
  • src/phonometry/room/noise_criteria.py
  • src/phonometry/room/open_plan.py
  • src/phonometry/room/reverberation_prediction.py
  • src/phonometry/room/spatial_decay.py
  • src/phonometry/room/steady_field.py
  • src/phonometry/signals/cepstrum.py
  • src/phonometry/signals/correlation.py
  • src/phonometry/signals/envelope.py
  • src/phonometry/signals/inversion.py
  • src/phonometry/signals/miso.py
  • src/phonometry/signals/multitaper.py
  • src/phonometry/signals/phase.py
  • src/phonometry/signals/spectra.py
  • src/phonometry/signals/synchronous_average.py
  • src/phonometry/signals/test_signals.py
  • src/phonometry/signals/time_frequency.py
  • src/phonometry/signals/windows.py
  • src/phonometry/simulation/elastic_fdtd.py
  • src/phonometry/simulation/fdtd.py
  • src/phonometry/simulation/ntff.py
  • src/phonometry/speech/objective_intelligibility.py
  • src/phonometry/speech/sii.py
  • src/phonometry/speech/sti.py
  • src/phonometry/underwater/bioacoustics/audiograms.py
  • src/phonometry/underwater/bioacoustics/weighting.py
  • src/phonometry/underwater/propagation/closed_form.py
  • src/phonometry/underwater/propagation/numerical.py
  • src/phonometry/underwater/propagation/seabed_reflection.py
  • src/phonometry/underwater/propagation/sound_speed.py
  • src/phonometry/underwater/propagation/weston_regimes.py
  • src/phonometry/underwater/sonar_equation.py
  • src/phonometry/underwater/sources/ambient_noise.py
  • src/phonometry/underwater/sources/pile_driving_noise.py
  • src/phonometry/underwater/sources/ship_radiated_noise.py
  • src/phonometry/underwater/sources/ship_traffic_noise.py
  • src/phonometry/vibration/human/exposure.py
  • src/phonometry/vibration/human/instrumentation.py
  • src/phonometry/vibration/human/multiple_shock.py
  • src/phonometry/vibration/human/signal_burst.py
  • src/phonometry/vibration/immission/people.py
  • src/phonometry/vibration/immission/railway.py
  • src/phonometry/vibration/immission/railway_prediction.py
  • src/phonometry/vibration/immission/vibration_meter.py
  • src/phonometry/vibration/structural/experimental_sea.py
  • src/phonometry/vibration/structural/impact_mobility.py
  • src/phonometry/vibration/structural/junction_transmission.py
  • src/phonometry/vibration/structural/mechanical_mobility.py
  • src/phonometry/vibration/structural/point_mobility.py
  • src/phonometry/vibration/structural/radiation_efficiency.py
  • src/phonometry/vibration/structural/transfer_stiffness.py
  • tests/noise_control/test_hvac_vdi2081.py
  • tests/room/test_enclosed_space_absorption.py
  • tests/room/test_noise_criteria.py
  • tests/speech/test_sii.py
  • tests/test_check_array_aliasing.py
  • tests/test_owns_arrays.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@sourcery-ai

sourcery-ai Bot commented Oct 7, 2026

Copy link
Copy Markdown

Sorry @jmrplens, your pull request is larger than the review limit of 150,000 diff characters

@github-actions github-actions Bot added documentation Improvements or additions to documentation site Documentation website i18n English and Spanish translations ci Workflows, linting and developer tooling area: aircraft Aircraft and rotorcraft noise area: broadcast Programme loudness and broadcast levels area: building Sound insulation and building acoustics area: electroacoustics Transducers, arrays and electroacoustic devices area: emission Sound power and source emission area: environment Outdoor propagation, environmental sources and noise assessment area: hearing Audiometric thresholds, hearing loss and noise exposure area: materials Absorption, impedance and material properties area: metrology Calibration, uncertainty and measurement quality area: noise control Silencers, barriers and noise control treatments area: psychoacoustics Loudness, sharpness, roughness and annoyance area: room Room acoustics and reverberation area: simulation FDTD and other numerical solvers area: underwater Underwater acoustics and propagation area: vibration Human vibration and structure-borne sound area: core Shared internals and cross-cutting code every domain depends on area: filters Octave filter banks, weightings and instrument class verification area: signals Levels, spectra, generators and general signal analysis area: speech Speech intelligibility: STI, SII and STOI labels Oct 7, 2026
@codecov

codecov Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.30233% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.80%. Comparing base (e88a846) to head (835d8e1).

Files with missing lines Patch % Lines
src/phonometry/_internal/frozen.py 93.87% 6 Missing ⚠️
Additional details and impacted files
@@                          Coverage Diff                           @@
##           fix/subscripts-follow-the-standard     #948      +/-   ##
======================================================================
- Coverage                               96.80%   96.80%   -0.01%     
======================================================================
  Files                                     443      443              
  Lines                                   87889    88037     +148     
======================================================================
+ Hits                                    85082    85223     +141     
- Misses                                   2807     2814       +7     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Numerical conformance

All 1893 conformance checks pass, across 111 domains and 523 standards

1893/1893 checks pass across 111 domains and 523 standards (227 normative designations, 125 further published sources).

Used in the tables below is how much of that clause's published tolerance the deviation consumes: 100 % sits exactly on the limit, 5 % uses a twentieth of the allowance, and a dash means the clause states no two-sided tolerance for the quantity, so there is no budget to spend. It is reported and never used to decide a verdict, which is settled at full precision before any rounding.

New checks (2)

Standard Quantity Deviation Used
IEC 61094-5:2016 6.7; ISO/IEC Guide 98-3 F.1.2.3, Example 2 Correlation of two calibrations against the same standard of 10^-4, for comparisons of 100, 10 and 1 x 10^-6, as printed 0 0 %
IEC 61094-5:2016 6.7, Table D.1; ISO/IEC Guide 98-3 5.2.2 Expanded uncertainty of the difference of two calibrations against the same LS2P, each with the budget of Table D.1 0 dB 0 %

Closest to their published limit (top 5)

The rows with the least room left, so the ones a change is most likely to push over.

Standard Quantity Deviation Used
ISO/TR 17534-3:2015 Table 3 Ground-projected path length dp, m 0.005 m 100 %
DIN 4150-2:1999-06 Annex C, Example 5 KB_FTr with hammer b) in the rest hours, Formula (5) -0.005 100 %
DIN 4150-2:1999-06 Annex C, Example 8 KB_FTm over the record with the passage maxima alone -0.0005 100 %
E DIN 4150-2:2023-08 Annex B, Table B.1 KB_FTm,Zug of the metro north by Formula (5) -0.0005 100 %
Jarvis (1996) NPL CIRA(EXT) 010 Appendix B, folio 26 Volume of the coupler of the example, v = pi r^2 L -0.00000000005 m³ 100 %

Pass Tests & coverage: 161850 tests, 0 failures (all green)
Python Version Tests Failures Coverage Status
macos-latest-3.13 26975 0 96.8% Pass Passed
macos-latest-3.14 26975 0 96.8% Pass Passed
ubuntu-latest-3.13 26975 0 96.8% Pass Passed
ubuntu-latest-3.14 26975 0 96.8% Pass Passed
windows-latest-3.13 26975 0 96.8% Pass Passed
windows-latest-3.14 26975 0 96.8% Pass Passed

Full report at this commit: docs/CONFORMANCE.md · docs/conformance.json · full CI artifacts

@jmrplens
jmrplens force-pushed the fix/records-copy-at-construction branch from 7f8ffe1 to b665f7f Compare October 7, 2026 16:51
…t holds, however it was built

The library's functions already copy the arrays a result keeps, but a record built by hand, by calling its class directly (`room.ImpulseResponseResult(ir=measured, ...)`, or `aircraft.AnpNpdCurves(...)` filled from your own NPD data), still kept the array you handed it, so editing that array afterwards edited the record. With this change every one of the 428 public records that can hold an array copies it at construction, whoever builds it.
@jmrplens
jmrplens force-pushed the fix/records-copy-at-construction branch from b665f7f to 835d8e1 Compare October 7, 2026 18:05
@sonarqubecloud

sonarqubecloud Bot commented Oct 7, 2026

Copy link
Copy Markdown

@jmrplens
jmrplens merged commit 5a93956 into main Oct 7, 2026
92 of 95 checks passed
@jmrplens
jmrplens deleted the fix/records-copy-at-construction branch October 7, 2026 19:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: aircraft Aircraft and rotorcraft noise area: broadcast Programme loudness and broadcast levels area: building Sound insulation and building acoustics area: core Shared internals and cross-cutting code every domain depends on area: electroacoustics Transducers, arrays and electroacoustic devices area: emission Sound power and source emission area: environment Outdoor propagation, environmental sources and noise assessment area: filters Octave filter banks, weightings and instrument class verification area: hearing Audiometric thresholds, hearing loss and noise exposure area: materials Absorption, impedance and material properties area: metrology Calibration, uncertainty and measurement quality area: noise control Silencers, barriers and noise control treatments area: psychoacoustics Loudness, sharpness, roughness and annoyance area: room Room acoustics and reverberation area: signals Levels, spectra, generators and general signal analysis area: simulation FDTD and other numerical solvers area: speech Speech intelligibility: STI, SII and STOI area: underwater Underwater acoustics and propagation area: vibration Human vibration and structure-borne sound ci Workflows, linting and developer tooling documentation Improvements or additions to documentation i18n English and Spanish translations site Documentation website

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant