Skip to content

crates.io publish prep for mortie-core (issue #201) - #210

Closed
espg wants to merge 19 commits into
mainfrom
claude/201-crates-prep
Closed

crates.io publish prep for mortie-core (issue #201)#210
espg wants to merge 19 commits into
mainfrom
claude/201-crates-prep

Conversation

@espg

@espg espg commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Refs #201 (crates.io publish prep). Refs #202 (due-diligence residuals folded in — espg decides when that issue closes).

Blocked by #207 — this PR stacks on the workspace-split branch (claude/200-workspace-split is the base, so the diff shows only the publish prep). It must stay draft until #207 merges and this is retargeted to main. The actual cargo publish is a production release espg executes by hand; this PR goes exactly as far as a clean cargo publish --dry-run and stops.

Phases

  • Phase 1 — crate metadata (430810a): mortie-core/Cargo.toml gains rust-version, homepage/readme, keywords, categories, and a docs.rs target pin; LICENSE (MIT) copied into the crate dir so the published archive ships the license text.
  • Phase 2 — README (78cdcd0): mortie-core/README.md with the wire-format-frozen framing per the semver ruling: crate API 0.x/unstable, byte-level codec grammar frozen-for-1.x and normative in the spec page (deep-linked under the latest/ alias, since the docs site is mike-versioned and the unprefixed path 404s). The anchors are slugified from the numbered headings, so they are not stable by construction — they are unaffected by Spec: normative toc word grammar, frozen for 1.x (issue #193) #206 specifically, because that PR appends a new section and leaves §1/§2 untouched. Includes the mortie-core due diligence: license, CDS-healpix dep overlap, MSRV, wasm32 target #202 license-direction line (MIT crate ← Apache-2.0 consumer is the clean direction). Also two test-only lines: iter::repeat_n (stabilized 1.82) → repeat().take() so the whole crate, tests included, compiles on the declared MSRV.
  • Phase 3 — CI leg (5b0e411): .github/workflows/mortie-core.yml, new standalone workflow (existing workflows untouched): build, cargo test -p mortie-core (includes tests/dep_contract.rs, the zero-dependency guard — the stale "no CI runs this" note in lib.rs updated accordingly), wasm32 build (mortie-core due diligence: license, CDS-healpix dep overlap, MSRV, wasm32 target #202), publish dry-run, and an MSRV job that tests the packaged crate on 1.67 (the check must leave the workspace: the workspace Cargo.lock is v4, unreadable by pre-1.78 cargo).

Name

Defaulted to mortie-core — available on crates.io, as are all alternatives (see the availability findings on #201). The name is espg's ruling and a five-minute mechanical rename, but it is not two-places-trivial — the sites are: the name field in mortie-core/Cargo.toml; the README title line and its use mortie_core::… example (the lib name derives from the package name, so the example stops compiling otherwise); the workspace-root Cargo.toml dependency key mortie-core = { path = "mortie-core" } (a build break, not a doc nit, unless the key changes or gains package = "…"); and .github/workflows/mortie-core.yml's four -p mortie-core flags plus its mortie-core-*.crate globs. The name-derived documentation = "https://docs.rs/mortie-core" field has been dropped (docs.rs is cargo's default for a published crate), removing one silent-breakage site.

MSRV: 1.67 (determined empirically)

  • Lib gate is u64::ilog10 (decimal_morton.rs:671), stabilized 1.67.0.
  • Verified against the packaged crate: full suite green on 1.67.0; 1.66 fails on int_log even with --ignore-rust-version, so 1.67 is the true floor, not just the declared one.
  • The only post-1.67 usage was iter::repeat_n in two #[cfg(test)] lines (would have made the crate-as-tested need 1.82); swapped to the equivalent repeat().take() (phase 2) rather than declaring a 15-release-newer MSRV for a test convenience.
  • Consumer side: healpix-geo's workspace pins no top-level rust-version, so there is no upstream constraint to match (mortie-core due diligence: license, CDS-healpix dep overlap, MSRV, wasm32 target #202).

Dry run (local, clean)

$ cargo publish --dry-run -p mortie-core
    Updating crates.io index
   Packaging mortie-core v0.1.0 (.../mortie-core)
    Packaged 11 files, 100.9KiB (28.8KiB compressed)
   Verifying mortie-core v0.1.0 (.../mortie-core)
   Compiling mortie-core v0.1.0 (.../target/package/mortie-core-0.1.0)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22s
   Uploading mortie-core v0.1.0 (.../mortie-core)
warning: aborting upload due to dry run

No path-dependency issues: the workspace root depends on mortie-core, not the reverse; cargo tree -p mortie-core is one line and tests/dep_contract.rs keeps it that way.

wasm32 (#202)

cargo build --target wasm32-unknown-unknown -p mortie-coreFinished clean, no changes needed (zero-dep arithmetic crate). Also wired into the CI leg.

How it was tested

  • cargo test -p mortie-core — 72 tests green (66 unit + dep_contract 2 + pivot_surface 4).
  • cargo publish --dry-run -p mortie-core — clean (tail above).
  • Packaged-crate MSRV check on 1.67.0 / negative check on 1.66.1, as described.
  • wasm32 build clean.
  • CI: this PR runs the new mortie-core crate workflow itself.

Questions for review

  1. Crate name ruling (publish mortie-core to crates.io: naming, semver posture, release mechanics #201): metadata defaults to mortie-core; all candidates are free on crates.io. Your call.
  2. Should the CI leg also run cargo fmt --check / clippy for mortie-core (touches Follow up items for the week of 2026-08-17 #208 item 1)? Left out to keep the leg minimal and avoid pre-empting the Follow up items for the week of 2026-08-17 #208 discussion.
  3. Release cadence (publish mortie-core to crates.io: naming, semver posture, release mechanics #201, still open): the ruling covered semver posture; own-cadence vs riding the mortie 1.0 tag event remains yours. Nothing in this PR mechanizes a release — publish stays a by-hand command.

@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.54%. Comparing base (9e8ad86) to head (3583a20).

Additional details and impacted files

Impacted file tree graph

@@                      Coverage Diff                       @@
##           claude/200-workspace-split     #210      +/-   ##
==============================================================
- Coverage                       96.67%   96.54%   -0.13%     
==============================================================
  Files                              20       19       -1     
  Lines                            2283     2171     -112     
==============================================================
- Hits                             2207     2096     -111     
+ Misses                             76       75       -1     
Flag Coverage Δ
unittests 96.54% <ø> (-0.13%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 4 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9e8ad86...3583a20. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread mortie-core/README.md Outdated
landing.
- **The byte-level codec grammar is frozen for the mortie 1.x series.** What
a word *means* — the
[packed 64-bit morton word](https://espg.github.io/mortie/specification/#1-the-packed-64-bit-morton-word)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🤖 from Claude (review)

All three spec links in this bullet 404. The docs site is mike-versioned (docs.yml runs mike deploy --push dev on main and mike deploy --push --update-aliases --alias-type redirect "$GITHUB_REF_NAME" latest on tags), so every page lives under a version segment — only /mortie/ itself is a redirect stub. Checked just now:

  • https://espg.github.io/mortie/specification/404
  • https://espg.github.io/mortie/latest/specification/ → 200 (redirect stub to /0.9.10/specification/; its JS re-appends window.location.hash, so the #1-… fragment survives the hop)
  • https://espg.github.io/mortie/dev/specification/ → 200 (direct page)

Both dev/ and 0.9.10/ do carry the anchors this cites (id="1-the-packed-64-bit-morton-word", id="2-decimal-string-representation"), so only the URL prefix is wrong.

This matters more than a usual dead link: the README is the crates.io landing page for a crate whose entire stability story is "the normative contract lives on that page, not in this version number" — and a published README is immutable, so a 404 ships forever at that version. (homepage in Cargo.toml is the site root and resolves fine; it's only these deep links.)

Fix: insert latest/ in all three URLs (lines 34, 36, 38), e.g. https://espg.github.io/mortie/latest/specification/#1-the-packed-64-bit-morton-word.

Separately, the PR body describes these as "stable anchors, so the section renumbering #206 introduces doesn't break the links". They are not stable by construction — they are slugified from the numbered headings (## 1. The packed 64-bit morton word#1-the-packed-64-bit-morton-word). They survive #206 only because that PR inserts a new §10 and leaves §1/§2 untouched; #206 itself has to keep a legacy #10-frozen-for-1x anchor precisely because numbered anchors break on renumber. Worth stating as "unaffected by #206" rather than as a property of the anchor scheme.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🤖 from Claude

Fixed in b973791 — all three spec links now carry the latest/ version segment (https://espg.github.io/mortie/latest/specification/#1-the-packed-64-bit-morton-word, …#2-decimal-string-representation, and the bare page). Verified with curl -sI before committing: unprefixed /mortie/specification/ → 404, /mortie/latest/specification/ → 200, and the redirect stub resolves to ../../0.9.10/specification/, which does carry both cited anchor ids. homepage = "https://espg.github.io/mortie/" in Cargo.toml returns 200 as you noted, so it is left as is.

The anchor-stability clause in the PR body is corrected too (same fold, body edit): it now says the anchors are slugified from the numbered headings and so are not stable by construction — they are unaffected by #206 specifically, because that PR appends a new section and leaves §1/§2 untouched.

Comment thread mortie-core/Cargo.toml Outdated
license = "MIT"
repository = "https://github.com/espg/mortie"
homepage = "https://espg.github.io/mortie/"
documentation = "https://docs.rs/mortie-core"

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🤖 from Claude (review)

The name-swappability claim is wrong as stated, and it is the claim espg is being asked to rule from. The PR body and the #201 availability comment both say the name "appears in exactly two places — the name field in mortie-core/Cargo.toml and the README title line". Grepping the branch finds at least five sites, and three of them break on a rename rather than merely going stale:

  • this linedocumentation = "https://docs.rs/mortie-core": the docs.rs URL is name-derived, so it silently points at the wrong (nonexistent) crate after a rename.
  • mortie-core/README.md:16use mortie_core::{from_nested, to_nested};: the lib name is derived from the package name, so a rename makes the README's only code example not compile.
  • Cargo.toml (workspace root)mortie-core = { path = "mortie-core" }: the dependency key is the package name; rename the package and the workspace stops building unless the key changes or a package = "…" field is added.
  • .github/workflows/mortie-core.yml — four -p mortie-core invocations plus the tar/cd globs on mortie-core-*.crate (and the workflow file name).

None of these is hard to edit, but "exactly two places" understates the swap for the person making the ruling, and the root-manifest one is a build break, not a doc nit. Either correct the count on the PR body and #201 with the actual site list, or shrink it for real: documentation can be dropped (docs.rs is cargo's default for a published crate, so the field buys nothing) and the README example can avoid the crate path — which would get the mandatory edits down to name, the root dep key, and the workflow.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🤖 from Claude

Folded both ways you offered — shrink what shrinks, tell the truth about the rest.

3583a20 drops documentation = "https://docs.rs/mortie-core" from mortie-core/Cargo.toml (docs.rs is cargo's default for a published crate, so the field bought nothing and was a silent-breakage site on rename). cargo test -p mortie-core still 72 green and cargo publish --dry-run -p mortie-core still clean after the drop.

The README use mortie_core::… example and the workflow's -p flags/globs are left alone — they are legitimate name sites, and contorting the crate's only code example to dodge the crate path would cost more than the rename it saves.

The prose that made the false claim is corrected in both places (no commit — GitHub-side edits):

  • PR body, "Name" section — now enumerates the real sites: the name field; the README title line and its use mortie_core::… example; the workspace-root dep key mortie-core = { path = "mortie-core" } (flagged as a build break, not a doc nit); and .github/workflows/mortie-core.yml's four -p flags plus the mortie-core-*.crate globs. Framed as a five-minute mechanical rename, not "two places". The phase-1 bullet no longer lists documentation among the added fields.
  • #201 availability comment — the "exactly two places" sentence is replaced with the same enumeration; the rest of the comment is untouched.

@codspeed-hq

codspeed-hq Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will degrade performance by 15.44%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 1 regressed benchmark
✅ 70 untouched benchmarks
⏩ 1 skipped benchmark1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
fast_norm2mort_scalar 319.4 ns 377.8 ns -15.44%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing claude/201-crates-prep (3583a20) with claude/200-workspace-split (9e8ad86)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

@espg

espg commented Aug 24, 2026

Copy link
Copy Markdown
Owner Author

🤖 from Claude

Status: all three phases landed, both adversarial-review findings folded (b973791, 3583a20) with replies on their threads, and CI is green on 3583a20 — including the new mortie-core crate workflow this PR adds (crate and msrv jobs both pass, so the packaged-crate MSRV check and the wasm32/dry-run legs are empirically verified on the runner, not just locally).

One flag, not fixed here: CodSpeed Performance Analysis reports "fail" on a single benchmark, fast_norm2mort_scalar (319.4 ns → 377.8 ns, −15.44%), comparing 3583a20 against the #207 base 9e8ad86. That benchmark lives in src_rust/benches/morton_bench.rs; this PR touches no src_rust code at all (diff: mortie-core/ metadata + README + two #[cfg(test)]-only lines, one lib.rs doc comment, one new workflow file), and CodSpeed's own report carries a "Different runtime environments detected" warning for exactly this comparison. Reading it as measurement noise across runner environments, per the repo rule against papering over unrelated CI signal — acknowledging it on the CodSpeed dashboard is your call.

The PR stays draft + blocked (Blocked by #207): it cannot go ready while the workspace-split base is unmerged. When #207 merges, this retargets to main; remaining espg decisions are in "Questions for review" (crate name ruling, fmt/clippy in the CI leg vs #208, release cadence).

Base automatically changed from claude/200-workspace-split to main August 24, 2026 16:41
@espg

espg commented Aug 24, 2026

Copy link
Copy Markdown
Owner Author

🤖 from Claude

Superseded by #211. #207 was squash-merged to main, so this stacked branch's ancestry no longer matches and retargeting the base would double-count the workspace-split content; force-pushing is off the table by policy. #211 carries the same five prep commits (phases 1–3 plus both review folds) cherry-picked onto main, with the body updated for the espg name ruling (mortie-core, recorded on #201). Both adversarial-review threads here were folded and answered before the move (b973791, 3583a202d40543, 2b119db on #211).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked flag for claude implement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant