Skip to content

feat(patch): meta-population model over the three affected provinces - #412

Merged
seabbs merged 131 commits into
mainfrom
patch-model
Sep 15, 2026
Merged

seabbs merged 131 commits into
mainfrom
patch-model

Conversation

@seabbs-bot

@seabbs-bot seabbs-bot commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Makes the headline model a meta-population: one renewal equation per province, coupled by importation, with every national stream fitted against the summed provinces. n_patches = 1 collapses it exactly onto main's single-population model, so there is one model rather than two.

What the branch adds over main

Four patches. Ituri, Nord-Kivu, Haut-Uélé, and other pooling Tshopo, Sud-Kivu and Bas-Uélé, which is the province set the situation reports now carry.

Reproduction number. R_{p,t} = R_t exp(δ_{p,t}), with R_t main's national weekly-knot walk. The deviations share those knots, are correlated across provinces through an LKJ factor, revert toward zero with a shared half-life, and sum to zero at every knot, so no province is the reference and the national level is left to R_t.

Seeding. One cryptic epidemic partitioned across provinces: s_1 = 1/(1+Σf), s_p = f_{p-1}/(1+Σf), with f_p ~ LogNormal(log 0.05, 1). The shares sum to one, so 2^m keeps its elicited meaning as the country's cryptic size and C_T stays comparable with main.

Importation. A gravity kernel weights each origin's exported transmission by destination population and inverse distance between provincial capitals, holding each origin's total outflow at 1 - N_q/N. The intensity is one level per origin, partially pooled, and changes at detection on the ramp the reproduction number already uses. Coupling is a same-day transfer: the origin is debited exactly what the destinations are credited.

National quantities read back, not imposed. I_t = Σ_p I_{p,t}, C_T = Σ_t I_t, and the national reproduction number is recovered by inverting the renewal on the summed infections. The provinces are not rescaled to reproduce the trend, so the country runs at the force-weighted mean of the provincial reproduction numbers.

Composition likelihoods. Per-vintage provincial shares of confirmed cases and of confirmed deaths, scored as stick-breaking BetaBinomials on the totals the national streams already carry. Cases identify only the product of relative ascertainment and incidence; the deaths column, under a shared case-fatality ratio and a tight death-ascertainment prior, is what separates them.

Data. Per-province confirmed cases and deaths from Tableau 1, and per-province laboratory throughput, both scanned from the situation-report PDFs and gated on summing exactly to the national totals on every date.

Report. Per-province summary and overview tables, per-province reproduction numbers, the provincial case-fatality comparison, and one-week-ahead forecast scoring by province.

Consequences worth knowing

The provinces are free to disagree with the single-population model, and the national streams are what hold the summed trajectory down. Because the faster province keeps gaining share of the force, the force-weighted mean converges on the fastest province, so the prior-implied national size depends on the deviation scale and the molecular-clock prior sets the trend rather than the country.

With no deviations the provinces reproduce the single-population trajectory to machine precision, which is what the partitioned seed and the transferred importation buy.

Verified

test/test_patch_model.jl covers the renewal against the single-patch reference, importation transfer, the sum-to-zero deviations, the composition likelihoods on both columns, the per-province tables, and the headline quantities on a patch chain.

This was opened by a bot. Please ping @seabbs for any questions.

Comment thread src/models/priors.jl Outdated
Comment thread src/models/joint.jl Outdated
Comment thread src/summaries.jl Outdated
Comment thread src/models/priors.jl Outdated
@seabbs-bot

Copy link
Copy Markdown
Collaborator Author

Review pass done (4 inline comments above). CI status: pre-commit, Downgrade compat (Julia 1.11), Julia lts - ubuntu-latest, Resolve env and list fits and Fit exports all pass; the remaining Julia matrix jobs and the 11-job fit matrix are still running. No failures so far.

One further observation from watching the fit matrix fan out: bvd_patch_joint is not in the fits registry. The matrix runs joint, cases, deaths, confirmed, confirmed_deaths, exports, treatment, and the frozen vintages — no patch entry. grep -rn patch scripts/run.jl scripts/reproduce.jl returns nothing, and nothing under scripts/ constructs a bvd_patch_joint.

