Skip to content

fix(cladistics): load the DOI module and repair the CladeCumulus readers - #223

Closed
hyperpolymath wants to merge 5 commits into
mainfrom
arena/00d742e3-metamanifold-webui
Closed

hyperpolymath wants to merge 5 commits into
mainfrom
arena/00d742e3-metamanifold-webui

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

main (8b76b71) cannot load the Julia package, and the CladeCumulus suite — which had never been reached before, because the run aborted earlier — reports 3 failures and 14 errors. This PR fixes the load failure, the route registration, and every CladeCumulus defect the suite can now see.

1. The package does not load

File Defect Effect
src/core/doi.jl #210 removed module DOI and left end # module DOI lowering error ("end" at top level) at include time, so every test file fails before it starts
src/server/server.jl routes/cladistics.jl included twice every /cladistics route registered twice (silently shadows itself)

2. CladeCumulus, once the suite can run

  • routes/clade_cumulus.jl opened a DuckDB database without importing DuckDB/DBInterface. The sources endpoint answered 500, and every HTTP assertion downstream of it failed. Both modules are imported now, as the other route files already do.
  • Stale field names after the feat(cladistics): CladeCumulus phylogenetic & epistemic integration #207 rewrite. QueryCandidate has like_weight, distal_len, pendant_len; PhyloNode has edge_number. The jplace graft path and the route's diversity block still used weight, distal_length, pendant_length and .edge_num — five FieldErrors.
  • parse_newick lost NHX support. The label reader consumed [&&NHX:B=92] before the call that records it, so ) [&&NHX:B=92] :0.1 parsed with support nothing. The reader now takes the capture refs.
  • parse_jplace rejected a legitimate single-candidate placement. Placement tools report a query placed at one site as a single row whose like_weight_ratio is the share of the mass behind it; the rest is mass the tool did not place. A single candidate is now decisive at >= PLACEMENT_SINGLE_MIN_LWR (0.5); a multi-candidate placement must still partition the mass within PLACEMENT_WEIGHT_SUM_TOL, and a single candidate below half stays undecided with the same reason string.
  • The test reached the tool registry as PH.Tools, but Phylogeny imports tool_bin selectively and never binds Tools. The registry belongs to MetaManifold.Tools.

3. Guards against both merge-damage classes

  • scripts/check-julia-syntax.jl now rejects a bare end at the top level. That file parses cleanly and fails only at lowering — exactly how the missing module DOI opener passed the "Parse Julia sources" gate while breaking the whole suite.
  • test/unit/test_routes.jl asserts that no method+path pair is registered twice, and that both cladistics route files are present. A duplicate registration cannot be caught by a request test: the second registration simply shadows the first.

Validation

Frontend: npx tsc --noEmit clean, bun test src unchanged. Julia is not available in this environment (no runtime, and the pinned download host is unreachable), so the Julia evidence is static plus CI: tree-sitter parses every touched file, a block-balance pass over src/ and test/unit/ reports every file balanced, all route helper calls resolve, and no file is included or registered twice. I am following CI on this branch and will fix what it reports.

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 43 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 18c6597d-3869-40d7-bde0-67a40f5bd9e8
📥 Commits

Reviewing files that changed from the base of the PR and between 8df1041 and edfd02d.

📒 Files selected for processing: 6
  • scripts/check-julia-syntax.jl
  • src/analysis/clade_cumulus.jl
  • src/server/routes/clade_cumulus.jl
  • src/server/server.jl
  • test/unit/test_clade_cumulus.jl
  • test/unit/test_routes.jl
  • Autofix · 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.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-23T09:45:58.052162Z
We couldn’t complete this review. Comment @codex review to try again.
edfd02d New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Fork governance

Lane Status Run
DEED syntax (repo deed) 🟢 conformant run 39925928661
Hypatia verdict grid purple (job: success) same run

Hypatia grid purple

🟣 critical · commit 29c30b1f5c38 · run 39925928661

