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
17 changes: 12 additions & 5 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ targeted `Edit` patches. Do not suppress clippy warnings with `#[allow(...)]`.
- **GPG-signed commits**: always use `git commit -S`. The GPG agent is working.
- **Atomic commits**: commit early and often. Huge monolithic commits make it
hard to catch off-rail behaviour.
- **PR descriptions are concise and professional**: a short summary of what
changed and why, the validation performed, and any risk or follow-up —
a few sentences or bullets total. Do NOT inventory individual edits (the
diff shows those), narrate review rounds, or paste investigation memos.
Long-form audit/investigation material goes in a PR **comment** or the
commit messages, never the description.
- **No temp file litter**: clean up all one-off scripts immediately.
- **Do not touch `.claude/worktrees/`**: this directory is managed by
Claude Code for isolated worktree sessions. Never delete, modify, or
Expand Down Expand Up @@ -158,12 +164,13 @@ when working single-threaded on one feature branch.
**Anything else does not belong in `docs/`.** In particular:

- **Audit memos** (impact analysis of a bug fix, which research scripts
were affected, etc.) — belong in the PR body. When the PR merges,
the memo is preserved in the commit + PR history where it is actually
searchable. Do not create `docs/audit/` or similar.
were affected, etc.) — belong in a PR **comment**, never the PR
description (see Commit Style). When the PR merges, the memo is
preserved in the PR history where it is actually searchable. Do not
create `docs/audit/` or similar.
- **Investigation / ablation / debugging notes** (step-by-step inquiry
into a performance question, correctness hypothesis, etc.) — belong in
`.research/` (gitignored; session-private) or in the PR body if the
`.research/` (gitignored; session-private) or in a PR comment if the
investigation directly motivates a concrete code change.
- **Design specs / requirements drafts** — belong inline with the code
they specify (rustdoc on the struct / module they describe) or in
Expand All @@ -173,7 +180,7 @@ when working single-threaded on one feature branch.
If I feel compelled to commit a memo under `docs/`, I stop and check:
(a) is this user-facing reference that someone reading the project
cold will want to read? If yes, it fits one of the subtrees above.
If no, it belongs in `.research/` or the PR body. **When in doubt,
If no, it belongs in `.research/` or a PR comment. **When in doubt,
ask the user before creating the file** — do not invent a new
`docs/<whatever>/` directory to make the artifact commit-able.

Expand Down
34 changes: 19 additions & 15 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- run: cargo check --workspace --exclude nereids-python
# Compile-check workspace examples so docs snippets cannot drift
Expand Down Expand Up @@ -50,9 +50,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml
components: rustfmt
- run: cargo fmt --all -- --check

Expand All @@ -70,9 +70,9 @@ jobs:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml
components: clippy
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- run: cargo clippy --workspace --exclude nereids-python --all-targets -- -D warnings
Expand All @@ -95,9 +95,9 @@ jobs:
os: [macos-latest, windows-latest]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Build
run: cargo build --workspace --exclude nereids-python
Expand All @@ -111,9 +111,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Build docs
run: cargo doc --workspace --no-deps --exclude nereids-python
Expand Down Expand Up @@ -141,9 +141,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- name: Install pixi
uses: prefix-dev/setup-pixi@a0af7a228712d6121d37aba47adf55c1332c9c2e # v0.9.4
Expand All @@ -159,12 +159,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml
components: llvm-tools-preview
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
- uses: taiki-e/install-action@50570a4fd0cb7e583e6a512c02bffb9ade28d868 # cargo-llvm-cov
# Pin release-tag SHAs only (like security.yml), never taiki-e's
# per-tool tags (e.g. `cargo-llvm-cov`): those are orphan commits on
# no branch, and Dependabot's github_actions updater hard-errors on
# them ("no such commit"), killing the whole update run.
- uses: taiki-e/install-action@c7eb1735f09259a5035e8e5d44b1406b1cddc0fb # v2.83.0
with:
tool: cargo-llvm-cov
- name: Generate coverage
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ jobs:
- name: Check curated Python API page is in sync with .pyi stubs
run: python scripts/check_python_api_drift.py

- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml

- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ jobs:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml

- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2

Expand Down Expand Up @@ -270,9 +270,9 @@ jobs:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: stable
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml

- name: Publish crates (dependency order)
env:
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
- uses: taiki-e/install-action@4684b8405694ae9dd42c9f39ba901a70ae83f4a3 # v2.82.9
- uses: dtolnay/rust-toolchain@fa04a1451ff1842e2626ccb99004d0195b455a88 # master
with:
toolchain: "1.96.1" # keep in sync with rust-toolchain.toml
- uses: taiki-e/install-action@c7eb1735f09259a5035e8e5d44b1406b1cddc0fb # v2.83.0
with:
tool: cargo-audit
# Fails on unignored vulnerabilities. Accepted-risk advisories (with a
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/wheel-policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ on:
- '.github/workflows/publish.yml'
- '.github/workflows/wheel-policy.yml'
- 'scripts/check_wheel_policy.sh'
# maturin-action resolves the in-container compiler from the repo
# root rust-toolchain.toml, so a pin-only bump changes the release
# wheel compiler and MUST schedule this gate.
- 'rust-toolchain.toml'

