Skip to content

feat: CD-owned ComposedDistributions bridge — censored leaves are first-class composer leaves (E2) - #851

Draft
seabbs-bot wants to merge 3 commits into
mainfrom
feat/composed-censored-leaves
Draft

feat: CD-owned ComposedDistributions bridge — censored leaves are first-class composer leaves (E2)#851
seabbs-bot wants to merge 3 commits into
mainfrom
feat/composed-censored-leaves

Conversation

@seabbs-bot

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

Copy link
Copy Markdown
Collaborator

Track-1 E2: the CD-owned bridge to ComposedDistributions. It makes a censored delay a first-class leaf of a composed distribution tree, so the composer can introspect and refit it like any other leaf.

Draft — do not merge. CD is not releasable until ComposedDistributions is registered (see Packaging).

Ownership

CensoredDistributions owns this bridge. The generic functions (free_leaf, rewrap_leaf, _shared_tag, _uncertain_specs) are owned by ComposedDistributions; every dispatched argument type (PrimaryCensored, IntervalCensored) is owned by CensoredDistributions. The bridge sits exactly at the seam of the two, so it belongs with the package that owns the types — not with upstream, and it is not piracy in either direction. ComposedDistributions anticipates it: composers/introspection.jl:157-163 names CensoredDistributions as the supplier of the censored-leaf methods, and :600-602 documents that a censored leaf shows only its inner free delay's params.