Reporter Status Critical High Medium Minor Since previous revision
Hypatia scan 🟣 critical 43 59 31 0 ↔ unchanged
panic-attack assail 🔴 high 0 6 13 0 ↔ unchanged
pons asinorum 🟡 medium 0 0 10 0 ↔ unchanged
rhodibot (RSR compliance) 🟠 indeterminate 0 0 0 0 — indeterminate
panicbot (panic recovery, error handling) 🟠 indeterminate 0 0 0 0 — indeterminate
echidnabot (formal verification: proofs/) 🟠 indeterminate 0 0 0 0 — indeterminate
seambot (integration health: API routes) 🟠 indeterminate 0 0 0 0 — indeterminate
finishingbot (release readiness) 🟠 indeterminate 0 0 0 0 — indeterminate
accessibilitybot (WCAG on the React UI) 🟠 indeterminate 0 0 0 0 — indeterminate
glambot (presentation quality) 🟠 indeterminate 0 0 0 0 — indeterminate
cipherbot ⚪ not applicable 0 0 0 0 ↔ unchanged
sustainabot ⚪ not applicable 0 0 0 0 ↔ unchanged
Hypatia scan: 133 finding(s)
  • critical cicd_rules/banned_language_file — frontend/src/views/run/parseFilterYaml.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/encode.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/charts.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/export.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/figure.test.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/legend.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/figure/types.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/utils/download.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/utils/text.test.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/utils/timeago.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/utils/text.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useUnsavedGuard.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useApi.test.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useApi.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useAnalysis.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useSSE.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useTabParam.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useNavRefresh.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/hooks/useJobEvents.ts — TypeScript file detected -- banned language
  • critical cicd_rules/banned_language_file — frontend/src/about.ts — TypeScript file detected -- banned language
  • 113 more; see the structured report in the artifact.
panic-attack assail: 19 finding(s)
  • high DynamicCodeExecution — src/pipeline/dada2/context.jl — eval/Meta.parse in src/pipeline/dada2/context.jl
  • high DynamicCodeExecution — src/analysis/analysis.jl — eval/Meta.parse in src/analysis/analysis.jl
  • high DynamicCodeExecution — src/analysis/differential.jl — eval/Meta.parse in src/analysis/differential.jl
  • high DynamicCodeExecution — src/core/provenance.jl — eval/Meta.parse in src/core/provenance.jl
  • high DynamicCodeExecution — scripts/check-julia-syntax.jl — eval/Meta.parse in scripts/check-julia-syntax.jl
  • high DynamicCodeExecution — test/unit/test_permanova.jl — eval/Meta.parse in test/unit/test_permanova.jl
  • medium UnsafeFFI — src/core/memory_probe.jl — 3 ccall/FFI calls in src/core/memory_probe.jl
  • medium InputBoundary — src/server/routes/runs.jl — 2 JSON3.read/JSON.parse call(s) with 0 try block(s) in src/server/routes/runs.jl — these throw on malformed input; wrap in try/catch
  • medium InputBoundary — src/server/routes/composition.jl — 6 JSON3.read/JSON.parse call(s) with 2 try block(s) in src/server/routes/composition.jl — these throw on malformed input; wrap in try/catch
  • medium InputBoundary — src/server/routes/studies.jl — 4 JSON3.read/JSON.parse call(s) with 2 try block(s) in src/server/routes/studies.jl — these throw on malformed input; wrap in try/catch
  • medium InputBoundary — src/server/routes/analysis.jl — 9 JSON3.read/JSON.parse call(s) with 4 try block(s) in src/server/routes/analysis.jl — these throw on malformed input; wrap in try/catch
  • medium UnsafeFFI — install.jl — 1 ccall/FFI calls in install.jl
  • medium ProofDrift — test/unit/test_occupancy_grade.jl — 2 `@test x isa Y` assertion(s) with no value check — type-only tests may substitute for an unwritten formal theorem in test/unit/test_occupancy_grade.jl
  • medium ProofDrift — test/unit/test_evidence.jl — 1 `@test x isa Y` assertion(s) with no value check — type-only tests may substitute for an unwritten formal theorem in test/unit/test_evidence.jl
  • medium InputBoundary — bench/advanced_zero_handling/benchmark.jl — 1 JSON3.read/JSON.parse call(s) with 0 try block(s) in bench/advanced_zero_handling/benchmark.jl — these throw on malformed input; wrap in try/catch
  • medium InputBoundary — frontend/src/figure/charts.ts — 1 JSON.parse call(s) with 0 try block(s) in frontend/src/figure/charts.ts — JSON.parse throws SyntaxError on malformed input; wrap in try-catch
  • medium InputBoundary — frontend/src/tree/model.ts — 1 JSON.parse call(s) with 0 try block(s) in frontend/src/tree/model.ts — JSON.parse throws SyntaxError on malformed input; wrap in try-catch
  • medium InputBoundary — frontend/src/api/events.ts — 2 JSON.parse call(s) with 0 try block(s) in frontend/src/api/events.ts — JSON.parse throws SyntaxError on malformed input; wrap in try-catch
  • medium InputBoundary — frontend/src/components/alphaMetrics.tsx — 1 JSON.parse call(s) with 0 try block(s) in frontend/src/components/alphaMetrics.tsx — JSON.parse throws SyntaxError on malformed input; wrap in try-catch