So the patch model has unit tests (test/test_patch_model.jl, which exercise the renewal primitives and the submodel varnames) but is never fit end-to-end in CI, produces no release artefact, and appears on no docs/analysis page. For a draft that is a reasonable place to be, but it means the two critical issues I flagged above — the secondary-patch seed prior, and the unused per-province lab denominator — would not have been caught by anything in the pipeline. Registering a patch fit (even a short, low-draw one) is what would turn the posterior-predictive check into a standing gate rather than a one-off manual run.

This was opened by a bot. Please ping @seabbs for any questions.

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.73%. Comparing base (4898024) to head (013529a).
⚠️ Report is 9 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #412      +/-   ##
==========================================
+ Coverage   95.12%   96.73%   +1.61%     
==========================================
  Files          15       16       +1     
  Lines        3731     4536     +805     
==========================================
+ Hits         3549     4388     +839     
+ Misses        182      148      -34     

☔ 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.

@github-actions

Copy link
Copy Markdown
Contributor

📖 Documentation preview is ready!

View the docs for this PR at: http://epiforecasts.io/BVDOutbreakSize/previews/PR412/

This preview will be updated automatically when you push new commits.

@seabbs
seabbs marked this pull request as ready for review July 12, 2026 08:10
@seabbs
seabbs self-requested a review as a code owner July 12, 2026 08:10
@seabbs

seabbs commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

This needs to be the new headline model ie joint and be wired into the analysis and sensitivity ie for one week ahead forecasts. I don't see evidence it works here

@seabbs-bot

This comment was marked as outdated.

@seabbs-bot

This comment was marked as outdated.

@seabbs

seabbs commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

There are some conflicts. The much larger outbreak size is worrying and I am not sure plausible. You don't show estimates or forecats for any of the spatial patches or Rt by patch

seabbs-bot and others added 13 commits August 10, 2026 11:17
A meta-population / patch model formulation for the 2026 DRC BVD outbreak
that splits the single-patch national model into three spatial patches
(Ituri, Nord-Kivu, Sud-Kivu). Each patch has a province-specific
reproduction number (hierarchical modifier on the national Rt),
within-patch renewal transmission, and a between-patch importation
kernel. National data streams are fitted to the sum of patch trajectories;
per-province spatial-table data (confirmed cases, lab analysed, isolation)
fit individual patches.

See notes/patch-model.md for the full formulation.

Relates-to: patch-model exploration
- patch_rt_model: hierarchical Rt (national walk + per-patch modifiers)
- patch_infection_model: multi-patch renewal with importation
- patch_infections() and importation_from_kernel() in renewal.jl
- Verified: module compiles, prior predictive sampling runs

Relates-to: patch-model exploration
- _patch_latent: wraps patch_infection_model and sums patch trajectories
- bvd_patch_joint: full joint model using patch latent process with
  national-level observation submodels
- All models compile; patch_infection_model prior predictive verified

Relates-to: patch-model exploration #5
Use the national-level cases_state.bvd_reports_daily and cases_state.bg_daily
for the treatment flow model, matching the signature of treatment_flow_model.
Fix field name from deaths_state.onsets_to_deaths (does not exist) to the
correct cases_state.bvd_reports_daily + cases_state.bg_daily pair.
Remove duplicate := deterministics for parameters already traced inside the
patch submodel (importation_epsilon, sigma_region, C_T_total).
- Expose C_T_patch_1/2/3, R_T_patch_1/2/3, infections_T_patch_1/2/3
  as := deterministics in bvd_patch_joint
- Add patch_summary_table() to summaries.jl — per-patch posterior
  summary of C_T, R_T, daily infections, and δ modifier
- Export patch_summary_table from BVDOutbreakSize.jl
…onal Rt

