Skip to content

feat(analysis): issue #21 zero handling + glmGamPoi port, and the KYAML pilot - #80

Merged
arena-ai-coding-agent[bot] merged 2 commits into
mainfrom
arena/01a0db23-metamanifold-webui
Sep 26, 2026
Merged

arena-ai-coding-agent[bot] merged 2 commits into
mainfrom
arena/01a0db23-metamanifold-webui

Conversation

@arena-ai-coding-agent

Copy link
Copy Markdown

Summary

Two pieces of work, on one branch, each with its own commit:

  1. Issue feat(analysis): Advanced zero handling — glmGamPoi dispersion, Bayesian multiplicative replacement, multiplicative replacement with delta  #21 — advanced zero handling and the glmGamPoi dispersion port (ae8323d).
  2. The KYAML pilot (cf5102f), the owner's ruling of 2026-09-26 making this repository the
    estate's pilot for the migration, plus a temporary CI probe (1e77a81).

1. Issue #21

Zero replacement, implemented rather than aliased (src/analysis/zero_replacement.jl):

  • multiplicative replacement (Martín-Fernández, Barceló-Vidal & Pawlowsky-Glahn 2003), the
    operator of zCompositions::multRepl: zeros get delta × per-part detection limit,
    observed parts scale by 1 − Δ, and the sample total and the ratios among observed
    parts are preserved exactly;
  • Bayesian multiplicative replacement (Martín-Fernández, Hron, Templ, Filzmoser &
    Palarea-Albaladejo 2015), the GBM of cmultRepl: posterior mean of a Dirichlet-multinomial
    with the leave-one-out prior mean and concentration 1/gmean(t) unless alpha is supplied,
    with the reference's frac × colmins cap and its adjust switch;
  • both refuse by name what they cannot do (δ outside (0,1); an imputed mass that would consume
    the sample, naming the largest admissible δ; all-zero samples; never-observed parts; parts
    seen in fewer than two samples) and both record a full provenance block, including all
    replacement is biased
    .

Dispersion (src/analysis/dispersion.jl) is a pure-Julia port of glmGamPoi
(Ahlmann-Eltze & Huber 2020): Cox-Reid adjusted NB MLE with the reference's 0.99 factor and
its early returns, the dnorm-weighted local-median trend, the quasi-likelihood conversion,
the inverse-chisquare prior by Nelder-Mead. The natural-spline abundance trend is not
ported
: true is refused, unset is refused at ≥ 100 features, false runs the reference's
own non-trended prior and records the deviation. estimation.jl's by-name refusal becomes the
real two-pass path (theta = 1/alpha, stats::glm(poisson()) where α is 0).

Proofs (proofs/agda/, Agda 2.7.0.1 + agda-stdlib 2.1.1, --safe, no postulates):
totals and ratios preserved; imputed values positive and below their limit; no
data-determined rule can be faithful (the fibre behind "everything is biased"); the shrinkage
lies between prior and estimate. proofs/agda/README.md records what is not proved and
what would falsify each file.

Surface: Julia config + Nickel contract + JSON schema + frontend types/expander (δ slider
with a replacement preview, α field, trend selector, estimated-runtime note), DEED echo,
DANGER banner at ≥3 δ trials, unit + integration tests, 100/1000/10000-taxa benchmark.

2. KYAML pilot

just use-kyaml / just use-yaml / just check-kyaml (scripts/kyaml/KYAML.jl), the drift
list (config/kyaml/drift.txt), and the operating manual (docs/pilots/kyaml-pilot.md).
Comments keep their association, --check is canonical-form checking (idempotent by
construction), refusals name file and line and write nothing, and the doc records what the
tools make the owner do: nothing, beyond one just use-kyaml.

What is verified, and what is not

Honest status: none of the Julia or R code in this PR has been executed. The authoring
sandbox has no Julia and no R (all distribution hosts are blocked), so:

  • every Python code path was checked by reading, the Julia by tree-sitter parse only;
  • the numeric expectations come from test/fixtures/issue21/golden.json, whose generator
    block states plainly that they are a pinned transcription of the published methods rather
    than a live call, and that test/reference/issue21_reference.jl (next, in Julia) is what
    turns them into a reproduced result;
  • the Agda proofs were checked (all three modules, clean) on a hand-assembled Agda
    toolchain; the CI lane for them is written but needs the image built (below).

The first CI run is the debugger. Expect it to find something; the fixtures, the tests and
the bench are written so that what it finds is named rather than mysterious.