pons asinorum: 10 finding(s)
  • medium string-concat-in-loop — ./frontend/src/tree/model.ts:122 — string built by repeated concatenation in a loop (T0, HEURISTIC)
  • medium string-concat-in-loop — ./frontend/src/tree/model.ts:118 — string built by repeated concatenation in a loop (T0, HEURISTIC)
  • medium string-concat-in-loop — ./frontend/src/tree/TreeShapes.tsx:69 — string built by repeated concatenation in a loop (T0, HEURISTIC)
  • medium string-concat-in-loop — ./frontend/src/tree/TreeShapes.tsx:66 — string built by repeated concatenation in a loop (T0, HEURISTIC)
  • medium string-concat-in-loop — ./frontend/src/tree/TreeShapes.tsx:61 — string built by repeated concatenation in a loop (T0, HEURISTIC)
  • medium string-concat-in-loop — ./frontend/src/tree/TreeShapes.tsx:53 — string built by repeated concatenation in a loop (T0, HEURISTIC)
  • medium string-concat-in-loop — ./frontend/src/tree/TreeShapes.tsx:43 — string built by repeated concatenation in a loop (T0, HEURISTIC)
  • medium string-concat-in-loop — ./frontend/src/tree/TreeShapes.tsx:42 — string built by repeated concatenation in a loop (T0, HEURISTIC)
  • medium unreachable-after-jump — ./frontend/src/figure/PaneEditor.tsx:45 — statement is unreachable after an unconditional jump (T0, HEURISTIC)
  • medium unreachable-after-jump — ./frontend/src/components/PublicationTablesPanel.tsx:208 — statement is unreachable after an unconditional jump (T0, HEURISTIC)
rhodibot (RSR compliance): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
panicbot (panic recovery, error handling): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
echidnabot (formal verification: proofs/): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
seambot (integration health: API routes): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
finishingbot (release readiness): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
accessibilitybot (WCAG on the React UI): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
glambot (presentation quality): not_run — enrolled, but no report-back was received
  • 🟠 indeterminate: enrolled, but no report-back was received
cipherbot: not_applicable — no cryptography is implemented in this repository
  • ⚪ not applicable: no cryptography is implemented in this repository
sustainabot: not_applicable — fleet adapter slot reserved; no adapter exists yet (gitbot-fleet README)
  • ⚪ not applicable: fleet adapter slot reserved; no adapter exists yet (gitbot-fleet README)

Scope: static findings reported by each row's tool at the named commit. Purple, red, yellow and blue grade the worst finding present; orange is evidence missing, malformed or a scanner that did not run; grey is an explicit scope exclusion with its reason. No row is a security certification. report.json, badge.json and the raw findings are in the verdict-grid artifact on the linked run.

@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 23, 2026 07:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6f7d5f5f37

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

for (ci, cand) in enumerate(q.candidates)
tid = multi ? string(qname, "@edge", cand.edge_num, "#", ci) : qname
tip_weights[tid] = cand.weight / tw
tip_weights[tid] = cand.like_weight / tw

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve unplaced LWR mass in diversity weights

When the newly accepted single-candidate placement has an LWR between 0.5 and 1.0, tw equals that candidate's weight, so this division always produces 1.0. The /clade-cumulus diversity block therefore assigns all of the query's abundance to the reported edge even though the parser explicitly treats the remaining probability mass as unplaced, inflating that tip's contribution to weighted UniFrac and related abundance-based results. Preserve the raw LWR for this one-candidate case, with the remainder accounted for as unplaced, rather than renormalizing it away.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

The conflicts here are with #222, which landed on main while this was open and repaired an overlapping set of CladeCumulus defects by a different route. I have resolved them, addressed the Codex P1 finding, and opened the result as #230.

The conflict git could not see. Two hunks conflicted textually and were trivial (the read_label_and_quoted signature, and the PH.Tools → MetaManifold.Tools testset fix, which both sides made identically). The one that matters merged cleanly and silently produced a rule neither side intended:

  • Fix CladeCumulus testset: field names, NHX capture, LWR tolerance, route loading #222 widened PLACEMENT_WEIGHT_SUM_TOL from 1e-5 to 0.05 so a lone 0.98 placement would be accepted.
  • This PR left it at 1e-5 and added PLACEMENT_SINGLE_MIN_LWR instead.
  • Git kept both. The result applies the 0.05 slack only to multi-candidate partitions — precisely where it is least wanted, since a truncated 0.96 partition would then pass as complete evidence.

