Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
488 changes: 468 additions & 20 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ indexmap = { version = "=2.11.4", features = ["rayon", "serde"] }
indoc = "=2.0.6"
intervallum = { version = "=1.4.4", package = "intervallum" }
itertools = "=0.14.0"
jsonschema = { version = "=0.48.1", default-features = false }
lazy_static = "=1.5.0"
log = "=0.4.28"
maplit = { version = "=1.0.2", features = [] }
Expand Down
2 changes: 1 addition & 1 deletion kb/features/ancestral.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
- [x] `--reconstruct-tip-states` (overwrite ambiguous tips, controls leaf emission)
- [x] `--model` relevant only on marginal paths (parsimony bypasses GTR)
- [ ] `--keep-overhangs` (parsed but not wired; gap handling not implemented)
- [ ] `--zero-based` indexing (parsed but not wired; [kb/issues/M-core-mutation-representation-and-format-projection-inconsistent.md](../issues/M-core-mutation-representation-and-format-projection-inconsistent.md))
- [ ] `--zero-based` indexing (parsed but not wired: [kb/issues/M-core-mutation-representation-and-format-projection-inconsistent.md](../issues/M-core-mutation-representation-and-format-projection-inconsistent.md))
- [ ] `--report-ambiguous` (parsed but not wired)
- [x] `--seed` for reproducibility
- [ ] `--gtr-params` custom GTR parameters (parsed but not wired)
Expand Down
6 changes: 3 additions & 3 deletions kb/features/io.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
- [x] CSV (clock regression, confidence intervals)
- [x] SVG/PNG charts (clock regression)
- [x] Graphviz DOT
- [/] Output topology ordering (direct formats honor the plan; TreeIR-backed formats can project the unordered graph: [kb/issues/M-io-tree-backed-output-order-inconsistent.md](../issues/M-io-tree-backed-output-order-inconsistent.md))
- [x] Output topology ordering
- [ ] VCF output (v0 writes .vcf for VCF inputs: [kb/issues/M-io-vcf-input-output-unimplemented.md](../issues/M-io-vcf-input-output-unimplemented.md))
- [/] Auspice JSON (substitutions implemented; required `meta.updated` is absent and inference metadata remains incomplete: [kb/issues/H-io-auspice-v2-required-updated-missing.md](../issues/H-io-auspice-v2-required-updated-missing.md), [kb/issues/M-timetree-tree-output-inference-metadata-incomplete.md](../issues/M-timetree-tree-output-inference-metadata-incomplete.md))
- [/] Auspice v2 JSON (schema-validated for all tree-writing commands; entropy perturbs the Shannon definition and inference metadata is incomplete: [kb/issues/M-io-auspice-entropy-perturbs-shannon-definition.md](../issues/M-io-auspice-entropy-perturbs-shannon-definition.md), [kb/issues/M-timetree-tree-output-inference-metadata-incomplete.md](../issues/M-timetree-tree-output-inference-metadata-incomplete.md))
- [ ] Skyline TSV/plot
- [ ] Substitution rates TSV
- [ ] Outliers TSV
Expand All @@ -36,7 +36,7 @@
## v1-Only Formats

- [x] PhyloXML
- [/] UShER MAT (partial - reference nucleotides can use the parent allele, and ancestral parsimony cannot supply TreeIR; [kb/issues/H-io-usher-ref-nuc-uses-parent-allele.md](../issues/H-io-usher-ref-nuc-uses-parent-allele.md), [kb/issues/N-ancestral-auspice-json-not-produced.md](../issues/N-ancestral-auspice-json-not-produced.md))
- [/] UShER MAT (output validates global reference nucleotides; input converts missing branch lengths to zero: [kb/issues/M-io-usher-missing-branch-length-becomes-zero.md](../issues/M-io-usher-missing-branch-length-becomes-zero.md))
- [x] YAML serialization
- [x] Compressed FASTA output
- [x] Streaming readers/writers with automatic decompression
4 changes: 2 additions & 2 deletions kb/features/timetree.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,12 @@

