Severity: P1 · Area: 10 (HSJ/XFORM kernels)
Location: R/recode_hierarchy.R:106-109 (secNStates[s] == 0), :193-197 (-2 encoding); src/ts_rcpp.cpp:1936; abort at R/MaximizeParsimony.R:1717
secNStates[s] == 0 makes nPresent = prod(...) zero and nStates 1; every present-primary tip then encodes as the -2 sentinel, and src/ts_rcpp.cpp:1936 loops for (s = 1; s < ns) with ns == 1, admitting no state -- so all tip costs are INF and sankoff_score returns Inf. Verified REAL, and the reachability route (the load-bearing part) holds (opus verifier, build at bbab0f7c): a full 5-taxon dataset validates cleanly (n_states = 3), and then TreeLength(<4-tip tree>, ds, hierarchy = h, inapplicable = "xform") returns Inf silently, with no warning, while inapplicable = "hsj" returns a finite 4.5. ValidateHierarchy runs before both subsetting sites (R/MaximizeParsimony.R:1361 vs the taxon-drop at :1428; R/tree_length.R:276 vs the dataset[TipLabels(tree)] subset at :302), so it cannot see the degenerate block. .Recompress = MatrixToPhyDat(PhyDatToMatrix()) preserves the column count, so it is the taxon subset alone that does it -- i.e. valid user input reaching a degenerate state through a documented code path, not hand-crafted malformed input. Consequence corrected during verification, and the correction matters: MaximizeParsimony does not silently return the start tree with score = Inf as first claimed -- it aborts at R/MaximizeParsimony.R:1717 with Error in if (diff(range(canonicalScores)) > sqrt(.Machine$double.eps))): missing value where TRUE/FALSE needed, because diff(range(c(Inf, Inf))) is NaN. A louder symptom than claimed, but a worse one for the user, and it points at a second defect worth fixing in the same patch: :1717 will NaN for any all-Inf pool, whatever produced it. Cross-ref T-393 (shared root line) and T-379 (the other -2-sentinel defect, which under-counts by discarding known secondaries -- distinct failure, same sentinel).
Migrated 2026-08-04 from dev/red-team/findings.md; pre-tracker ID T-394. References to T-394 in source comments, dev/red-team/log.md, commit messages and PR bodies mean this issue — see dev/red-team/migration-map.tsv. Cross-repo references use the fully-qualified form agent-issues/TreeSearch#<n>; a bare #n means this repo.
Severity: P1 · Area: 10 (HSJ/XFORM kernels)
Location:
R/recode_hierarchy.R:106-109(secNStates[s] == 0),:193-197(-2encoding);src/ts_rcpp.cpp:1936; abort atR/MaximizeParsimony.R:1717secNStates[s] == 0makesnPresent = prod(...)zero andnStates1; every present-primary tip then encodes as the-2sentinel, andsrc/ts_rcpp.cpp:1936loopsfor (s = 1; s < ns)withns == 1, admitting no state -- so all tip costs areINFandsankoff_scorereturnsInf. Verified REAL, and the reachability route (the load-bearing part) holds (opus verifier, build atbbab0f7c): a full 5-taxon dataset validates cleanly (n_states = 3), and thenTreeLength(<4-tip tree>, ds, hierarchy = h, inapplicable = "xform")returnsInfsilently, with no warning, whileinapplicable = "hsj"returns a finite 4.5.ValidateHierarchyruns before both subsetting sites (R/MaximizeParsimony.R:1361vs the taxon-drop at:1428;R/tree_length.R:276vs thedataset[TipLabels(tree)]subset at:302), so it cannot see the degenerate block..Recompress=MatrixToPhyDat(PhyDatToMatrix())preserves the column count, so it is the taxon subset alone that does it -- i.e. valid user input reaching a degenerate state through a documented code path, not hand-crafted malformed input. Consequence corrected during verification, and the correction matters:MaximizeParsimonydoes not silently return the start tree withscore = Infas first claimed -- it aborts atR/MaximizeParsimony.R:1717withError in if (diff(range(canonicalScores)) > sqrt(.Machine$double.eps))): missing value where TRUE/FALSE needed, becausediff(range(c(Inf, Inf)))isNaN. A louder symptom than claimed, but a worse one for the user, and it points at a second defect worth fixing in the same patch::1717willNaNfor any all-Infpool, whatever produced it. Cross-ref T-393 (shared root line) and T-379 (the other-2-sentinel defect, which under-counts by discarding known secondaries -- distinct failure, same sentinel).Migrated 2026-08-04 from
dev/red-team/findings.md; pre-tracker ID T-394. References toT-394in source comments,dev/red-team/log.md, commit messages and PR bodies mean this issue — seedev/red-team/migration-map.tsv. Cross-repo references use the fully-qualified formagent-issues/TreeSearch#<n>; a bare#nmeans this repo.