#230 resolves to this PR's two-rule model: a multi-candidate record partitions the mass and must sum to one within 1e-5; a single-candidate record is judged on its own share against PLACEMENT_SINGLE_MIN_LWR. A lone 0.98 still passes, and a truncated partition is caught again.

Codex P1, preserve unplaced LWR mass. The finding is right, and it is a defect this PR introduced: before it, a single candidate had to carry nearly all the mass, so cand.like_weight / tw == 1.0 was harmless. Admitting a 0.5 placement turned that division into a silent upgrade from coin flip to certainty. In #230 the diversity block weights tips by the raw like-weight ratio, and the shortfall is reported per sample as a new unplaced_reads field rather than renormalised onto the reported edge. _graft_jplace_queries is deliberately left alone — the clade tree is a count view of the table and still conserves every read; only the abundance-weighted matrix discounts unplaced mass.

Everything else from this PR carries over unchanged: the module DOI opener, the duplicate routes/cladistics.jl include, the edge_number/like_weight field names, the stray-top-level-end gate, and the duplicate-route-registration test (rewritten so a failure names the offending route instead of printing false).

Closing in favour of #230 once CI there is green — the review history is worth keeping here.

hyperpolymath added a commit that referenced this pull request Oct 23, 2026
CI on `main` (8df1041) shows `POST /clade-cumulus` answering 500 for
every `study_tree` request:

    MethodError: no method matching _valid_tree_file(::SubString{String})

`JSON3` hands request fields back as `SubString`s and `strip` keeps them
that way, but `_valid_tree_file` and `_tree_format` in `routes/trees.jl`
are `String`-typed. The handler has no catch around
`_resolve_tree_inputs_from_request`, so the MethodError surfaced as a
500 and took seven assertions down with it: `r_comb.status == 200`
failed, and every `comb.*` access after it raised `KeyError` until the
testset aborted.

#222 fixed this class at `_load_run_table_df` -- "JSON3 hands request
fields back as SubStrings; the DuckDB helpers are String-typed, so
normalise once at this boundary" -- but `_resolve_tree_inputs_from_request`
two functions below kept the unnormalised values. `cladistics.jl`
already wraps its own call as `_valid_tree_file(String(published))`, so
the convention is to normalise at the call site; this follows it.

The existing `r_comb` assertion is the regression test: it sends
`"treeFile" => "amplicon.nwk"` over JSON, which is exactly the SubString
path that broke.

With the `u.edge_num` -> `u.edge_number` repair already carried in from
#223, this accounts for 8 of the 9 errors that run reported.
Arena Agent and others added 2 commits October 23, 2026 08:01
Builds on #222, which fixed the graft query fields but left three sites:

- `_graft_jplace_queries` still constructed `PhyloNode(..., u.edge_num, ...)`
  and read `u.edge_num` when matching placements to edges. The field is
  `edge_number`, so any graft threw `FieldError` before the tree was rebuilt
  ("Got exception outside of a @test" — no test line, which is why it read
  as an unrelated suite failure).
- The diversity block in the route still summed `c.weight` over jplace
  candidates. `QueryCandidate` carries `like_weight`; reading `.weight` threw
  inside the handler, and with `show_errors=false` the POST answered a bare
  500, so every assertion on the combined-mode payload failed with
  `KeyError: key :root not found`.
- `routes/cladistics.jl` was included twice in server.jl, registering every
  /cladistics route twice.

`cand.edge_num` stays: that is the `QueryCandidate` field. The undirected
edge struct's `edge_no` and its `weight` are separate types.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…y `end`

Both merge-damage classes that broke this branch were invisible to the tests
that existed:

- A duplicated `include` in server.jl registers every route in that file
  twice. A request test cannot see it: the second registration shadows the
  first and both answer. `test_routes.jl` now reads server.jl and asserts that
  each include path appears once and that both cladistics route files are
  present, then asserts that no route file declares the same method+path twice.
- A dropped `module` opener leaves a bare `end`, which parses cleanly and only
  fails at lowering — so the "Parse Julia sources" gate passed while the whole
  suite died at include time. `scripts/check-julia-syntax.jl` now rejects a
  top-level `end` with the code unit it was found at.