Replace the constant-modifier patch_rt_model with patch_rt_mvwalk_model:
- Each patch gets its own log-Rt trajectory via an MVN random walk at weekly knots
- Innovations are correlated across patches via LKJ(2) sampled correlation matrix
- Each patch has its own step SD sigma_rw_patch and initial R0 variation
- Allows Ituri (high Rt, sustained transmission) and Sud-Kivu (near-zero local Rt)
  to diverge arbitrarily

Add implied_national_Rt() helper to renewal.jl:
- Derives the national Rt from summed patch infections via the renewal equation
- No separate national Rt parameter — it emerges from the aggregated dynamics

Update patch_infection_model to use the new MV walk by default:
- Removes rt_state.delta_patch and rt_state.sigma_region dependencies
- Adds implied_Rt_national to the return tuple
- Exposes sigma_rw_patch and Omega from the MV walk
- Fix docstring to document new return values

Add LinearAlgebra as a project dependency for cholesky factorization.
Replace delta_patch references with sigma_rw patch step SDs from
the multivariate normal random walk.
- Fix intervention ramp in patch_rt_mvwalk_model: add intervention_effect
  parameter and apply ramp properly (was multiplied by 0.0)
- Add @inbounds to MV walk core loops (Sigma_half, knot innovations,
  daily interpolation)
- Add effect_prior keyword arg to patch_rt_mvwalk_model
- Fix background_re code path: guard against empty histories with
  bg_lead pattern matching bvd_joint
- Update design doc to document MV walk model as Option C
- Add confirmed_cases_patch_model to observations.jl: shares receipt
  delay and test sensitivity with the national confirmed stream, fits
  against per-province data from spatial tables (Tableau 1)
- Wire into bvd_patch_joint: per-province fitting loop routes each
  patch's onsets through the shared lab pipeline
- Add province_confirmed_history to load_observations() return
  (empty Dict by default, ready for data population)
- Export s_test and spec from confirmed_cases_model so per-province
  models can access them
- Export confirmed_cases_patch_model from BVDOutbreakSize.jl
- Add province_confirmed_history TOML block with per-province spatial
  table data (Ituri, Nord-Kivu, Sud-Kivu confirmed cases from Tableau 1)
- Add province_history() parser in data.jl that reads per-province arrays
  from TOML blocks into Dict{String, NamedTuple}
- Wire province_history() output into load_observations return tuple
- Fix MustNotOverwriteError: use = instead of := for
  expected_patch_confirmed (loop runs multiple times)
The per-province confirmed counts are an exact partition of the national
confirmed counts (verified: Ituri + Nord-Kivu + Sud-Kivu equals the
national total at all 17 shared vintages). Fitting them with their own
count likelihood alongside the national confirmed stream put the same
observations into the joint density twice, double-weighting the confirmed
stream against every other stream.

Replace confirmed_cases_patch_model with province_composition_model, which
factorises P(y) = P(N) x P(shares | N): the national stream keeps the total
term, and the composition term scores only the spatial split, by
stick-breaking over patches with an overdispersed Binomial. The vintage
totals are conditioned on, never scored.

Rt across space: the provincial shares are flat over the whole window
(Ituri 91.4% -> 91.1%; Ituri grew 1.82x, Nord-Kivu 1.94x), so the data
carry no signal for a time-varying divergence between provinces. Drop the
multivariate-normal random walk on joint per-patch log-Rt, which fitted
~30 parameters to that absent signal, discarded the national Rt walk the
headline model depends on, and had an inverted intervention sign (half
normal on lower=0, raising Rt post-intervention, where rt_walk_model uses
upper=0). patch_rt_model now layers a constant per-patch modifier on the
unchanged national walk, reference-coded on the primary patch (delta_1 = 0)
so the walk level and the mean of delta are not confounded.

Importation: epsilon is now sampled only when a non-zero kernel is
supplied. There is no mobility data, and under flat shares importation is
confounded with the secondary-patch seeds, so the default kernel is zero
and no epsilon enters the parameter space. Previously epsilon was sampled
against an all-zero kernel, giving a parameter the likelihood never
touched.