- [x] Timetree Newick
- [x] Timetree Nexus
- [/] Tree-format topology ordering ([kb/issues/M-io-tree-backed-output-order-inconsistent.md](../issues/M-io-tree-backed-output-order-inconsistent.md))
- [x] Tree-format topology ordering
- [x] Clock model JSON with `timetree.*` basename
- [x] Confidence TSV
- [ ] Node dates TSV (`write_node_dates()` is `todo!()` - [kb/issues/N-timetree-node-dates-output-unimplemented.md](../issues/N-timetree-node-dates-output-unimplemented.md))
- [ ] Substitution rates TSV (v0 writes `substitution_rates.tsv` when `--relax` is used)
- [/] Auspice JSON (v1 writes substitutions, `num_date`, `div`, and `bad_branch`; required `meta.updated` and remaining inference metadata are incomplete: [kb/issues/H-io-auspice-v2-required-updated-missing.md](../issues/H-io-auspice-v2-required-updated-missing.md), [kb/issues/M-timetree-tree-output-inference-metadata-incomplete.md](../issues/M-timetree-tree-output-inference-metadata-incomplete.md))
- [/] Auspice v2 JSON (schema-valid substitutions, dates, divergence, outlier state, sequences, and genome annotations; entropy perturbs the Shannon definition and inference metadata is incomplete: [kb/issues/M-io-auspice-entropy-perturbs-shannon-definition.md](../issues/M-io-auspice-entropy-perturbs-shannon-definition.md), [kb/issues/M-timetree-tree-output-inference-metadata-incomplete.md](../issues/M-timetree-tree-output-inference-metadata-incomplete.md))
- [ ] Outliers TSV (v0 writes `outliers.tsv`)
- [ ] Tracelog run (v0 `tracelog_run()` with detailed per-iteration state)
- [ ] Plotting (`--plot-tree`, `--plot-rtt` - parsed, return explicit error - [kb/issues/N-timetree-plot-unimplemented.md](../issues/N-timetree-plot-unimplemented.md))
Expand Down
18 changes: 0 additions & 18 deletions kb/issues/H-io-auspice-v2-required-updated-missing.md

This file was deleted.

25 changes: 0 additions & 25 deletions kb/issues/H-io-usher-ref-nuc-uses-parent-allele.md

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

Mutation coordinates, string rendering, and tree-format projection do not share one application-wide contract. The same biological mutation can change position base, textual spelling, or representable variants depending on the code path.

> [!NOTE]
> The tree-output refactor removed the `tree_ir` layer and now writes each format directly from the graph in [`packages/treetime/src/commands/shared/tree_output.rs`](../../packages/treetime/src/commands/shared/tree_output.rs). This relocated the format-projection sites but did not, by itself, establish a single shared mutation contract. Which of the sub-points below the refactor already resolved is **not yet confirmed**; re-audit the writers in `tree_output.rs` against each point.

## Problem

- Core and sparse mutation structures mix zero-based and one-based positions.
- TreeIR substitutions use a separate string parser that accepts position zero and duplicates parsing performed elsewhere. Its UShER reader casts signed protobuf positions directly to `usize`, while its writer narrows `usize` to `i32`; zero shifts reference lookup through `saturating_sub(1)` and negative or oversized positions can wrap.
- Substitution strings are assembled at multiple output sites instead of by the mutation value itself.
- Insertions and deletions reconstructed by ancestral inference do not reach every TreeIR-backed output.
- UShER conversion narrows positions through unchecked `usize`/`i32` casts and reconstructs one-based format positions ad hoc.
- Insertions and deletions reconstructed by ancestral inference may not reach every format's output.
- UShER conversion narrows positions through `usize`/`i32` casts and reconstructs one-based format positions ad hoc.