Blockers that are yours, not the branch's

  1. CI cannot start in this repository at all, for anybody. Two repository settings:
    • Allowed actions: julia-actions/setup-julia, julia-actions/cache,
      julia-actions/julia-processcoverage are not allowed ("all actions must be from a
      repository owned by hyperpolymath, created by GitHub, verified in the Marketplace, or
      match arena-ai-coding-agent[bot]"). Your own push to main fails on this.
    • Allowed actors: "Actor is not allowed to trigger Actions workflows" for
      arena-ai-coding-agent[bot] — proven independent of the allow-list by
      .github/workflows/ci-probe.yml, a workflow with no uses: at all, which still
      fails startup.
      Both are in Settings → Actions → General. Until then this PR cannot be verified: the only
      Julia/R runners available are CI's.
  2. The proofs lane needs the image: proofs job is gated on vars.STAPELN_AGDA_IMAGE;
    build Containerfile (per stapeln.toml) and set the variable. While it is unset the
    hygiene job prints the actionable line on every run, so the skip is visible rather than
    silent. The Containerfile has never been built (no container runtime here) — that is
    stated in the file itself.
  3. just use-kyaml has not been run (it needs Julia). The conversion is one command; the
    CI gate step lands in the same commit as the conversion. Until then just check-kyaml
    fails as designed on unconverted files, and it is deliberately not in CI yet.

Testing

Gate State
scripts/check-spdx.sh OK (296 files)
scripts/check-format.sh OK (358 files)
scripts/check-blob-hygiene.sh ok (0 violations)
npx js-yaml .github/workflows/ci.yml parses; jobs repo-hygiene, test, cicd-squabbler, proofs
tree-sitter Julia parse, all changed .jl no errors
just prove-agda clean locally on Agda 2.7.0.1 (all three modules, --safe); CI lane pending the image
just test not run — no Julia in the authoring sandbox

Follow-ups (recorded, not hidden)

  • Run just use-kyaml, commit the result, add the CI gate step.
  • Extract the shell from .github/workflows/ci.yml into scripts/ci/*.sh (owner-approved
    style), then convert the workflows to KYAML.
  • Delete .github/workflows/ci-probe.yml once the actor policy is relaxed and the probe has
    been run.
  • test/reference/issue21_reference.jl — a Julia re-derivation of the fixture's numbers,
    deliberately by a different algorithm so agreement is evidence rather than a tautology.
  • Port test/unit/test_exact_summaries.jl's python3 oracle to Julia (LANGUAGE-POLICY §3).

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: c6de99d8-46fb-4eef-827d-fa446bb39631

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:

  • 🔍 Trigger review

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.

@arena-ai-coding-agent
arena-ai-coding-agent Bot force-pushed the arena/01a0db23-metamanifold-webui branch from ae8323d to 63424f0 Compare September 26, 2026 19:55
arena-ai-coding-agent Bot and others added 2 commits September 26, 2026 19:56
Pilot ruling of 2026-09-26 (owner): this repository is the pilot for migrating
the estate's YAML to KYAML, the strict YAML subset of KEP-5295. Authority is
hyperpolymath/standards 3-practice/YAML-POLICY.adoc rules Y-2 and Y-3.

- scripts/kyaml/KYAML.jl: the switch. --to-kyaml, --to-yaml, --check and
  --report; comments keep their association; canonical-form checking makes the
  gate idempotent by construction; a refusal names the file and line and writes
  nothing, so a tree is never half-converted.
- config/kyaml/drift.txt: the two workflow files Dependabot and gh actions-lock
  rewrite. Converted, not gated, accepted in writing (policy §5 step 6).
- Justfile: use-kyaml, use-yaml, check-kyaml (wired into hygiene and ci),
  kyaml-report, and prove-agda, which fails loudly when no Agda is on PATH.
- docs/pilots/kyaml-pilot.md: the operating manual — the ruling, what the switch
  guarantees, what it refuses by name, the decisions it takes and prints, the
  proof-obligation table, how to revert, and what is deliberately out of scope.
- test/unit/test_kyaml.jl: comment association, idempotence, YAML round trip,
  block scalars, the forced decisions, six refusals, a dropped-comment mutant
  that must turn the gate red, and every tracked YAML file parsed and re-emitted.
- EXPLAINME.adoc: the language ruling (Julia for everything we can; the dada2
  pipeline stays as it is; the TypeScript view is a plan, not a task) and the
  KYAML pilot pointer.
- proofs/agda/README.md: how to run the proofs, what each proves, what is
  deliberately not proved, and what would falsify them. *.agdai ignored.

Not in this commit: the conversion itself (next), the shell extraction out of
ci.yml into scripts/ci/*.sh, the CI step for check-kyaml, and the Agda CI job.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…ort (issue #21)

Zero handling, implemented rather than aliased, and proved where it can be proved.

Operators (src/analysis/zero_replacement.jl):
- multiplicative replacement (Martin-Fernandez et al. 2003), the operator of
  zCompositions::multRepl: zeros get delta x per-part detection limit, observed
  parts scale by 1 - Delta, and the sample total and the ratios among observed
  parts are preserved exactly.
- Bayesian multiplicative replacement (Martin-Fernandez et al. 2015), the GBM of
  cmultRepl: posterior mean of a Dirichlet-multinomial with the leave-one-out
  prior mean and concentration 1/gmean(t) unless alpha is supplied, with the
  reference's frac x colmins cap and its adjust switch.
- Both refuse by name what they cannot do, record per-sample diagnostics, and
  carry the provenance sentence the issue asks for: all replacement is biased.

Dispersion (src/analysis/dispersion.jl):
- pure-Julia port of glmGamPoi (Ahlmann-Eltze & Huber 2020): Cox-Reid adjusted
  NB maximum likelihood with the reference's 0.99 factor and its early returns,
  the dnorm-weighted local-median trend, the quasi-likelihood conversion, and
  the inverse-chisquare prior by Nelder-Mead.
- The reference's natural-spline abundance trend is NOT ported: true is refused,
  null is refused at or above 100 features, false runs the reference's own
  non-trended prior and records the deviation. No silent substitution.
- estimation.jl: the by-name refusal becomes the real two-pass path (mean sweep
  in R, dispersions in Julia, refit at fixed dispersion; theta = 1/alpha, with
  stats::glm(poisson()) where alpha is 0).

Configuration and surface: normalization.bayesian_multiplicative_alpha and
advanced.{zero_replacement_method, multiplicative_delta, bayesian_alpha,
glmgampoi_abundance_trend} in the Julia model, the Nickel contract, the JSON
schema and the frontend types; delta in (0,1) and alpha > 0 validated at the
door; warnings below 0.01 and at or above 0.9; a DEED echo of every value; the
DANGER banner when three or more deltas have been tried. The Advanced expander
gains the delta slider with a replacement preview, the alpha field and the trend
selector.

Proofs (proofs/agda/, Agda 2.7.0.1 + stdlib 2.1.1, --safe, no postulates):
totals and ratios preserved, imputed values positive and below their detection
limit; no data-determined rule can be faithful (the fibre behind "every
replacement is biased"); the shrinkage lies between the prior and the sample
estimate. proofs/agda/README.md states what is not proved and what would
falsify each file.

Tests and benchmarks:
- test/unit/test_zero_replacement.jl and test_dispersion.jl against
  test/fixtures/issue21/golden.json, with direct comparisons against
  zCompositions and glmGamPoi wherever R has them and an explicit "this
  comparison did not run" where it does not;
- bench/zero_replacement/benchmark.jl at 100/1000/10000 taxa with the issue's
  5-minute warning and the 10% regression report behind METAMANIFOLD_BENCH_STRICT
  (the repository's later decision made the other Julia benches informational;
  the reasoning and the switch are recorded in the file header).

KYAML pilot follow-ups in the same change: the KYAML tool now preserves comments
that sit above the document root instead of dropping them (every file here
starts with an SPDX header, so a silent drop would have deleted licence
headers); guix.scm gains the agda + agda-stdlib lane; stapeln.toml and
Containerfile define the standalone toolchain deployment (owner ruling:
standalone, not local-only); the review bench lane is added to the existing
Julia benchmark step. The three new Agda modules are flat, standalone-checked
files: folding them into the existing MetaManifold/ suite (module namespace, the
suite OPTIONS header, All.agda, a guard run) is the follow-up, and doing it
blind would have risked a passing lane.

Docs: docs/statistics/zero-handling.md,
docs/statistics/method-conditions/dispersion-glmGamPoi.md, CHANGELOG, ROADMAP.

Not in this commit: the KYAML conversion itself (one command, where Julia is),
the shell extraction from ci.yml into scripts/ci/*.sh, and the first CI run of
any of it - the sandbox has no Julia or R, so every number here is unexecuted
locally and the first CI run is the debugger.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@arena-ai-coding-agent
arena-ai-coding-agent Bot force-pushed the arena/01a0db23-metamanifold-webui branch from 63424f0 to 16e4342 Compare September 26, 2026 19:56
@arena-ai-coding-agent
arena-ai-coding-agent Bot merged commit 1f802fc into main Sep 26, 2026
6 of 7 checks passed
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.

0 participants