The project has a full release pipeline — release.toml, cliff.toml, a maintained CHANGELOG.md, and three tagged releases (0.1.0 → 0.1.2) — but Cargo.toml is missing the metadata cargo publish requires.
description — cargo publish rejects the crate without it
license or license-file — likewise rejected; also, there is no LICENSE file in the repo at all, so the code currently carries no stated terms
repository, documentation, homepage — no links from crates.io/docs.rs back to the source
keywords, categories — undiscoverable in search
readme — README.md exists but isn't wired up
authors
rust-version — no declared MSRV, so there's nothing for CI to test against (#24) and no contract with consumers. edition = "2024" already implies Rust 1.85+, but that should be explicit
exclude — docs/, benches/baseline.txt, and temp/ would otherwise ship in the published tarball
No crate-level documentation
src/lib.rs opens directly with use std::{…} — there is no //! module doc. On docs.rs the landing page would be a bare symbol list with no explanation of what the crate is, what TrueSkill Through Time does, or how to start.
Every other module in the crate has a //! header, which makes the omission at the root conspicuous.
Also missing across the public API (from cargo clippy -- -W clippy::pedantic):
9 Result-returning public functions with no # Errors section
4 potentially-panicking public functions with no # Panics section — including predict_outcome and Outcome::winner, both of which do panic (#21, #20)
31 missing #[must_use] on pure accessors — notably Gaussian's arithmetic and posteriors()/log_evidence(), where discarding the result is always a bug
18 doc items missing backticks
None of these have doc examples either, so cargo test --doc currently verifies nothing.
Also
[profile.release] debug = true and the matching [profile.dev]/[profile.bench] entries: profile settings in a library are ignored by downstream consumers, so these only affect local builds. Harmless, but debug = true on release is worth a comment explaining it's there for cargo flamegraph (per the flame recipe in the Justfile) rather than looking like an oversight.
Acceptance
cargo publish --dry-run succeeds.
A LICENSE file exists and matches the license key.
src/lib.rs has a //! header with a runnable example.
rust-version is declared and verified by CI (#24).
Public Result/panicking functions document # Errors / # Panics.
The project has a full release pipeline — `release.toml`, `cliff.toml`, a maintained `CHANGELOG.md`, and three tagged releases (0.1.0 → 0.1.2) — but `Cargo.toml` is missing the metadata `cargo publish` requires.
## Missing manifest keys
```toml
[package]
name = "trueskill-tt"
version = "0.1.2"
edition = "2024"
```
That is the entire `[package]` section. Absent:
- **`description`** — `cargo publish` rejects the crate without it
- **`license`** or `license-file` — likewise rejected; also, there is no `LICENSE` file in the repo at all, so the code currently carries no stated terms
- `repository`, `documentation`, `homepage` — no links from crates.io/docs.rs back to the source
- `keywords`, `categories` — undiscoverable in search
- `readme` — `README.md` exists but isn't wired up
- `authors`
- **`rust-version`** — no declared MSRV, so there's nothing for CI to test against (#24) and no contract with consumers. `edition = "2024"` already implies Rust 1.85+, but that should be explicit
- `exclude` — `docs/`, `benches/baseline.txt`, and `temp/` would otherwise ship in the published tarball
## No crate-level documentation
`src/lib.rs` opens directly with `use std::{…}` — there is no `//!` module doc. On docs.rs the landing page would be a bare symbol list with no explanation of what the crate is, what TrueSkill Through Time does, or how to start.
Every other module in the crate has a `//!` header, which makes the omission at the root conspicuous.
Also missing across the public API (from `cargo clippy -- -W clippy::pedantic`):
- 9 `Result`-returning public functions with no `# Errors` section
- 4 potentially-panicking public functions with no `# Panics` section — including `predict_outcome` and `Outcome::winner`, both of which do panic (#21, #20)
- 31 missing `#[must_use]` on pure accessors — notably `Gaussian`'s arithmetic and `posteriors()`/`log_evidence()`, where discarding the result is always a bug
- 18 doc items missing backticks
None of these have doc examples either, so `cargo test --doc` currently verifies nothing.
## Also
`[profile.release] debug = true` and the matching `[profile.dev]`/`[profile.bench]` entries: profile settings in a library are ignored by downstream consumers, so these only affect local builds. Harmless, but `debug = true` on release is worth a comment explaining it's there for `cargo flamegraph` (per the `flame` recipe in the `Justfile`) rather than looking like an oversight.
## Acceptance
- `cargo publish --dry-run` succeeds.
- A `LICENSE` file exists and matches the `license` key.
- `src/lib.rs` has a `//!` header with a runnable example.
- `rust-version` is declared and verified by CI (#24).
- Public `Result`/panicking functions document `# Errors` / `# Panics`.
Partly done in 9506fed — staying open for the licence, which is yours to choose.
Added: description, repository, readme, keywords, categories, exclude, and rust-version = "1.85" (the edition-2024 floor, now verified by a CI job in #24).
src/lib.rs gained the missing //! header: what Through Time does differently from plain TrueSkill, three runnable examples, and the draw/p_draw interaction. cargo test --doc runs 3 tests where it previously had nothing to check.
cargo publish --dry-run now packages and verifies cleanly, stopping only on:
warning: manifest has no license or license-file
Remaining, and blocking publication:
Pick a licence. The Rust convention is license = "MIT OR Apache-2.0" with matching LICENSE-MIT / LICENSE-APACHE files. There is no LICENSE file in the repo at all today, so the source currently carries no stated terms. A TODO comment marks the spot in Cargo.toml.
# Errors / # Panics sections and #[must_use] across the public API are still missing — worth doing once the API changes in #20 and #21 settle, since both move which functions panic and which return Result.
Partly done in 9506fed — **staying open for the licence, which is yours to choose.**
Added: `description`, `repository`, `readme`, `keywords`, `categories`, `exclude`, and `rust-version = "1.85"` (the edition-2024 floor, now verified by a CI job in #24).
`src/lib.rs` gained the missing `//!` header: what Through Time does differently from plain TrueSkill, three runnable examples, and the draw/`p_draw` interaction. `cargo test --doc` runs 3 tests where it previously had nothing to check.
`cargo publish --dry-run` now packages and verifies cleanly, stopping only on:
```
warning: manifest has no license or license-file
```
**Remaining, and blocking publication:**
- Pick a licence. The Rust convention is `license = "MIT OR Apache-2.0"` with matching `LICENSE-MIT` / `LICENSE-APACHE` files. There is no `LICENSE` file in the repo at all today, so the source currently carries no stated terms. A TODO comment marks the spot in `Cargo.toml`.
- `# Errors` / `# Panics` sections and `#[must_use]` across the public API are still missing — worth doing once the API changes in #20 and #21 settle, since both move which functions panic and which return `Result`.
Public Result/panicking functions document # Errors / # Panics
✅9b2c2b3
The manifest keys all landed in 9506fed; the licence in b73cf01; the docs in 9b2c2b3. Clippy went from 56 warnings to zero across missing_errors_doc, missing_panics_doc, must_use_candidate and doc_markdown.
On the 13 hand-written sections: they name the actual variants rather than gesturing at "an error", which meant reading each error path. Game::ranked alone returns four distinct variants. record_draw can hit TieWithoutDrawProbability where record_winner provably cannot, since a two-team decisive outcome has nothing to tie. Documenting those as interchangeable would have been worse than leaving them undocumented, because a reader would trust it.
Two panics were already described in prose but not under a # Panics heading, so neither rustdoc nor clippy surfaced them — Outcome::winner and EventBuilder::weights. Both now carry it, and Outcome::winner gained a note that it ties every loser, so n >= 3 needs a positive p_draw. That is the easiest error in this crate to hit by accident.
Two notes for the record:
The licence turned out to be a hard blocker for the release workflow, not just crates.io. cargo publish does not check license for an alternative registry — verified by a clean dry run with none — but cargo release refuses outright with missing the following fields: license || license-file, and --no-verify does not bypass it.
The published tarball was going to be 48.1 MiB. All of it examples/atp.csv. It is read by relative path rather than include_str!, so excluding it still compiles and cargo package --verify still builds every target. Published size is 374 KiB / 88 KiB compressed. Your exclude list predated that fixture; nothing warns you, the only signal is the Packaged N files line.
The # Errors/# Panics deferral note above mentioned waiting on #20/#21 — that turned out unnecessary: predict_outcome and Outcome::winner are documented as panicking today, which is accurate regardless of whether those issues later convert them to Result.
All five acceptance criteria met. **trueskill-tt 0.2.0 is published** to the kellnr registry.
| Criterion | Status |
|---|---|
| `cargo publish --dry-run` succeeds | ✅ — went further and actually published |
| LICENSE file exists and matches the `license` key | ✅ `MIT OR Apache-2.0` + LICENSE-MIT + LICENSE-APACHE |
| `src/lib.rs` has a `//!` header with a runnable example | ✅ 3 doctests, checked by `cargo test --doc` |
| `rust-version` declared and verified by CI | ✅ `1.85`, per #24 |
| Public `Result`/panicking functions document `# Errors` / `# Panics` | ✅ `9b2c2b3` |
The manifest keys all landed in `9506fed`; the licence in `b73cf01`; the docs in `9b2c2b3`. Clippy went from 56 warnings to zero across `missing_errors_doc`, `missing_panics_doc`, `must_use_candidate` and `doc_markdown`.
**On the 13 hand-written sections:** they name the actual variants rather than gesturing at "an error", which meant reading each error path. `Game::ranked` alone returns four distinct variants. `record_draw` can hit `TieWithoutDrawProbability` where `record_winner` provably cannot, since a two-team decisive outcome has nothing to tie. Documenting those as interchangeable would have been worse than leaving them undocumented, because a reader would trust it.
**Two panics were already described in prose but not under a `# Panics` heading**, so neither rustdoc nor clippy surfaced them — `Outcome::winner` and `EventBuilder::weights`. Both now carry it, and `Outcome::winner` gained a note that it ties every loser, so `n >= 3` needs a positive `p_draw`. That is the easiest error in this crate to hit by accident.
Two notes for the record:
- **The licence turned out to be a hard blocker for the release workflow**, not just crates.io. `cargo publish` does not check `license` for an alternative registry — verified by a clean dry run with none — but `cargo release` refuses outright with `missing the following fields: license || license-file`, and `--no-verify` does not bypass it.
- **The published tarball was going to be 48.1 MiB.** All of it `examples/atp.csv`. It is read by relative path rather than `include_str!`, so excluding it still compiles and `cargo package --verify` still builds every target. Published size is 374 KiB / 88 KiB compressed. Your `exclude` list predated that fixture; nothing warns you, the only signal is the `Packaged N files` line.
The `# Errors`/`# Panics` deferral note above mentioned waiting on #20/#21 — that turned out unnecessary: `predict_outcome` and `Outcome::winner` are documented as panicking *today*, which is accurate regardless of whether those issues later convert them to `Result`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The project has a full release pipeline —
release.toml,cliff.toml, a maintainedCHANGELOG.md, and three tagged releases (0.1.0 → 0.1.2) — butCargo.tomlis missing the metadatacargo publishrequires.Missing manifest keys
That is the entire
[package]section. Absent:description—cargo publishrejects the crate without itlicenseorlicense-file— likewise rejected; also, there is noLICENSEfile in the repo at all, so the code currently carries no stated termsrepository,documentation,homepage— no links from crates.io/docs.rs back to the sourcekeywords,categories— undiscoverable in searchreadme—README.mdexists but isn't wired upauthorsrust-version— no declared MSRV, so there's nothing for CI to test against (#24) and no contract with consumers.edition = "2024"already implies Rust 1.85+, but that should be explicitexclude—docs/,benches/baseline.txt, andtemp/would otherwise ship in the published tarballNo crate-level documentation
src/lib.rsopens directly withuse std::{…}— there is no//!module doc. On docs.rs the landing page would be a bare symbol list with no explanation of what the crate is, what TrueSkill Through Time does, or how to start.Every other module in the crate has a
//!header, which makes the omission at the root conspicuous.Also missing across the public API (from
cargo clippy -- -W clippy::pedantic):Result-returning public functions with no# Errorssection# Panicssection — includingpredict_outcomeandOutcome::winner, both of which do panic (#21, #20)#[must_use]on pure accessors — notablyGaussian's arithmetic andposteriors()/log_evidence(), where discarding the result is always a bugNone of these have doc examples either, so
cargo test --doccurrently verifies nothing.Also
[profile.release] debug = trueand the matching[profile.dev]/[profile.bench]entries: profile settings in a library are ignored by downstream consumers, so these only affect local builds. Harmless, butdebug = trueon release is worth a comment explaining it's there forcargo flamegraph(per theflamerecipe in theJustfile) rather than looking like an oversight.Acceptance
cargo publish --dry-runsucceeds.LICENSEfile exists and matches thelicensekey.src/lib.rshas a//!header with a runnable example.rust-versionis declared and verified by CI (#24).Result/panicking functions document# Errors/# Panics.Partly done in
9506fed— staying open for the licence, which is yours to choose.Added:
description,repository,readme,keywords,categories,exclude, andrust-version = "1.85"(the edition-2024 floor, now verified by a CI job in #24).src/lib.rsgained the missing//!header: what Through Time does differently from plain TrueSkill, three runnable examples, and the draw/p_drawinteraction.cargo test --docruns 3 tests where it previously had nothing to check.cargo publish --dry-runnow packages and verifies cleanly, stopping only on:Remaining, and blocking publication:
license = "MIT OR Apache-2.0"with matchingLICENSE-MIT/LICENSE-APACHEfiles. There is noLICENSEfile in the repo at all today, so the source currently carries no stated terms. A TODO comment marks the spot inCargo.toml.# Errors/# Panicssections and#[must_use]across the public API are still missing — worth doing once the API changes in #20 and #21 settle, since both move which functions panic and which returnResult.All five acceptance criteria met. trueskill-tt 0.2.0 is published to the kellnr registry.
cargo publish --dry-runsucceedslicensekeyMIT OR Apache-2.0+ LICENSE-MIT + LICENSE-APACHEsrc/lib.rshas a//!header with a runnable examplecargo test --docrust-versiondeclared and verified by CI1.85, per #24Result/panicking functions document# Errors/# Panics9b2c2b3The manifest keys all landed in
9506fed; the licence inb73cf01; the docs in9b2c2b3. Clippy went from 56 warnings to zero acrossmissing_errors_doc,missing_panics_doc,must_use_candidateanddoc_markdown.On the 13 hand-written sections: they name the actual variants rather than gesturing at "an error", which meant reading each error path.
Game::rankedalone returns four distinct variants.record_drawcan hitTieWithoutDrawProbabilitywhererecord_winnerprovably cannot, since a two-team decisive outcome has nothing to tie. Documenting those as interchangeable would have been worse than leaving them undocumented, because a reader would trust it.Two panics were already described in prose but not under a
# Panicsheading, so neither rustdoc nor clippy surfaced them —Outcome::winnerandEventBuilder::weights. Both now carry it, andOutcome::winnergained a note that it ties every loser, son >= 3needs a positivep_draw. That is the easiest error in this crate to hit by accident.Two notes for the record:
cargo publishdoes not checklicensefor an alternative registry — verified by a clean dry run with none — butcargo releaserefuses outright withmissing the following fields: license || license-file, and--no-verifydoes not bypass it.examples/atp.csv. It is read by relative path rather thaninclude_str!, so excluding it still compiles andcargo package --verifystill builds every target. Published size is 374 KiB / 88 KiB compressed. Yourexcludelist predated that fixture; nothing warns you, the only signal is thePackaged N filesline.The
# Errors/# Panicsdeferral note above mentioned waiting on #20/#21 — that turned out unnecessary:predict_outcomeandOutcome::winnerare documented as panicking today, which is accurate regardless of whether those issues later convert them toResult.