Affected boundaries include `enum Mutation` and sparse mutation types in [`packages/treetime/src/partition`](../../packages/treetime/src/partition), TreeIR mutation types in [`packages/treetime-io/src/tree_ir/types.rs`](../../packages/treetime-io/src/tree_ir/types.rs), and the Auspice, PhyloXML, and UShER adapters in [`packages/treetime-io/src/tree_ir`](../../packages/treetime-io/src/tree_ir).
Affected boundaries include `enum Mutation` and sparse mutation types in [`packages/treetime/src/partition`](../../packages/treetime/src/partition), and the Auspice, PhyloXML, and UShER writers in [`packages/treetime/src/commands/shared/tree_output.rs`](../../packages/treetime/src/commands/shared/tree_output.rs).

## Required invariant

Expand Down Expand Up @@ -45,7 +47,7 @@ Recommendation: O1 for the canonical application string, with checked format-spe
- O1. Project substitutions, insertions, and deletions only where the external format has a verified lossless representation.
- O2. Define a documented lossy projection for a specific format. This changes scientific output and requires explicit approval.

Recommendation: O1 for verified mappings. Keep format-loss policy ticketless in [M-io-usher-mat-mutation-loss-is-implicit.md](M-io-usher-mat-mutation-loss-is-implicit.md) and [N-io-phyloxml-mutation-property-contract-undecided.md](N-io-phyloxml-mutation-property-contract-undecided.md) until each mapping is approved. Silent omission is invalid.
Recommendation: O1 for verified mappings. The UShER writer now rejects unrepresentable (amino-acid, indel) mutations with an explicit error rather than dropping them silently. The PhyloXML mutation-property loss policy remains open in [N-io-phyloxml-mutation-property-contract-undecided.md](N-io-phyloxml-mutation-property-contract-undecided.md) until its mapping is approved. Silent omission is invalid.

## Recommendation

Expand All @@ -60,6 +62,4 @@ Use zero-based typed mutations throughout the application, put canonical renderi

## Related issues

- [M-io-usher-mat-mutation-loss-is-implicit.md](M-io-usher-mat-mutation-loss-is-implicit.md)
- [N-io-phyloxml-mutation-property-contract-undecided.md](N-io-phyloxml-mutation-property-contract-undecided.md)
- [N-io-tree-ir-architecture-unapproved.md](N-io-tree-ir-architecture-unapproved.md)
6 changes: 3 additions & 3 deletions kb/issues/M-io-auspice-entropy-perturbs-shannon-definition.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Auspice entropy projection perturbs the Shannon definition
# Auspice entropy output perturbs the Shannon definition

The TreeIR projection computes entropy with an added `TINY` inside every logarithm. This changes every positive term and gives a deterministic distribution such as $(1,0)$ a nonzero entropy.
Entropy is computed with an added `TINY` inside every logarithm. This changes every positive term and gives a deterministic distribution such as $(1,0)$ a nonzero entropy.