Also: surface C_T, R_T, r, r0, T, CFR, R0 and doubling_time under the same
names as bvd_joint so a patch chain drops into summary_table and the
existing reporting unchanged; rewrite patch_summary_table, which reported
the midpoint of the 20-80 percentile range as a "median"; export the patch
API, which was not actually exported.

Add test/test_patch_model.jl (198 assertions), covering the renewal
equivalence, the importation kernel, the implied-national-Rt identity, the
composition's invariance to the modelled level, the epsilon gating, and the
headline quantities on a real chain.

Co-authored-by: Sam Abbott <contact@samabbott.co.uk>
seabbs-bot and others added 20 commits September 15, 2026 13:50
Rewrite the model methods so the meta-population renewal reads as the
model rather than as an addendum. The bolt-on spatial section is gone and
its content sits in the sections it belongs to: provincial reproduction
numbers under Reproduction number, the per-patch cryptic seed under
Seeding and growth, a new Mixing and importation subsection for the
gravity kernel and the importation intensity, the patch renewal and the
national read-back under Infection process, the export weights under
Exported cases, and a new Province compositions subsection under
Observation models.

Every section now states its maths and its priors, the overview carries
prose only, and each notes how the model collapses at one patch. The
pooling target is renamed R^trend, the response effect becomes beta_R to
free delta for the patch deviations, and the equation tags are
renumbered.

Also corrects prose that had gone stale against the source: the seed is
C_T rather than 2^m, the exports are the weighted patch sum rather than
Ituri alone, the patch count is four, and the quoted capital distances
are the current patches'.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfoEJUruFPcNrWxtLUBBkz
…ries

The per-province summary figure and its folded table carry the log-Rt
deviation, its walk scale and the contrast against Ituri, so they sit
with the reproduction-number trajectories rather than with the size
tables. The cross-province overview table stays where it was.

Cut the prose around both to the fact a reader needs, that the
reproduction number and the relative case ascertainment are identified
only as a product with the deaths breaking the tie, and drop the
descriptions of the layout, the axes and the folded table.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfoEJUruFPcNrWxtLUBBkz
Drop the issue reference and the projection caveat, leaving what the
forecast split is and how each province's count is built.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfoEJUruFPcNrWxtLUBBkz
`exponential_growth_model` takes the generation interval so it can count
the cryptic phase in generations. The merge that brought that in updated
`infection_model`'s call site but not the patch composer's, so every
`bvd_joint` build on this branch threw a MethodError and no test that
builds the model could run.
…ches

The executive summary now describes the meta-population renewal and the
trend the provinces pool toward, rather than a national single-population
process. The reproduction-number results name the pooled patch instead of
a Sud-Kivu panel that no longer exists, and the correlation note counts
four patches. Drop the y-axis explanation on the modelled-infections
figure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfoEJUruFPcNrWxtLUBBkz
…urns

The helper recomputed the national cryptic curve from `2^m`, which stopped
matching when `m` became a count of generations. It now reads the anchor
`patch_infection_model` surfaces, so it cannot drift from the growth
prior's parameterisation again.
`plot_province_forecast` draws the per-province one-week-ahead forecast
as one panel per stream, provinces side by side on a shared axis, each a
median dot over nested 30/60/90% credible bars, in the style of
`plot_patch_summary`. `province_forecast_archive` writes the same split
in the `forecast_archive` long schema plus the province each row is a
share of, so a release records the provincial forecast it made alongside
the national one.

Both read the split through `_province_forecast_draws`, which
`province_forecast_table` now uses too, so the table, the figure and the
archive multiply the national draw by the province share draw by draw in
one place.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfoEJUruFPcNrWxtLUBBkz
The one-week-ahead split by province is a figure alongside the other
forecast figures, with the table kept behind the drop-down for the
numbers. The same draws are written to `output/province_forecast.csv`, in
the national forecast's schema plus the province each row is a share of,
so every release records the provincial forecast it made.
…n the step

The dashboard carried the national and per-province reproduction numbers
but nothing showing where the epidemic sits. It now also shows modelled
infections by province and the per-province summary of size, reproduction
number and relative ascertainment.