The same principle applies to the CD x ModifiedDistributions bridge (a CD-owned Modified bridge, not Modified owning a CD extension) and to CD x ConvolvedDistributions (#847). Recorded in #846.

What it does

src/censoring/composed_leaves.jl forwards the composer's leaf protocol through the censoring wrappers:

  • free_leaf — peel a censored leaf down to the delay actually being estimated. The primary event, the solver method and the interval boundaries are fixed structure, not free parameters. Recursive, so the stacked IntervalCensored(Truncated(PrimaryCensored(...))) that double_interval_censored builds peels through in one call.
  • rewrap_leaf — the inverse: rebuild the same wrapper stack around a new inner delay, carrying every fixed field over untouched.
  • _shared_tag — forward a shared tag. Without this a tied delay wrapped in censoring is inventoried as its own free parameter and estimated twice.
  • _uncertain_specs — forward an attached prior. Without this a prior on a censored leaf is silently dropped and the parameter is treated as fixed.

Both of those last two are silent-correctness bugs, not niceties. Weighted is deliberately not bridged: a likelihood weight is an observation-side wrapper, not a delay the composer estimates.

Effect: params_table, build_priors, update and event_names all work on trees containing censored leaves.

Packaging: hard dep now, CD-owned extension later

Julia will not resolve an unregistered package declared in [weakdeps][sources] is honoured only for deps/extras, never for weakdeps. Verified both ways:

  • [weakdeps] + [sources]ERROR: expected package ComposedDistributions [2f642b71] to be registered
  • [deps] + [sources] → resolves

ComposedDistributions is unregistered, so the bridge cannot be a package extension yet. It therefore lives in plain src/ behind a hard [deps] + git [sources] pin. Post-registration the clean form is a CD-owned weakdep extension (CensoredDistributionsComposedDistributionsExt) — same code, same owner, additive and optional again. Ownership does not change; only the packaging does.

Project.toml changes:

[deps]
ComposedDistributions  = "2f642b71-32a9-4f47-97c4-6deb7517f7a7"
ConvolvedDistributions = "f5b942c9-bc5b-4664-8486-7f531bb06742"

[compat]
ComposedDistributions  = "0.1"
ConvolvedDistributions = "0.2"

[sources]  # dev, unregistered

ConvolvedDistributions is a direct dep only because [sources] is not honoured transitively and ComposedDistributions depends on the 0.2 line it is written against.

⚠️ ComposedDistributions is pinned to a branch, not main

ComposedDistributions main caps ConvolvedDistributions at 0.1 while its own source targets the 0.2 API (convolved / convolve_series), so main cannot resolve against Convolved main at all. The [sources] rev is therefore pinned to chore/convolved-0.2-compat, a one-line compat bump. Repoint to main once that lands. This blocker is independent of registration.

Verification

  • free_leaf peels PrimaryCensored, IntervalCensored and the double_interval_censored stack to the inner delay.
  • rewrap_leaf rebuilds the stacked wrapper to the identical concrete type, preserving the truncation bound, a non-default primary_event, the solver method and both scalar and vector boundaries; round-trips to an equal leaf.
  • params_table on a tree with a censored leaf lists exactly the inner delay's free params with the inner delay's support — not the primary event's, not the censoring bounds.
  • update rebuilds the censored leaf with a new inner delay and keeps the censoring.
  • A shared tag survives the wrapper (the tied delay is inventoried once, not twice).
  • An uncertain prior survives the wrapper: build_priors returns the attached Normal(1.5, 0.5), not a default.

Tests in test/integration/ComposedDistributions.jl.

Follow-ups

  • _shared_tag and _uncertain_specs are ComposedDistributions internals (underscore-prefixed) that any leaf-wrapper package must forward, so CD currently sits on unsanctioned API (ignored in the ExplicitImports check). They should be made public upstream — same class as ModifiedDistributions#43. Upstream already ships these forwards for Truncated and in its Modified extension, so the protocol is real, just undeclared.
  • compose differs from CD's historical API: upstream takes a NamedTuple (compose((a = d1, b = d2))), CD's took varargs pairs. Worth a migration-guide note.
  • E3 (adopt the uncertain-first inference codec / as_turing, feat: as_turing adaptor — drive the Turing route from the ComposedLogDensity spec #830) builds directly on this.

Related: #846 (ownership decision), #847, #831, #845, #848, #849.

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

Add CensoredDistributionsComposedDistributionsExt so a censored delay can sit
in a ComposedDistributions tree and be introspected and refit like any other
leaf.

free_leaf peels PrimaryCensored/IntervalCensored down to the delay being
estimated (the primary event, solver method and interval boundaries are fixed
structure), and rewrap_leaf rebuilds the same wrapper around a new inner delay.
_uncertain_specs recurses so a prior attached to the inner delay survives the
censoring wrapper instead of being silently dropped, and _leaf_detail_lines
gives a censored leaf a readable inspect view.

Effect: params_table, build_priors, update and event_names all work on trees
containing censored leaves.

No piracy: free_leaf/rewrap_leaf are owned by ComposedDistributions and every
dispatched type is owned by CensoredDistributions.

Known blocker (see PR): ComposedDistributions is unregistered, and Julia will
not resolve an unregistered package through [weakdeps] + [sources], so the
extension cannot load until it is registered.
@github-actions

Copy link
Copy Markdown
Contributor

Try this Pull Request!

Option 1: Julia Package Manager

Open Julia and type:

import Pkg
Pkg.activate(temp=true)
Pkg.add(url="https://github.com/EpiAware/CensoredDistributions.jl", rev="feat/composed-censored-leaves")
using CensoredDistributions

Option 2: Local Checkout

If you have the repo locally:

git checkout feat/composed-censored-leaves
julia --project=. -e "using Pkg; Pkg.instantiate()"

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ
ad-enzyme-forward 47.54% <0.00%> (-0.52%) ⬇️
ad-enzyme-reverse 47.54% <0.00%> (-0.52%) ⬇️
ad-forwarddiff 43.26% <0.00%> (-0.53%) ⬇️
ad-mooncake-forward 42.59% <0.00%> (-0.52%) ⬇️
ad-mooncake-reverse 43.20% <0.00%> (-0.53%) ⬇️
ad-reversediff 43.11% <0.00%> (-0.53%) ⬇️
unit 92.75% <100.00%> (+0.09%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/censoring/composed_leaves.jl 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Benchmark comparison vs main

Minimum time per call. Buckets are PR time as a % of main, so lower is faster (🟢 faster, ⚪ within 5%, 🔴 slower). Counts of benchmarks per bucket:

Group 🟢 <50% 🟢 50–75% 🟢 75–95% ⚪ 95–105% 🔴 105–125% 🔴 125–150% 🔴 >150%
Evaluation 2 2 · 5 15 17 15
ForwardDiff · · 1 · 8 20 3
ReverseDiff (tape) · · · · 10 22 ·
Mooncake reverse · · · · 6 25 1
Mooncake forward · · · · 13 19 ·
Enzyme reverse · · · · 14 16 2
Enzyme forward · · · · 5 22 5
Evaluation — 56 benchmarks (by time change)
Benchmark main PR time memory
PrimaryCensored / Gamma+Uniform / analytical / rand 963.0 ns 1.7 μs 🔴 1.77× ⚪ 1.0×
PrimaryCensored / Gamma+Uniform / numerical / rand 1.0 μs 1.73 μs 🔴 1.72× ⚪ 1.0×
PrimaryCensored / Gamma+Exponential / numerical / rand 1.27 μs 2.1 μs 🔴 1.66× ⚪ 1.0×
DoubleIntervalCensored / LogNormal+Uniform / rand 1.08 μs 1.72 μs 🔴 1.6× ⚪ 1.0×
PrimaryCensored / Gamma+Uniform / analytical / cdf 8.78 μs 13.81 μs 🔴 1.57× ⚪ 1.0×
PrimaryCensored / Exponential+Uniform / numerical / cdf 160.44 μs 251.42 μs 🔴 1.57× ⚪ 1.0×
DoubleIntervalCensored / Exponential+Uniform / logpdf 291.24 μs 454.67 μs 🔴 1.56× ⚪ 1.0×
IntervalCensored / Arbitrary / pdf 3.74 μs 5.83 μs 🔴 1.56× ⚪ 1.0×
PrimaryCensored / Exponential+Uniform / numerical / pdf 329.72 μs 513.6 μs 🔴 1.56× ⚪ 1.0×
PrimaryCensored / Exponential+Uniform / numerical / logpdf 328.8 μs 511.87 μs 🔴 1.56× ⚪ 1.0×
DoubleIntervalCensored / Exponential+Uniform / pdf 292.08 μs 452.48 μs 🔴 1.55× ⚪ 1.0×
PrimaryCensored / Gamma+Uniform / analytical / logpdf 23.38 μs 36.17 μs 🔴 1.55× ⚪ 1.0×
DoubleIntervalCensored / Exponential+Uniform / cdf 147.75 μs 227.26 μs 🔴 1.54× ⚪ 1.0×
IntervalCensored / Regular / rand 2.27 μs 1.06 μs 🟢 0.47× ⚪ 1.0×
IntervalCensored / Arbitrary / logpdf 4.97 μs 7.61 μs 🔴 1.53× ⚪ 1.0×
PrimaryCensored / LogNormal+Exponential / numerical / rand 851.0 ns 1.3 μs 🔴 1.53× ⚪ 1.0×
IntervalCensored / Exponential / rand 1.03 μs 511.0 ns 🟢 0.5× ⚪ 1.0×
PrimaryCensored / Gamma+Uniform / analytical / pdf 24.56 μs 36.65 μs 🔴 1.49× ⚪ 1.0×
PrimaryCensored / Exponential+Uniform / numerical / rand 507.0 ns 751.0 ns 🔴 1.48× ⚪ 1.0×
PrimaryCensored / Weibull+Uniform / analytical / cdf 15.73 μs 23.12 μs 🔴 1.47× ⚪ 1.0×
PrimaryCensored / Gamma+Exponential / numerical / logpdf 1.1 ms 1.59 ms 🔴 1.44× ⚪ 1.0×
PrimaryCensored / Gamma+Exponential / numerical / pdf 1.1 ms 1.59 ms 🔴 1.44× ⚪ 1.0×
PrimaryCensored / Gamma+Exponential / numerical / cdf 547.64 μs 786.57 μs 🔴 1.44× ⚪ 1.0×
PrimaryCensored / Weibull+Uniform / analytical / logpdf 39.73 μs 56.04 μs 🔴 1.41× ⚪ 1.0×
PrimaryCensored / LogNormal+Uniform / analytical / rand 1.67 μs 992.0 ns 🟢 0.59× ⚪ 1.0×
PrimaryCensored / LogNormal+Uniform / numerical / rand 1.67 μs 992.0 ns 🟢 0.59× ⚪ 1.0×
PrimaryCensored / Gamma+Uniform / numerical / logpdf 835.03 μs 1.17 ms 🔴 1.4× ⚪ 1.0×
PrimaryCensored / Gamma+Uniform / numerical / pdf 836.24 μs 1.17 ms 🔴 1.4× ⚪ 1.0×
PrimaryCensored / Weibull+Uniform / analytical / pdf 40.73 μs 56.97 μs 🔴 1.4× ⚪ 1.0×
PrimaryCensored / Gamma+Uniform / numerical / cdf 413.17 μs 574.99 μs 🔴 1.39× ⚪ 1.0×
PrimaryCensored / Weibull+Uniform / numerical / cdf 199.08 μs 270.64 μs 🔴 1.36× ⚪ 1.0×
DoubleIntervalCensored / Exponential+Uniform / rand 598.0 ns 811.0 ns 🔴 1.36× ⚪ 1.0×
PrimaryCensored / Weibull+Uniform / numerical / pdf 410.79 μs 555.7 μs 🔴 1.35× ⚪ 1.0×
PrimaryCensored / Weibull+Uniform / numerical / logpdf 409.85 μs 554.28 μs 🔴 1.35× ⚪ 1.0×
IntervalCensored / Regular / pdf 3.75 μs 4.8 μs 🔴 1.28× ⚪ 1.0×
IntervalCensored / Exponential / logpdf 2.42 μs 3.08 μs 🔴 1.27× ⚪ 1.0×
IntervalCensored / Arbitrary / rand 2.01 μs 2.48 μs 🔴 1.23× ⚪ 1.0×
IntervalCensored / Regular / logpdf 5.3 μs 6.41 μs 🔴 1.21× ⚪ 1.0×
PrimaryCensored / LogNormal+Exponential / numerical / logpdf 839.36 μs 1.01 ms 🔴 1.21× ⚪ 1.0×
PrimaryCensored / LogNormal+Exponential / numerical / pdf 840.24 μs 1.02 ms 🔴 1.21× ⚪ 1.0×
IntervalCensored / Regular / cdf 1.94 μs 2.32 μs 🔴 1.2× ⚪ 1.0×
PrimaryCensored / LogNormal+Exponential / numerical / cdf 420.23 μs 500.63 μs 🔴 1.19× ⚪ 1.0×
PrimaryCensored / LogNormal+Uniform / numerical / logpdf 818.35 μs 938.1 μs 🔴 1.15× ⚪ 1.0×
PrimaryCensored / LogNormal+Uniform / numerical / cdf 405.6 μs 464.8 μs 🔴 1.15× ⚪ 1.0×
PrimaryCensored / LogNormal+Uniform / numerical / pdf 819.55 μs 939.0 μs 🔴 1.15× ⚪ 1.0×
PrimaryCensored / Weibull+Uniform / analytical / rand 4.32 μs 4.86 μs 🔴 1.12× ⚪ 1.0×
PrimaryCensored / Weibull+Uniform / numerical / rand 4.32 μs 4.85 μs 🔴 1.12× ⚪ 1.0×
IntervalCensored / Exponential / cdf 849.0 ns 921.0 ns 🔴 1.08× ⚪ 1.0×
DoubleIntervalCensored / LogNormal+Uniform / logpdf 22.43 μs 24.16 μs 🔴 1.08× ⚪ 1.0×
IntervalCensored / Arbitrary / cdf 3.05 μs 3.27 μs 🔴 1.07× ⚪ 1.0×
DoubleIntervalCensored / LogNormal+Uniform / pdf 20.97 μs 22.39 μs 🔴 1.07× ⚪ 1.0×
IntervalCensored / Exponential / pdf 1.69 μs 1.62 μs ⚪ 0.96× ⚪ 1.0×
PrimaryCensored / LogNormal+Uniform / analytical / cdf 11.37 μs 10.95 μs ⚪ 0.96× ⚪ 1.0×
PrimaryCensored / LogNormal+Uniform / analytical / logpdf 32.65 μs 32.19 μs ⚪ 0.99× ⚪ 1.0×
PrimaryCensored / LogNormal+Uniform / analytical / pdf 33.85 μs 33.45 μs ⚪ 0.99× ⚪ 1.0×
DoubleIntervalCensored / LogNormal+Uniform / cdf 10.52 μs 10.43 μs ⚪ 0.99× ⚪ 1.0×
AD gradients — 192 benchmarks (by time change)
Benchmark main PR time memory
AD gradients / PrimaryCensored LogNormal+Uniform analytical 32d / Mooncake reverse 108.99 μs 176.57 μs 🔴 1.62× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform numerical / Enzyme forward 33.45 μs 53.22 μs 🔴 1.59× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+ExponentiallyTilted numerical / Enzyme reverse 63.89 μs 101.59 μs 🔴 1.59× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+ExponentiallyTilted numerical / ForwardDiff 55.91 μs 87.94 μs 🔴 1.57× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform numerical / ForwardDiff 30.81 μs 48.01 μs 🔴 1.56× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical / Enzyme forward 155.48 μs 241.57 μs 🔴 1.55× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+truncNormal numerical GaussLegendre solver / Enzyme forward 346.34 μs 525.71 μs 🔴 1.52× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+ExponentiallyTilted numerical / Enzyme reverse 187.81 μs 284.89 μs 🔴 1.52× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical / ForwardDiff 120.98 μs 183.12 μs 🔴 1.51× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+ExponentiallyTilted numerical / Enzyme forward 172.95 μs 260.62 μs 🔴 1.51× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+ExponentiallyTilted numerical / Enzyme forward 50.18 μs 75.54 μs 🔴 1.51× ⚪ 1.0×
AD gradients / Convolved Gamma+LogNormal numerical / Enzyme reverse 104.21 μs 156.3 μs 🔴 1.5× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+ExponentiallyTilted numerical / ForwardDiff 140.39 μs 210.39 μs 🔴 1.5× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched logpdf / Mooncake reverse 38.51 μs 57.68 μs 🔴 1.5× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal / Mooncake reverse 67.4 μs 100.78 μs 🔴 1.5× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical / ForwardDiff 4.31 μs 6.44 μs 🔴 1.5× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical / Enzyme reverse 184.28 μs 273.67 μs 🔴 1.49× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical / Mooncake reverse 329.34 μs 486.99 μs 🔴 1.48× ⚪ 1.0×
AD gradients / Convolved Gamma+LogNormal numerical / Enzyme forward 76.79 μs 112.72 μs 🔴 1.47× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical / Mooncake reverse 35.44 μs 51.97 μs 🔴 1.47× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical 32d / Mooncake forward 559.33 μs 816.77 μs 🔴 1.46× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+ExponentiallyTilted numerical / ForwardDiff 53.04 μs 77.44 μs 🔴 1.46× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical 32d / Enzyme reverse 1.09 ms 1.59 ms 🔴 1.46× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical / Mooncake forward 395.46 μs 576.25 μs 🔴 1.46× ⚪ 1.0×
AD gradients / IntervalCensored Gamma regular / ForwardDiff 1.69 μs 2.46 μs 🔴 1.46× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform numerical / Enzyme reverse 46.5 μs 67.71 μs 🔴 1.46× ⚪ 1.0×
AD gradients / Weighted LogNormal scalar logpdf / Enzyme reverse 847.0 ns 1.23 μs 🔴 1.46× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform analytical / ForwardDiff 5.16 μs 7.5 μs 🔴 1.45× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+truncNormal numerical GaussLegendre solver / ForwardDiff 260.42 μs 378.75 μs 🔴 1.45× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+ExponentiallyTilted numerical / Mooncake forward 574.57 μs 833.94 μs 🔴 1.45× ⚪ 1.0×
AD gradients / Convolved Gamma+LogNormal numerical / ForwardDiff 78.88 μs 114.32 μs 🔴 1.45× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical / Enzyme forward 39.02 μs 56.54 μs 🔴 1.45× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+ExponentiallyTilted numerical / Enzyme forward 52.83 μs 76.33 μs 🔴 1.44× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched pdf / Mooncake reverse 32.93 μs 47.44 μs 🔴 1.44× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+truncNormal numerical GaussLegendre solver / Mooncake forward 879.16 μs 1.26 ms 🔴 1.44× ⚪ 1.0×
AD gradients / Convolved Gamma+LogNormal numerical / Mooncake forward 326.81 μs 469.92 μs 🔴 1.44× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched pdf / Mooncake reverse 16.41 μs 23.46 μs 🔴 1.43× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform numerical / Mooncake reverse 278.52 μs 397.78 μs 🔴 1.43× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical / Enzyme forward 10.9 μs 15.55 μs 🔴 1.43× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform analytical / Enzyme forward 11.47 μs 16.35 μs 🔴 1.43× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical 32d / Enzyme reverse 43.78 μs 62.39 μs 🔴 1.43× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched logpdf / Mooncake reverse 20.67 μs 29.46 μs 🔴 1.42× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical / Mooncake reverse 55.38 μs 78.73 μs 🔴 1.42× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical 32d / Enzyme forward 2.19 ms 3.11 ms 🔴 1.42× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical 32d / Mooncake forward 28.04 ms 39.78 ms 🔴 1.42× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical / Enzyme reverse 8.23 μs 11.61 μs 🔴 1.41× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Gamma / Enzyme forward 12.64 μs 17.77 μs 🔴 1.41× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+truncNormal numerical / Enzyme forward 45.9 μs 64.41 μs 🔴 1.4× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Weibull / Enzyme forward 16.44 μs 23.04 μs 🔴 1.4× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical / Mooncake forward 17.25 μs 24.16 μs 🔴 1.4× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical 32d / Mooncake forward 1.09 ms 1.52 ms 🔴 1.39× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical 32d / Mooncake reverse 120.06 μs 166.04 μs 🔴 1.38× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched pdf / Enzyme forward 5.78 μs 7.98 μs 🔴 1.38× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+truncNormal numerical / ForwardDiff 46.97 μs 64.92 μs 🔴 1.38× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched logpdf / Enzyme forward 5.85 μs 8.06 μs 🔴 1.38× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical 32d / Enzyme forward 84.86 μs 116.82 μs 🔴 1.38× ⚪ 1.0×
AD gradients / IntervalCensored Gamma regular / Enzyme forward 7.69 μs 10.58 μs 🔴 1.38× ⚪ 1.0×
AD gradients / IntervalCensored Gamma regular / Mooncake forward 7.64 μs 10.5 μs 🔴 1.37× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+ExponentiallyTilted numerical / Enzyme reverse 73.7 μs 101.06 μs 🔴 1.37× ⚪ 1.0×
AD gradients / IntervalCensored Gamma regular / Enzyme reverse 3.36 μs 4.61 μs 🔴 1.37× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform analytical / Mooncake forward 19.48 μs 26.68 μs 🔴 1.37× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched logpdf / ForwardDiff 2.17 μs 2.98 μs 🔴 1.37× ⚪ 1.0×
AD gradients / Weighted LogNormal scalar logpdf / Mooncake reverse 15.24 μs 20.75 μs 🔴 1.36× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical / Mooncake reverse 450.63 μs 612.55 μs 🔴 1.36× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched pdf / ForwardDiff 2.11 μs 2.86 μs 🔴 1.36× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+truncNormal numerical GaussLegendre solver / Enzyme reverse 651.1 μs 884.82 μs 🔴 1.36× ⚪ 1.01×
AD gradients / Weighted LogNormal scalar logpdf / Enzyme forward 5.82 μs 7.9 μs 🔴 1.36× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical 32d / ForwardDiff 15.46 ms 21.0 ms 🔴 1.36× ⚪ 1.0×
AD gradients / Weighted LogNormal scalar logpdf / ForwardDiff 399.0 ns 541.0 ns 🔴 1.36× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched logpdf / Enzyme forward 6.6 μs 8.94 μs 🔴 1.35× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+truncNormal numerical / Mooncake reverse 419.46 μs 566.26 μs 🔴 1.35× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform analytical / Enzyme reverse 9.17 μs 12.36 μs 🔴 1.35× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical 32d / Mooncake reverse 2.46 ms 3.31 ms 🔴 1.35× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal / Mooncake forward 13.63 μs 18.32 μs 🔴 1.34× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Gamma / Mooncake forward 21.92 μs 29.46 μs 🔴 1.34× ⚪ 1.0×
AD gradients / Product{Weighted} LogNormal vector logpdf / ForwardDiff 439.0 ns 590.0 ns 🔴 1.34× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Weibull / Enzyme reverse 14.59 μs 19.54 μs 🔴 1.34× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform logccdf / Enzyme forward 6.47 μs 8.65 μs 🔴 1.34× ⚪ 1.0×
AD gradients / Convolved Normal+Normal analytical / Mooncake reverse 12.56 μs 16.77 μs 🔴 1.34× ⚪ 1.0×
AD gradients / Convolved Normal+Normal analytical / Enzyme forward 6.07 μs 8.1 μs 🔴 1.33× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+ExponentiallyTilted numerical / Mooncake reverse 467.21 μs 622.29 μs 🔴 1.33× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched pdf / Enzyme forward 6.56 μs 8.73 μs 🔴 1.33× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+ExponentiallyTilted numerical / Mooncake reverse 530.86 μs 704.03 μs 🔴 1.33× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Weibull / Mooncake forward 31.73 μs 42.04 μs 🔴 1.32× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Weibull / Mooncake reverse 52.16 μs 69.09 μs 🔴 1.32× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical / Enzyme forward 7.42 μs 9.82 μs 🔴 1.32× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal / Enzyme forward 7.72 μs 10.2 μs 🔴 1.32× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched logpdf / ForwardDiff 6.6 μs 8.73 μs 🔴 1.32× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Weibull / ForwardDiff 28.41 μs 37.48 μs 🔴 1.32× ⚪ 1.0×
AD gradients / ExponentiallyTilted logpdf wrt r / ForwardDiff 402.0 ns 530.0 ns 🔴 1.32× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+ExponentiallyTilted numerical / Mooncake reverse 429.15 μs 564.92 μs 🔴 1.32× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform analytical / Mooncake reverse 42.96 μs 56.54 μs 🔴 1.32× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform numerical / ReverseDiff (tape) 1.09 ms 1.43 ms 🔴 1.31× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched logpdf / Mooncake forward 10.72 μs 14.07 μs 🔴 1.31× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Gamma / Mooncake reverse 43.89 μs 57.53 μs 🔴 1.31× ⚪ 1.0×
AD gradients / ExponentiallyTilted logpdf wrt r / Enzyme forward 5.94 μs 7.76 μs 🔴 1.31× ⚪ 1.0×
AD gradients / IntervalCensored Weibull regular / ForwardDiff 683.0 ns 891.0 ns 🔴 1.3× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched logpdf / ReverseDiff (tape) 29.35 μs 38.18 μs 🔴 1.3× ⚪ 1.0×
AD gradients / Weighted LogNormal scalar logpdf / ReverseDiff (tape) 12.67 μs 16.47 μs 🔴 1.3× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal / ReverseDiff (tape) 170.06 μs 220.95 μs 🔴 1.3× ⚪ 1.0×
AD gradients / Weighted LogNormal scalar logpdf / Mooncake forward 4.44 μs 5.76 μs 🔴 1.3× ⚪ 1.0×
AD gradients / IntervalCensored Gamma regular / ReverseDiff (tape) 9.07 μs 11.76 μs 🔴 1.3× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Gamma / ForwardDiff 25.35 μs 32.89 μs 🔴 1.3× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform analytical / ReverseDiff (tape) 74.27 μs 96.31 μs 🔴 1.3× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched pdf / ReverseDiff (tape) 28.98 μs 37.54 μs 🔴 1.3× ⚪ 1.0×
AD gradients / Product{Weighted} LogNormal vector logpdf / Mooncake reverse 20.0 μs 25.91 μs 🔴 1.3× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical / ReverseDiff (tape) 93.91 μs 121.6 μs 🔴 1.29× ⚪ 1.0×
AD gradients / Convolved Normal+Normal analytical / Mooncake forward 4.28 μs 5.53 μs 🔴 1.29× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched logpdf / ReverseDiff (tape) 84.25 μs 108.85 μs 🔴 1.29× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical 32d / Enzyme reverse 25.12 μs 32.44 μs 🔴 1.29× ⚪ 1.0×
AD gradients / Convolved Normal+Normal analytical / ReverseDiff (tape) 12.7 μs 16.39 μs 🔴 1.29× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Weibull / ReverseDiff (tape) 144.47 μs 186.39 μs 🔴 1.29× ⚪ 1.0×
AD gradients / IntervalCensored Gamma regular / Mooncake reverse 17.48 μs 22.54 μs 🔴 1.29× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical / ReverseDiff (tape) 72.48 μs 93.29 μs 🔴 1.29× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical / Mooncake forward 12.08 μs 15.55 μs 🔴 1.29× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched pdf / ReverseDiff (tape) 76.47 μs 98.22 μs 🔴 1.28× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical 32d / ReverseDiff (tape) 570.59 μs 731.91 μs 🔴 1.28× ⚪ 1.0×
AD gradients / Convolved Gamma+LogNormal numerical / Mooncake reverse 518.6 μs 664.84 μs 🔴 1.28× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical 32d / ReverseDiff (tape) 471.31 μs 604.11 μs 🔴 1.28× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical / ReverseDiff (tape) 996.61 μs 1.28 ms 🔴 1.28× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical / Enzyme reverse 5.23 μs 6.68 μs 🔴 1.28× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical 32d / ReverseDiff (tape) 11.01 ms 14.02 ms 🔴 1.27× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical / ReverseDiff (tape) 1.74 ms 2.22 ms 🔴 1.27× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical 32d / Enzyme forward 972.67 μs 1.24 ms 🔴 1.27× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched pdf / ForwardDiff 6.85 μs 8.71 μs 🔴 1.27× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Gamma / ReverseDiff (tape) 141.46 μs 179.23 μs 🔴 1.27× ⚪ 1.0×
AD gradients / Product{Weighted} LogNormal vector logpdf / ReverseDiff (tape) 12.56 μs 15.9 μs 🔴 1.27× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical 32d / Mooncake reverse 1.9 ms 2.4 ms 🔴 1.27× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+truncNormal numerical GaussLegendre solver / ReverseDiff (tape) 2.03 ms 2.57 ms 🔴 1.27× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform numerical 32d / ReverseDiff (tape) 6.45 ms 8.17 ms 🔴 1.27× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched pdf / Mooncake forward 6.71 μs 8.49 μs 🔴 1.26× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched logpdf / Mooncake forward 7.06 μs 8.9 μs 🔴 1.26× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform logccdf / Enzyme reverse 3.4 μs 4.28 μs 🔴 1.26× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal / ForwardDiff 21.63 μs 27.24 μs 🔴 1.26× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular / Enzyme reverse 3.01 μs 3.78 μs 🔴 1.26× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched pdf / Mooncake forward 10.78 μs 13.46 μs 🔴 1.25× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+ExponentiallyTilted numerical / Mooncake forward 402.98 μs 502.0 μs 🔴 1.25× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+truncNormal numerical / Enzyme reverse 69.92 μs 87.09 μs 🔴 1.25× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform logccdf / ReverseDiff (tape) 37.18 μs 46.29 μs 🔴 1.25× ⚪ 1.0×
AD gradients / IntervalCensored Gamma arbitrary / ForwardDiff 1.8 μs 2.22 μs 🔴 1.23× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical 32d / Mooncake forward 16.4 ms 20.15 ms 🔴 1.23× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform logccdf / Mooncake reverse 34.86 μs 42.8 μs 🔴 1.23× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched pdf / Enzyme reverse 4.76 μs 5.83 μs 🔴 1.22× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+truncNormal numerical / Mooncake forward 321.9 μs 392.82 μs 🔴 1.22× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical / Mooncake forward 231.5 μs 282.41 μs 🔴 1.22× ⚪ 1.0×
AD gradients / IntervalCensored Gamma arbitrary / Mooncake reverse 50.35 μs 61.4 μs 🔴 1.22× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular / Mooncake reverse 21.87 μs 26.56 μs 🔴 1.21× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal / Enzyme reverse 5.34 μs 6.47 μs 🔴 1.21× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular batched logpdf / Enzyme reverse 5.11 μs 6.19 μs 🔴 1.21× ⚪ 1.0×
AD gradients / Convolved Gamma+LogNormal numerical / ReverseDiff (tape) 3.0 ms 3.64 ms 🔴 1.21× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+Uniform numerical / Mooncake forward 171.99 μs 208.25 μs 🔴 1.21× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical / Enzyme reverse 65.57 μs 79.39 μs 🔴 1.21× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular / ReverseDiff (tape) 17.67 μs 21.37 μs 🔴 1.21× ⚪ 1.0×
AD gradients / Convolved Normal+Normal analytical / Enzyme reverse 2.98 μs 3.6 μs 🔴 1.21× ⚪ 1.0×
AD gradients / IntervalCensored Gamma arbitrary / Enzyme forward 9.1 μs 10.98 μs 🔴 1.21× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical / ForwardDiff 2.3 μs 2.77 μs 🔴 1.2× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched logpdf / Enzyme reverse 5.54 μs 6.63 μs 🔴 1.2× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular / Enzyme forward 6.95 μs 8.32 μs 🔴 1.2× ⚪ 1.0×
AD gradients / ExponentiallyTilted logpdf wrt r / Mooncake reverse 13.06 μs 15.53 μs 🔴 1.19× ⚪ 1.0×
AD gradients / IntervalCensored Weibull regular / Enzyme forward 7.03 μs 8.36 μs 🔴 1.19× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+ExponentiallyTilted numerical / ReverseDiff (tape) 2.11 ms 2.51 ms 🔴 1.19× ⚪ 1.0×
AD gradients / Product{Weighted} LogNormal vector logpdf / Enzyme forward 6.95 μs 8.2 μs 🔴 1.18× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical 32d / Enzyme reverse 460.81 μs 541.79 μs 🔴 1.18× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+truncNormal numerical / ReverseDiff (tape) 3.44 ms 4.04 ms 🔴 1.17× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+truncNormal numerical GaussLegendre solver / Mooncake reverse 1.65 ms 1.92 ms 🔴 1.17× ⚪ 1.0×
AD gradients / Convolved Normal+Normal analytical / ForwardDiff 517.0 ns 601.0 ns 🔴 1.16× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical 32d / ForwardDiff 1.3 ms 1.09 ms 🟢 0.84× ⚪ 1.0×
AD gradients / IntervalCensored Gamma arbitrary / Mooncake forward 10.42 μs 12.03 μs 🔴 1.15× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+ExponentiallyTilted numerical / ReverseDiff (tape) 3.04 ms 3.49 ms 🔴 1.15× ⚪ 1.0×
AD gradients / DoubleIntervalCensored Gamma / Enzyme reverse 12.16 μs 13.92 μs 🔴 1.14× ⚪ 1.0×
AD gradients / ExponentiallyTilted logpdf wrt r / Enzyme reverse 2.63 μs 3.0 μs 🔴 1.14× ⚪ 1.0×
AD gradients / PrimaryCensored Gamma+Uniform analytical 32d / ForwardDiff 572.53 μs 651.3 μs 🔴 1.14× ⚪ 1.0×
AD gradients / IntervalCensored Gamma arbitrary / ReverseDiff (tape) 8.3 μs 9.44 μs 🔴 1.14× ⚪ 1.0×
AD gradients / ExponentiallyTilted logpdf wrt r / Mooncake forward 4.2 μs 4.77 μs 🔴 1.14× ⚪ 1.0×
AD gradients / Product{Weighted} LogNormal vector logpdf / Enzyme reverse 655.0 ns 741.0 ns 🔴 1.13× ⚪ 1.0×
AD gradients / IntervalCensored Weibull regular / ReverseDiff (tape) 12.56 μs 14.17 μs 🔴 1.13× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform logccdf / Mooncake forward 7.73 μs 8.71 μs 🔴 1.13× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform logccdf / ForwardDiff 1.19 μs 1.34 μs 🔴 1.13× ⚪ 1.0×
AD gradients / IntervalCensored Weibull regular / Mooncake reverse 17.14 μs 19.28 μs 🔴 1.12× ⚪ 1.0×
AD gradients / IntervalCensored Gamma arbitrary / Enzyme reverse 4.99 μs 5.56 μs 🔴 1.12× 🔴 1.05×
AD gradients / Product{Weighted} LogNormal vector logpdf / Mooncake forward 5.71 μs 6.34 μs 🔴 1.11× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+ExponentiallyTilted numerical / Mooncake forward 384.61 μs 426.87 μs 🔴 1.11× ⚪ 1.0×
AD gradients / IntervalCensored Weibull regular / Enzyme reverse 3.44 μs 3.79 μs 🔴 1.1× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular / Mooncake forward 6.18 μs 6.8 μs 🔴 1.1× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform numerical / ForwardDiff 49.75 μs 54.79 μs 🔴 1.1× ⚪ 1.0×
AD gradients / IntervalCensored LogNormal regular / ForwardDiff 746.0 ns 821.0 ns 🔴 1.1× ⚪ 1.0×
AD gradients / ExponentiallyTilted logpdf wrt r / ReverseDiff (tape) 7.68 μs 8.41 μs 🔴 1.09× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical 32d / ForwardDiff 62.58 μs 67.63 μs 🔴 1.08× ⚪ 1.0×
AD gradients / IntervalCensored Weibull regular / Mooncake forward 5.95 μs 6.4 μs 🔴 1.08× ⚪ 1.0×
AD gradients / PrimaryCensored LogNormal+Uniform analytical 32d / Enzyme forward 42.13 μs 45.04 μs 🔴 1.07× ⚪ 1.0×
AD gradients / PrimaryCensored Weibull+ExponentiallyTilted numerical / ReverseDiff (tape) 2.53 ms 2.7 ms 🔴 1.07× ⚪ 1.0×
AD gradients / DoubleIntervalCensored LogNormal batched pdf / Enzyme reverse 7.41 μs 7.8 μs 🔴 1.05× ⚪ 1.0×

@seabbs-bot seabbs-bot changed the title feat: censored leaves are first-class composer leaves (E2) — BLOCKED on ComposedDistributions registration feat: CD-owned ComposedDistributions bridge — censored leaves are first-class composer leaves (E2) Jul 11, 2026
ComposedDistributions and ConvolvedDistributions move from [weakdeps] to
[deps], with git [sources] pinning ComposedDistributions to its
chore/convolved-0.2-compat branch (ConvolvedDistributions needs the 0.2
line; [sources] is not honoured transitively, so it is pinned too, on
main). Julia cannot resolve an unregistered package through
[weakdeps] + [sources], so the composer-leaf methods move out of
CensoredDistributionsComposedDistributionsExt into
src/censoring/composed_leaves.jl and load unconditionally.

Test coverage adds: a shared-tag regression (a tied delay censored on
one branch and bare on another must inventory as the same edge, not
double-counted), the stacked IntervalCensored(Truncated(PrimaryCensored))
rebuild keeping every fixed field, and vector-boundary round-tripping.

Still hard-dep on dev [sources]; do not merge until ComposedDistributions'
convolved-0.2-compat lands on its main and both packages are registered.
@seabbs-bot

Copy link
Copy Markdown
Collaborator Author

Status update: the packaging restructure this description already anticipated ("hard dep now, CD-owned extension later") is now shipped in 5c22407CensoredDistributionsComposedDistributionsExt is gone, the composer-leaf hooks live in src/censoring/composed_leaves.jl and load unconditionally under the [deps] + git [sources] pin, matching the Packaging section above.

Local verification (this worktree only, julia --project=. -e 'using Pkg; Pkg.test()', excluding the separately-CI'd :ad tag): 4841/4841 tests passed, ~7m16s, including Aqua, ExplicitImports, JET and doctest. Also added a _shared_tag double-count regression test, stacked-wrapper rebuild coverage and vector-boundary round-tripping.

Still draft — do not merge: hard-dep on dev [sources] (ComposedDistributions@chore/convolved-0.2-compat, ConvolvedDistributions@main) until that compat bump lands on ComposedDistributions' main and both packages are registered.

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

ConvolvedDistributions' main now depends on EpiAwareADTools, which has no
registered versions anywhere (CD's own migration onto it, #850, is not
merged either), so a fresh resolve against current main is unconditionally
broken. This worktree's own cached Manifest.toml only kept working because
it resolved before that migration landed -- exactly the trap a fresh clone
or CI run falls into.

Pinned to da71dd1, the last commit before the migration; resolves to the
identical git-tree-sha this worktree already had, so nothing else changes.
Repoint to main once EpiAwareADTools registers. Same fix applied on #853
(E3, which hit this from a genuinely fresh instantiate).
@seabbs-bot

Copy link
Copy Markdown
Collaborator Author

Follow-up fix (b2e4009): repinned `ConvolvedDistributions` in `[sources]` to a commit SHA (`da71dd1`) instead of `main`.

`ConvolvedDistributions` `main` has since moved to depend on `EpiAwareADTools`, which has no registered versions anywhere (that migration, tracked separately, is not merged on CD's side either), so a fresh resolve against current `main` is unconditionally broken — not merely undesirable. This worktree's cached `Manifest.toml` only kept passing because it resolved before that migration landed on upstream `main`; a fresh clone or CI run would have hit it. `da71dd1` resolves to the identical `git-tree-sha` this branch already had pinned, so nothing else changes — reconfirmed green after repinning (package loads, resolved content identical).

Repoint to `main` once `EpiAwareADTools` is registered. Same fix applied on #853 (E3), which is where this was first caught (genuinely fresh `instantiate`).

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

seabbs-bot added a commit that referenced this pull request Jul 12, 2026
…851)

CI on this PR failed (test on every OS/version, downgrade-compat) because
the extension imported IntervalCensored.jl internals (is_regular_intervals,
interval_width) that are not declared `public` in CensoredDistributions --
ExplicitImports correctly flags any cross-module import of a non-public
name, and package extensions are separate modules.

Root cause was the extension boundary itself, not (only) the compat range.
#851 established the fix for exactly this shape of problem: when CD needs a
currently-unregistered package at more than "optional extension" strength,
move it to a hard [deps] entry, pin it via [sources] (Julia will not resolve
an unregistered package declared only in [weakdeps], even with [sources]),
and move the bridging code from ext/ into src/ as a plain include()'d file
in the same module -- so it never needs to cross-import a non-public name
in the first place. Applying that here:

- ext/CensoredDistributionsConvolvedDistributionsExt.jl ->
  src/censoring/convolve_series.jl, module wrapper and internal
  import/using lines dropped (already in scope via the main module: pdf via
  the existing Distributions import, IntervalCensored/PrimaryCensored/
  is_regular_intervals/interval_width as CD's own same-module definitions).
- ConvolvedDistributions: [weakdeps] -> [deps], drop its [extensions]
  entry, compat "0.1, 0.2" -> "0.2" (convolve_series doesn't exist in the
  registered 0.1 line -- the real reason CI's `test` jobs failed once the
  ExplicitImports issue is also accounted for: a weakdep gets no [sources]
  override, so it resolved from the registry to 0.1.0, which lacks
  convolve_series entirely).
- [sources] pinned to a commit SHA, not `main`: ConvolvedDistributions main
  now depends on the unregistered EpiAwareADTools, so a fresh resolve
  against current main is unconditionally broken. Same SHA as #851/#853;
  this Project.toml block is expected to collide with theirs on rebase,
  identically, whichever merges first.
- Mirrored the same [deps]+[sources] addition in every sub-environment that
  path-deps on CensoredDistributions (test/, test/ad/, test/jet/, docs/):
  [sources] is not honoured transitively, so each independently needs it or
  precompiling CD itself fails there.
- test/integration/ConvolvedDistributions.jl: dropped the now-meaningless
  "extension loads via Base.get_extension" test item (always available now,
  no load gate); renamed the remaining items away from "extension" language.
- docs FAQ: no longer describes this as "a package extension".

Verified: full local suite (this worktree's own test/, excluding the
separately-CI'd :ad tag) 4829/4829 passed, including Aqua (piracy/
ambiguity/stale-deps) and ExplicitImports (now clean -- no more cross-module
import of a non-public name, confirming the root-cause diagnosis). Spot-
checked ForwardDiff.gradient through convolve_series(double_interval_censored,
series): finite, sane gradient. The two convolve_series methods and the
_grid_pmf helper are byte-identical to the original PR; only their location
and import wiring changed.

Not fixed here (tracked as CensoredDistributions#854): there is no dedicated
AD scenario for convolve_series in test/ADFixtures/test/ad, so the original
PR's all-green ad/* CI jobs were exercising unrelated code, not this bridge,
across the other 5 backends beyond the ForwardDiff spot-check above.

Draft: hard-dep on dev [sources]; do not merge until ConvolvedDistributions
registers and the EpiAwareADTools line resolves. Do NOT merge to main.
seabbs-bot added a commit that referenced this pull request Jul 16, 2026
…loor (#872)

build: currency refresh — ReparameterisedDistributions at current main + 1.11 floor

Brings the integration base up to date with the ecosystem as it stands, and
applies the ecosystem-wide 1.11 floor. This is the currency refresh, NOT the
source port: it deliberately does not adopt ComposedDistributions,
ConvolvedDistributions or ModifiedDistributions, which the E-series
(#847/#851/#855) owns.

Integration was already current for everything CensoredDistributions actually
uses — ReparameterisedDistributions landed via #871 (the moment-parameterisation
move), and its `[sources]` pin at `rev = "main"` already resolves to the current
main tip. So the only genuine currency delta is the Julia 1.11 floor:
`julia = "1.10, 1.11, 1.12"` becomes `"1.11, 1.12"`. The test workflow already
runs only `julia_versions: '["1"]'` and drops the 1.10 LTS, because `[sources]`
is honoured only from Julia 1.11 — the Project.toml compat now matches that.

The standalone distribution-ops packages are left out on purpose. They cannot be
carried in a green state until their source is actually used:

- Declaring them without `using` them fails `Aqua.test_stale_deps`.
- ConvolvedDistributions has moved 0.1 -> 0.2, and 0.2 now depends on the
  unregistered EpiAwareADTools. `[sources]` is not honoured transitively and
  Julia refuses a `[sources]` entry for a package that is not a direct
  dependency, so sourcing EpiAwareADTools forces yet another unused dependency
  and another stale-deps failure.

There is therefore no green configuration that carries the unused dist-ops
dependencies. They become carryable only when the E-series wires them into the
source, at which point ConvolvedDistributions and EpiAwareADTools must be adopted
together.

Verified locally: resolve + precompile clean (no method-overwrite), full
Pkg.test 34080 passing (2 expected broken), AD matrix green.
@seabbs-bot
seabbs-bot force-pushed the feat/composed-censored-leaves branch from f5d429d to b2e4009 Compare July 16, 2026 20:42
@github-actions

Copy link
Copy Markdown
Contributor

📖 Documentation preview is ready!

View the docs for this PR at: https://EpiAware.github.io/CensoredDistributions.jl/previews/PR851/

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

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.

1 participant