permissions:
contents: read
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ tmp/

# do not track manuscript folders
.manuscripts/

# Session-local agent-harness state (task contracts, verify gates)
.harness/
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Open a GitHub issue with the `enhancement` label. Include:

### Prerequisites

- [Rust](https://www.rust-lang.org/tools/install) (stable toolchain)
- [Rust](https://www.rust-lang.org/tools/install) (rustup; the exact version is pinned by rust-toolchain.toml)
- [pixi](https://pixi.sh/) (Python environment manager)
- cmake (for HDF5 builds)

Expand Down
2 changes: 1 addition & 1 deletion apps/gui/src/file_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ impl FileDialogs {
egui::Window::new("native_dialog_pending")
.title_bar(false)
.resizable(false)
.anchor(egui::Align2::CENTER_TOP, [0.0, 8.0])
.anchor(egui::Align2::CENTER_TOP, [0.0_f32, 8.0_f32])
.show(ctx, |ui| {
ui.horizontal(|ui| {
ui.spinner();
Expand Down
12 changes: 6 additions & 6 deletions apps/gui/src/guided/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ fn fit_feedback_panel(ui: &mut egui::Ui, state: &AppState) {
};
egui::Frame::default()
.fill(bg_color)
.stroke(egui::Stroke::new(1.5, border_color))
.stroke(egui::Stroke::new(1.5_f32, border_color))
.corner_radius(4.0)
.inner_margin(6.0)
.show(ui, |ui| {
Expand Down Expand Up @@ -999,7 +999,7 @@ fn image_color_bar(
painter.rect_stroke(
response.rect,
0.0,
egui::Stroke::new(1.0, ui.visuals().widgets.noninteractive.bg_stroke.color),
egui::Stroke::new(1.0_f32, ui.visuals().widgets.noninteractive.bg_stroke.color),
egui::StrokeKind::Inside,
);
ui.horizontal(|ui| {
Expand Down Expand Up @@ -1446,7 +1446,7 @@ fn spectrum_panel(ui: &mut egui::Ui, state: &mut AppState) {
.collect()
};
let measured_points = Points::new("Measured", measured_points)
.radius(1.4)
.radius(1.4_f32)
.color(crate::theme::semantic::RED);

// OB reference line (counts mode only): the c·OB curve the KL
Expand Down Expand Up @@ -1721,7 +1721,7 @@ fn draw_aligned_tick_row(
painter.rect_stroke(
track_rect,
2.0,
egui::Stroke::new(1.0, ui.visuals().widgets.noninteractive.bg_stroke.color),
egui::Stroke::new(1.0_f32, ui.visuals().widgets.noninteractive.bg_stroke.color),
egui::StrokeKind::Inside,
);

Expand Down Expand Up @@ -1761,7 +1761,7 @@ fn draw_aligned_tick_row(
egui::pos2(x_pos, track_rect.top()),
egui::pos2(x_pos, track_rect.bottom()),
],
egui::Stroke::new(1.0, row.color),
egui::Stroke::new(1.0_f32, row.color),
);
}
}
Expand Down Expand Up @@ -1869,7 +1869,7 @@ fn draw_dragged_resonance_ruler(
));
painter.line_segment(
[egui::pos2(x, frame.top()), egui::pos2(x, frame.bottom())],
egui::Stroke::new(2.0, ruler.color),
egui::Stroke::new(2.0_f32, ruler.color),
);
painter.text(
egui::pos2(x + 6.0, pointer_y),
Expand Down
2 changes: 1 addition & 1 deletion apps/gui/src/guided/detectability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ pub(crate) fn detect_results_panel(ui: &mut egui::Ui, state: &AppState) {
.map(|i| [report.energies[i], report.delta_t_spectrum[i]])
.collect();
let color = design::isotope_dot_color(name);
plot_ui.line(Line::new(name.as_str(), points).color(color).width(1.5));
plot_ui.line(Line::new(name.as_str(), points).color(color).width(1.5_f32));
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion apps/gui/src/guided/forward_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ pub(crate) fn fm_spectrum_panel(ui: &mut egui::Ui, state: &mut AppState) {
.filter(|&i| x_values[i].is_finite())
.map(|i| [x_values[i], combined[i]])
.collect();
plot_ui.line(Line::new("Combined T(E)", points).width(2.0));
plot_ui.line(Line::new("Combined T(E)", points).width(2.0_f32));
}

// Per-isotope contribution lines (dashed, colored by isotope hash)
Expand Down
4 changes: 2 additions & 2 deletions apps/gui/src/guided/landing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ pub fn landing_step(ui: &mut egui::Ui, state: &mut AppState) {
.fill(tc.bg2)
.corner_radius(CornerRadius::same(8))
.inner_margin(Margin::symmetric(16, 10))
.stroke(Stroke::new(1.0, tc.border))
.stroke(Stroke::new(1.0_f32, tc.border))
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.vertical(|ui| {
Expand Down Expand Up @@ -167,7 +167,7 @@ fn landing_card(
.fill(tc.bg2)
.corner_radius(CornerRadius::same(12))
.inner_margin(Margin::same(20))
.stroke(Stroke::new(1.0, tc.border))
.stroke(Stroke::new(1.0_f32, tc.border))
.shadow(Shadow {
offset: [0, 1],
blur: 3,
Expand Down
2 changes: 1 addition & 1 deletion apps/gui/src/guided/result_widgets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ pub fn draw_colorbar(ui: &mut egui::Ui, data: &ndarray::Array2<f64>, colormap: C
painter.rect_stroke(
bar_rect,
0.0,
egui::Stroke::new(1.0, egui::Color32::GRAY),
egui::Stroke::new(1.0_f32, egui::Color32::GRAY),
egui::StrokeKind::Outside,
);

Expand Down
6 changes: 3 additions & 3 deletions apps/gui/src/guided/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn guided_sidebar(ui: &mut egui::Ui, state: &mut AppState) {
egui::Frame::NONE
.fill(colors.bg)
.inner_margin(margin)
.stroke(Stroke::new(1.0, colors.border)),
.stroke(Stroke::new(1.0_f32, colors.border)),
)
.show_inside(ui, |ui| {
if state.sidebar_collapsed || force_compact {
Expand Down Expand Up @@ -268,7 +268,7 @@ fn collapsed_step_badge(
);
} else {
ui.painter()
.circle_stroke(center, 10.0, Stroke::new(1.0, colors.border));
.circle_stroke(center, 10.0, Stroke::new(1.0_f32, colors.border));
ui.painter().text(
center,
egui::Align2::CENTER_CENTER,
Expand Down Expand Up @@ -466,7 +466,7 @@ fn pipeline_step_row(
} else {
// Pending: outlined icon, not a filled status dot.
ui.painter()
.circle_stroke(center, 10.0, Stroke::new(1.0, colors.border));
.circle_stroke(center, 10.0, Stroke::new(1.0_f32, colors.border));
ui.painter().text(
center,
egui::Align2::CENTER_CENTER,
Expand Down
8 changes: 4 additions & 4 deletions apps/gui/src/guided/wizard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn breadcrumb_bar(ui: &mut egui::Ui, state: &mut AppState) {
.stroke(if is_active || is_past {
Stroke::NONE
} else {
Stroke::new(1.0, tc.border)
Stroke::new(1.0_f32, tc.border)
})
.show(ui, |ui| {
ui.label(RichText::new(*label).size(11.0).strong().color(text_color));
Expand Down Expand Up @@ -250,7 +250,7 @@ fn wizard_confirm(ui: &mut egui::Ui, state: &mut AppState) {
.fill(tc.bg2)
.corner_radius(CornerRadius::same(8))
.inner_margin(Margin::same(16))
.stroke(Stroke::new(1.0, tc.accent))
.stroke(Stroke::new(1.0_f32, tc.accent))
.show(ui, |ui| {
ui.set_min_width(full_w - 38.0);
ui.label(
Expand Down Expand Up @@ -331,9 +331,9 @@ fn wizard_option_card(
let tc = ThemeColors::from_ctx(ui.ctx());
let fill = if selected { tc.bg3 } else { tc.bg2 };
let border = if selected {
Stroke::new(2.0, tc.accent)
Stroke::new(2.0_f32, tc.accent)
} else {
Stroke::new(1.0, tc.border)
Stroke::new(1.0_f32, tc.border)
};

let full_w = ui.available_width();
Expand Down
4 changes: 2 additions & 2 deletions apps/gui/src/studio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ fn bottom_dock(ui: &mut egui::Ui, state: &mut AppState) {
egui::Frame::NONE
.fill(colors.bg)
.inner_margin(egui::Margin::symmetric(12, 8))
.stroke(egui::Stroke::new(1.0, colors.border)),
.stroke(egui::Stroke::new(1.0_f32, colors.border)),
)
.show_inside(ui, |ui| {
let labels = &["Isotopes", "Residuals", "Provenance", "Export"];
Expand Down Expand Up @@ -1113,7 +1113,7 @@ fn parameter_sidebar(ui: &mut egui::Ui, state: &mut AppState) {
egui::Frame::NONE
.fill(colors.bg)
.inner_margin(egui::Margin::symmetric(10, 8))
.stroke(egui::Stroke::new(1.0, colors.border)),
.stroke(egui::Stroke::new(1.0_f32, colors.border)),
)
.show_inside(ui, |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
Expand Down
Loading
Loading