The headline fits drop to a target acceptance of 0.80. The patch fit's
cost is trajectory length rather than gradient cost, so a longer step is
what buys the adaptation the effective sample size needs.
`interpolate_knots` only reads its knots, so slicing a row out of the
knot matrix copied it for nothing and put one `getindex` per knot on the
gradient tape. A view removes the copy. The log density and its gradient
are bit-identical at both one and three patches.

Measured on the isolated kernel (Mooncake gradient of the three-patch
knot interpolation at the fitted sizes), 0.135 ms before and 0.103 ms
after. The saving is too small to resolve in the full joint gradient.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfoEJUruFPcNrWxtLUBBkz
Tableau 1 gained a seventh province at SitRep 119 (10 September): Sud
Ubangi, one confirmed case that is already a death, health zones 1/16.
The scanner knew six provinces, so its rows fell one case and one death
short of the national totals at 119, 120 and 121 and it refused all
three vintages. The province blocks have been three vintages behind the
national series since.

Sud Ubangi is a source province, not a patch. It joins the pooled
`other` patch with Tshopo, Sud-Kivu and Bas-Uele, whose population and
capital are already derived from their members, so the source entry is
all that is needed. One confirmed case would inform nothing given its
own reproduction number and ascertainment.

Its population is 2 755 000, the 2019 figure from the Democratic
Republic of the Congo's Institut National de la Statistique, Annuaire
statistique RDC 2020 (March 2021), read from the same Wikipedia
tabulation the other six provinces come from. The six existing figures
were checked against that table and match to the unit, so all seven are
one source. Its capital is Gemena at 3.25651 N, 19.77234 E, the
GeoNames record for the seat of the first-order administrative division
of Sud-Ubangi (geonameid 2315728), the same source as the other six
capitals.

Gemena sits well west of the pooled patch's other members, so the
population-weighted mean capital moves about 1.6 degrees west, from
27.46 E to 25.85 E. That is the kernel reading where the pooled
population is, which is what it is for.

Every vintage from 15 June to 12 September now reconciles exactly with
the national confirmed case and death totals, 82 dates against the
previous 75. Four of the seven new dates (29 and 30 June, 6 and 7
August) are not new vintages but dates the national series has gained
since the province blocks were last written.

The laboratory series does not advance past 9 September. SitReps 119 to
121 word their negative and positive results as "tous se sont reveles
negatifs/positifs", which the bullet parser does not read, and Sud
Ubangi's own 119 bullet gives no sample count at all ("sur l'echantillon
analyse"). Those vintages are left out as before. The block still gains
Sud Ubangi's columns and two earlier dates.
The header quoted a steady 8.5-9% Nord-Kivu case share from an early
window. Over the full scanned range it is 8.0-17.6%, against a death
share of 13.6-22.6%, so the gap the deaths column identifies narrows
rather than holding.
The patch renewal built the whole implied national reproduction number
trajectory and read one entry from it. Nothing read the rest: the
`Rt_national_implied` deterministic had no consumer in the analysis page,
the sensitivity page, the summaries, the plots, the forecast, the tests or
the docs prose. `implied_national_Rt_at` returns the single day, and the
trajectory form is now written in terms of it.

The point is the released chain rather than the gradient. Every draw
carried a 212-day vector that nothing ever read, and that vector is now
gone from the chain. The quantity never shipped, so no release loses it.

The log density and its gradient are bit-identical at one and three
patches, since the cut-off day is computed by the same arithmetic in the
same order, and the trajectory only ever fed deterministics. Gradient
17.233 -> 16.819 ms at one patch and 20.159 -> 19.933 ms at three, against
a run-to-run band of about 0.15 ms.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfoEJUruFPcNrWxtLUBBkz
The half-life is documented as the persistence of a provincial divergence
but the spatial hyperparameter table did not carry it.
Takes v2.0.0 from main.

`docs/examples/analysis.jl` keeps this branch's restructured model
section and applies main's form on top: the remaining `@cite` site drops
its author prefix for `@citet`, main's abscond competing-risk maths comes
in as equation 37, and the equation tags renumber to a contiguous 1-59.