`fn compute_entropy()` applies $p\ln(p+10^{-12})$ to every state [packages/treetime/src/commands/shared/ir_projection.rs#L207-L210](../../packages/treetime/src/commands/shared/ir_projection.rs#L207-L210). The mugration node-data path duplicates the same formula [packages/treetime/src/commands/mugration/augur_node_data.rs#L134-L138](../../packages/treetime/src/commands/mugration/augur_node_data.rs#L134-L138).
`fn compute_entropy()` applies $p\ln(p+10^{-12})$ to every state [packages/treetime/src/commands/mugration/augur_node_data.rs#L135-L137](../../packages/treetime/src/commands/mugration/augur_node_data.rs#L135-L137). Both the mugration node-data JSON [packages/treetime/src/commands/mugration/augur_node_data.rs#L113](../../packages/treetime/src/commands/mugration/augur_node_data.rs#L113) and the Auspice tree-output entropy [packages/treetime/src/commands/shared/tree_output.rs#L1385](../../packages/treetime/src/commands/shared/tree_output.rs#L1385) consume this function.

For state probabilities $p_i$, Shannon entropy is

Expand Down
9 changes: 4 additions & 5 deletions kb/issues/M-io-auspice-trait-confidence-silently-coerced.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

The Auspice reader treats malformed trait objects as absent and drops individual non-numeric confidence entries. A document can therefore return success with a partial probability map or without a trait that was present in the input.

> [!NOTE]
> The tree-output refactor removed the former `tree_ir` Auspice reader this issue originally cited. The current reader lives in [`packages/treetime-io/src/auspice.rs`](../../packages/treetime-io/src/auspice.rs). Whether it rejects or still silently drops malformed trait and confidence entries is **not yet confirmed**; the required contract below stands regardless.

## Evidence

- `fn parse_trait()` [packages/treetime-io/src/tree_ir/auspice.rs#L324](../../packages/treetime-io/src/tree_ir/auspice.rs#L324) returns `Option<TreeIrTrait>`. A missing or non-string `value` returns `None`, and `filter_map()` silently removes confidence members whose values are not JSON numbers.
- `fn AuspiceReader::auspice_node_to_graph_components()` [packages/treetime-io/src/tree_ir/auspice.rs#L218](../../packages/treetime-io/src/tree_ir/auspice.rs#L218) inserts a trait only when `parse_trait()` returns `Some`, so malformed present input becomes indistinguishable from absence.
- The former reader returned `Option` from trait parsing: a missing or non-string `value` yielded `None`, and `filter_map()` silently removed confidence members whose values were not JSON numbers. A trait was inserted only when parsing returned `Some`, so malformed present input became indistinguishable from absence.

## Required contract

Expand All @@ -32,6 +34,3 @@ Reject malformed present traits. Presence is an explicit request to parse typed
- Non-object confidence and non-number entropy.
- A whole-document test proving malformed present traits return an error rather than disappearing.

## Related issues

- [N-io-tree-ir-architecture-unapproved.md](N-io-tree-ir-architecture-unapproved.md)
10 changes: 5 additions & 5 deletions kb/issues/M-io-phyloxml-booleans-silently-coerced.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# PhyloXML boolean properties are silently coerced

The PhyloXML reader parses recognized boolean properties through equality with the string `"true"`. The valid XML Schema value `"1"` becomes false, while every invalid lexical value also becomes false without an error.
The PhyloXML reader parses recognized boolean properties (`treetime:bad_branch`, `treetime:date_inferred`) through equality with the string `"true"`. The valid XML Schema value `"1"` becomes false, while every invalid lexical value also becomes false without an error.

> [!NOTE]
> The tree-output refactor removed the former `tree_ir` PhyloXML reader that assigned these booleans via `prop.value == "true"`. The current reader lives in [`packages/treetime-io/src/phyloxml.rs`](../../packages/treetime-io/src/phyloxml.rs). Whether recognized boolean properties are now parsed per the XSD lexical space (accepting `1`/`0`, rejecting other text) and whether `bad_branch`/`date_inferred` still round-trip is **not yet confirmed**; the required contract below stands regardless.

## Evidence

The property loop in `fn PhyloXmlReader::clade_to_graph_components()` [packages/treetime-io/src/tree_ir/phyloxml.rs#L165](../../packages/treetime-io/src/tree_ir/phyloxml.rs#L165) assigns both `REF_BAD_BRANCH` and `REF_DATE_INFERRED` using `prop.value == "true"`.
The former property loop assigned both `treetime:bad_branch` and `treetime:date_inferred` using `prop.value == "true"`, so `"1"` and every invalid value silently became false.

XML Schema `boolean` permits exactly `true`, `false`, `1`, and `0`; its value space contains only true and false. [XML Schema Part 2: boolean](https://www.w3.org/TR/xmlschema-2/#boolean)

Expand All @@ -30,6 +33,3 @@ Use O1: one fallible XML Schema boolean parser for both recognized boolean prope
- Representative invalid values, including case variants, surrounding whitespace, an empty value, and unrelated text.
- Whole-document tests proving legal values round-trip and invalid values return contextual errors.

## Related issues

- [N-io-tree-ir-architecture-unapproved.md](N-io-tree-ir-architecture-unapproved.md)
21 changes: 0 additions & 21 deletions kb/issues/M-io-tree-backed-output-order-inconsistent.md

This file was deleted.

Loading
Loading