Also names `DuckDB` and `DBInterface` in routes/clade_cumulus.jl rather than
inheriting them from results.jl, which happens to be included earlier.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@hyperpolymath
hyperpolymath force-pushed the arena/00d742e3-metamanifold-webui branch from fc00d81 to 1a6a25a Compare October 23, 2026 08:02

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a6a25a1eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread test/unit/test_routes.jl
included = String[]
for m in eachmatch(r"include\(joinpath\(@__DIR__((?:,\s*\"[^\"]+\")+)\)\)",
server_src)
push!(included, join([c[2:end-1] for c in

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Slice the regex match text rather than RegexMatch

When this test processes any matching include, eachmatch yields a RegexMatch, not a string, so c[2:end-1] attempts unsupported range indexing on the match object and raises before any registration assertions run. Extract and slice c.match (or strip the quotes from it) instead so the unit suite can complete.

Useful? React with 👍 / 👎.

Arena Agent and others added 2 commits October 23, 2026 08:17
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…nst SV (temporary)

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

hyperpolymath added a commit that referenced this pull request Oct 23, 2026
Main landed #226 while this branch was in review, and the two found three
of the same defects independently. Main's resolution is taken for all
three, since it is already on main:

- `erfc`: main's private `_erfc` replaces the `compositional_erfc` added
  here. Same algorithm (incomplete gamma at a = 1/2, series below
  x^2 = 1.5 and a Lentz continued fraction above), so only the name and
  the tests differ; `compositional.jl` and `test_differential.jl` are
  taken wholesale from main.
- `subtree_pd` in `_reaggregate_after_move`: identical fix, main's
  `own_pd` naming and one-line post-loop form kept. Git had merged the
  two variants additively, which would have counted every active
  internal branch twice; that is resolved to a single addition.
- The `Main.SV` collision that was aborting the include loop: main
  renames this file's binding to `CLADE_SV` instead of dropping `const`.
  Main's rename is kept.
- `min_prevalence` in the multinomial engine test: main's eight-sample
  table is better than the four-sample one here, and is kept.

Kept from this branch, because main does not have them:

- The raw like-weight ratio in the diversity block. Main's change to
  that line only renames `c.weight` to `c.like_weight` and keeps
  `cand.like_weight / tw`, which is the renormalisation Codex objected
  to on #223: it hands a lone 0.6 placement a weight of 1.0. The
  divisor is removed, and the mass the tool never placed is reported as
  `unplaced_reads`.
- `_sample_total` and the `total_a`/`total_b`/`totals` arguments on
  `weighted_unifrac`, `branch_unifrac_contributions` and
  `unifrac_matrix`, with the route passing each sample's library size.
  Without them the metric divides by the placed-only mass and undoes
  the line above.
- Per-file testsets in `runtests.jl`. Main fixed the `SV` collision but
  not the reason one bad binding could silently skip thirty-five unit
  files and the occupancy probe.
- `_cc_find`, and the drag-and-drop assertions that pin the exact
  post-move PD values and total-PD conservation rather than comparing a
  positional index against an inequality.
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@sonarqubecloud

Copy link
Copy Markdown

Copy link
Copy Markdown
Owner Author

Superseded by #225 (d337f74), which landed the same repairs on main independently and additionally fixed the compositional Wald tail, the validated-statistics byte-body path and the remaining CladeCumulus items.

What main now has, and this branch no longer needs to add:

Defect this branch targeted Where it is fixed on main
src/core/doi.jl missing module DOI opener restored upstream (the file loads again)
routes/cladistics.jl included twice in server.jl single include, plus a route-uniqueness assertion
PhyloNode.edge_num read in _graft_jplace_queries edge_number (this was the FieldError that aborted the CladeCumulus testset with no test line)
jplace acceptance rule single candidate at PLACEMENT_SINGLE_MIN_LWR = 0.5, multi-candidate still at PLACEMENT_WEIGHT_SUM_TOL
NHX [&&NHX:B=…] support after ) capture refs threaded through read_label_and_quoted
const SV in test_clade_cumulus.jl clashing with other files renamed _CLADE_SV
stray top-level end passing the parse gate rejected in scripts/check-julia-syntax.jl

CI on main at d337f74 is green in full (run 39935043266: Julia tests, Occupancy disagreement test, Occupancy typed peak, Code/Occupancy relevance, Agda proofs). The branch is reset to main, so nothing here is worth rebasing.

One thing this branch found that the fix on main covers by construction: the /clade-cumulus POST answered a bare 500 because the diversity block still read .weight off QueryCandidate; main weights tips by like_weight and reports unplaced_reads.

auto-merge was automatically disabled October 23, 2026 10:31

Pull request was closed

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