`docs/src/news.md` keeps main's released v2.0.0 section and puts this
branch's entries under a fresh `Unreleased` heading above it.
The spatial model ships in v2.0.0, so its notes belong in that section
rather than under a heading of their own. The generations reparameter-
isation moves to Model and the per-fit convergence summary to Report.

Corrects three entries: the parameter set is compared against v1, the
target acceptance is 0.80, and the seeding is no longer a partition.
Completes the analysed-volume entry, which stated the old behaviour and
stopped, and adds the provincial forecast figure, its release asset and
the two new dashboard figures.
Comments had accumulated change history, arguments against alternatives
and restatement of the docstring above them. They now document the
current state once. Docstrings keep the summary, the contract and the
maths the code does not make clear.

The package loses 1,035 lines of prose and no code: the parsed syntax is
unchanged in every file but plots.jl, where the estimate-evolution block
parsed as a bare string between two helpers and so documented nothing.
It now sits on plot_estimate_evolution, which is exported and had none.

Corrects two stale claims. bvd_joint said Uganda exports are driven by
Ituri alone, where export_pressure weights every patch, and
plot_posterior_predictive said four streams lay out as a 2x2 grid, where
four or more panels take three columns.

Provenance, numerical guards, AD shape constraints and indexing
conventions are kept.
The break-day gross check and the centred dispersion default are both
chosen on measured sampler behaviour. Stating the choice without the
numbers leaves no way to tell whether it still holds, and the runs they
came from are not reproducible from the code.
The methods and the sensitivity page had grown a sentence after most
equations re-explaining what the equation shows, sentences announcing
the subsections that follow them, and arguments against alternatives
that were never implemented. About 200 lines of prose come out.

Corrections carried with it: the pooled patch has four members since
Sud Ubangi joined, the onset curve does carry symptom-onset dates so
the report-dating limitation was wrong, province populations and
capital coordinates now name their sources, and the seeding says the
outbreak is assumed to have begun in Ituri.

The per-province summary bullets list one province per line rather
than joining them with semicolons.
`province_forecast.csv` has been archived with every release and read by
nothing, so the provincial forecast was never scored. Each row is now
labelled `<stream> [<patch>]` and fed through the existing pipeline, so
the persistence baseline, the CRPS decomposition, coverage and bias all
apply to a province as they do to a national stream.

A patch's truth is its member provinces' cumulative counts summed
vintage by vintage. There is no per-province harmonisation data, so a
window holding a break day is skipped rather than corrected, both for
the truth and for the baseline's step pool.

Releases predating the asset carry no province rows and are counted,
not failed.
@seabbs
seabbs merged commit 54cc27c into main Sep 15, 2026
3 of 9 checks passed
@seabbs
seabbs deleted the patch-model branch September 15, 2026 20:55
seabbs-bot added a commit that referenced this pull request Sep 17, 2026
#717 and #713 each added their own news entry under the v2.0.0 heading
when they merged.
Re-filing them under v2.1.0 described the same two changes twice on the
same page.

The gradient entry already sits under v2.0.0 as "The joint gradient costs
about 30% less", carrying the same 87,000 to 8,500 hazard-evaluation
figures.
The suspect-series entry already sits there as the 7 August resumption
running to 13 September, cited against issue #708 rather than the pull
request.

#412 was left out of v2.1.0 on exactly these grounds.
This applies the same test to the other two.
seabbs pushed a commit that referenced this pull request Sep 17, 2026
#717 and #713 each added their own news entry under the v2.0.0 heading
when they merged.
Re-filing them under v2.1.0 described the same two changes twice on the
same page.

The gradient entry already sits under v2.0.0 as "The joint gradient costs
about 30% less", carrying the same 87,000 to 8,500 hazard-evaluation
figures.
The suspect-series entry already sits there as the 7 August resumption
running to 13 September, cited against issue #708 rather than the pull
request.

#412 was left out of v2.1.0 on exactly these grounds.
This applies the same test to the other two.
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.

3 participants