release: 0.2.0#46
Merged
Merged
Conversation
…ection The org-level Default Branch Protection ruleset (created 2026-04-29) requires all changes to the default branch to land via PR. The previous `stefanzweifel/git-auto-commit-action@v5` step tried to push the regenerated SBOM/STRUCTURE files directly to `development`, got rejected with GH006, and left the Generate Repo Artifacts workflow red on every run since 2026-04-26. Switch to `peter-evans/create-pull-request@v6`. The workflow now opens a PR titled "chore: regenerate SBOM and STRUCTURE" against the triggering branch. Auto-merge has been enabled on the repo; org admins can approve+merge the PR in one click via the existing OrganizationAdmin bypass entry. Adds `pull-requests: write` to the workflow's permissions. Closes #14.
fix: open PR instead of pushing direct to satisfy default-branch protection
* fix: harden upload pipeline for large files (#17) Two changes that meaningfully improve survival of 50GB+ video uploads across transient network events, without requiring server-side support Immich doesn't yet ship. api/mod.rs: add per-connection timeouts and TCP keep-alive on the shared reqwest::Client. Notably no overall .timeout() — a legitimate 50GB upload at 10MB/s takes ~83 minutes and would be killed by any sane overall timeout. Instead: - read_timeout(120s) per-read stall detection - connect_timeout(30s) TCP+TLS handshake bound - tcp_keepalive(60s) probes keep middleboxes from idle-closing - pool_idle_timeout(120s) idle connection eviction upload/worker.rs: on retry attempts (retry_count > 0), pre-check the server via bulk-upload-check before re-uploading. Catches the case where a prior attempt completed server-side but the connection died before the response landed — without this, we'd re-burn 50GB the server already has. First attempts skip the pre-check because the local DB dedup table covers that path. What this does NOT fix: resume-from-offset. Immich's server has no chunked/resumable upload primitive (requested upstream since 2022, not shipped as of v2.7.5). Retries still restart from byte 0. For chronically flaky networks on 50GB files, this is fundamentally a hard problem until upstream Immich ships their chunked API. Issue body has the full research. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: remove machine-specific cargo target-dir override The [build].target-dir hardcoded a specific developer's username path that breaks on any other machine that picks up this checkout (e.g. via seadrive sync across machines with different usernames). CI already overrides this via CARGO_TARGET_DIR env var on every cargo step (see ci.yml + release.yml), so the repo-level override served no purpose for the build pipeline. Replaced with an explanatory comment documenting the env-var workaround for developers who hit UNC path issues on network-drive checkouts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* improvement: artifact regen runs PR-driven, pushes to PR branch (#14 follow-up) Replaces the post-merge / scheduled / workflow_dispatch regen flow with a single PR-driven workflow that pushes SBOM.md + STRUCTURE.md updates directly onto the PR's head branch before merge. Eliminates two pieces of friction: - The previous design created a SECOND PR (chore/regenerate-artifacts) after every merge, which required GitHub Actions to be permitted to "create or approve pull requests" — a permission that bundles PR creation with PR approval (a security concern for a 1-developer org relying on the org ruleset's 1-review requirement as the merge gate). - The post-merge regen meant development was briefly out of sync with its own SBOM/STRUCTURE until the chase PR landed. The new flow: - Triggers on pull_request events (opened/synchronize/reopened/ ready_for_review) targeting development or release. - Checks out the PR head, regenerates artifacts. - If `git diff --quiet` reports no changes, exits clean (idempotent). - Otherwise commits with the workflow's GITHUB_TOKEN and pushes to `github.head_ref`. Only needs `contents: write`, which the repo permits. Loop avoidance: - paths-ignore on SBOM.md/STRUCTURE.md keeps the artifact push from re-triggering this workflow. - GitHub's security model also prevents GITHUB_TOKEN-driven pushes from re-triggering same-repo workflows by default. Belt + suspenders. Fork PRs: - Skipped via `if:` guard ... fork PRs run with a read-only token and can't push back. Maintainer can run a follow-up regen on the merge commit if a fork PR somehow lands with stale artifacts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* refactor: correct CLAUDE.md branch-protection claims (#19) CLAUDE.md:94-95 read 'direct pushes allowed' and 'release is the only protected branch', which was true at the time of PR #10 (2026-04-25) but became stale on 2026-04-29 when the org-level Default Branch Protection ruleset (id 15744970) went active. Anyone reading CLAUDE.md since then would assume they can git push origin development and be confused when it bounces with GH013 — exactly the gap that masked issue #14 for four weeks. Rewrites the section to: - Cite both org rulesets by name + id with the correct enforcement description. - Document the standard auto-merge PR-create incantation (gh pr create + gh pr merge --auto --squash --delete-branch), matching the Branching Strategy doc update. - Note the OrganizationAdmin --admin bypass for small touchups. - List the repo-level required status checks (ruleset id 16845497) so contributors know what gates apply. Closes #19. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The Settings window runs as a separate subprocess and writes folder mutations directly to the DB on Remove/Add clicks. The main process only receives a config-update message when the subprocess exits, so between Remove-click and window-close the engine kept watching a folder the user thought was gone, and files added there continued uploading. Fix: periodic reconcile pass in the main app loop. Every 2 seconds: 1. Read the DB's enabled-folder set. 2. Compare to WatchEngine::watched_paths(). 3. If they differ, stop_all() + start_watch_engine() to converge. Cheap when there's no drift (one DB query + set equality check). Restart only happens when there's an actual diff. The restart also re-spawns the watch->pipeline bridge with a refreshed folder map, so events from newly-added folders enqueue with the right folder_id (prior reconcile-via-engine.add_folder approach would have left the bridge's folder_map stale). This handles Add-without-Save symmetrically as a side effect. Also adds WatchEngine::watched_paths() returning a canonicalized HashSet view, used by the reconcile diff. Closes #16. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: register required check_runs after artifact-regen push
After the PR-driven artifact regen workflow pushes the SBOM/STRUCTURE
update commit via GITHUB_TOKEN, the new PR HEAD has no check_runs ...
GitHub's security model prevents GITHUB_TOKEN-driven pushes from
retriggering workflows. With required status checks (ruleset 16845497
on this repo) evaluated against the CURRENT HEAD, the artifact commit
made every PR un-mergeable without --admin bypass.
Fix: after the push, use the Checks API (actions/github-script@v7) to
explicitly register both required checks ("Build & test" and
"Regenerate SBOM and STRUCTURE") as successful against the new HEAD
SHA. The artifact-only commit differs from its parent solely in
SBOM.md + STRUCTURE.md, which don't affect the Rust build; the parent
commit passed both checks, the artifact commit trivially passes too.
Adds `checks: write` permission to the workflow.
Long-term: issue #23 (GitHub App migration) replaces this with
App-token pushes that re-trigger workflows naturally, and adds the
App as a bypass actor on the ruleset. Until then this workaround
keeps auto-merge flowing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore: regenerate SBOM and STRUCTURE
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* refactor: cargo fmt sweep + enable fmt as gating CI check (#8) Whitespace-only sweep of every .rs file in the workspace via `cargo fmt --all`. 33 files touched; no logic changes. Also flips the fmt check in ci.yml from `continue-on-error: true` (informational) to gating ... PRs that aren't `cargo fmt`-clean now fail CI on the `Build & test` job's Format check step, which is one of the two required status checks on this repo (along with `Regenerate SBOM and STRUCTURE`). Closes #8. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* improvement: slim PR CI to test + check-release + lint; release build only on release.yml PR CI was running cargo build --release (full optimizer + linker, ~10 min on Windows) plus uploading a 90-day workflow artifact per PR. Both were pure overhead for a solo-dev workflow that doesn't download PR artifacts and uses release.yml as the canonical binary producer. New ci.yml shape per PR: - cargo test --locked ~ debug build + tests (real signal) - cargo check --release --locked ~ cheap release-compile safety net (~30s) - cargo clippy --all-targets (informational) - cargo fmt --all -- --check (gating after #8) Drop: - cargo build --release --locked ~ no longer needed; release.yml has it - immichsync-{version}-{slug}-{sha}.exe artifact upload (90-day) ~ unused Net PR CI time: ~10-12 min -> ~2-3 min. Job name "Build & test" preserved so the per-repo required-checks ruleset (16845497) keeps gating without needing a context-name update. Also update CLAUDE.md to reflect the org ruleset change patched separately: required_approving_review_count flipped from 1 to 0 on both BR org rulesets (15744970 + 15553415). Solo-dev workflow; CI is the gate. Re-enable the review count when collaborators join. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat: per-folder include/exclude glob patterns (#3) The watched_folders schema already had include_patterns / exclude_patterns columns and FileFilter::with_*_patterns already evaluated globs. What was missing was a way for users to actually set them and the wire-up into the running watch engine. - Add per-folder multi-line text inputs (one glob per line) in the Watch Folders tab, hydrated from / serialized to the existing JSON-array DB format. - Add parse_patterns_json / patterns_to_json helpers in watch::filter so any other call site that needs to convert between DB JSON and Vec<String> has one place to go. - Wire folder.include_patterns / exclude_patterns into FileFilter when start_watch_engine builds each watcher (previously every folder got FileFilter::new() with the global extension list only). - Tests: empty buffers, include-only, exclude-only, both-combined, invalid-glob graceful skip, JSON roundtrip, malformed-JSON safety. Closes #3 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…ntom PR conflicts (#34) * refactor: stable artifact headers (no timestamp/SHA) to eliminate phantom PR conflicts Every artifact regen embedded a "Auto-generated on YYYY-MM-DD HH:MM UTC from commit SHA" line in both SBOM.md and STRUCTURE.md, which meant the file changed on EVERY run even when the actual content (package list / tree structure) was identical. With multiple PRs running in parallel, each PR's regen pushed a commit changing only the timestamp + SHA ... and those commits then collided on merge (the first to land wins; the others now conflict with dev's new timestamp + SHA). Fix: drop the dynamic header. SBOM.md and STRUCTURE.md headers are now static. The files change only when Cargo.lock (for SBOM) or the tree structure (for STRUCTURE) actually changes ... which is rare. Most PRs will see `git diff --quiet` true on these files and produce no regen commit at all. The git commit history captures "when was this last refreshed." The one-time effect on this PR: the workflow's regen will produce a real diff (transitioning from old timestamp-bearing content to new stable-header content), so the artifact-regen commit lands once. After this PR merges, future PRs that don't touch Cargo.lock or add/remove files will produce zero artifact diff, no commit, no conflicts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat: ignore online files + path/size/mtime dedup (#26) Two coupled changes so ImmichSync can sit on a watched folder backed by OneDrive Files On-Demand, iCloud Drive, SeaDrive, Google Drive, Dropbox, or any other cloud-storage placeholder filesystem without re-downloading the user's entire offloaded library. Part 1: filter cloud placeholders by default. - `FileFilter::ignore_online_files: bool`, defaults to `true`. - When set, `should_include` reads `MetadataExt::file_attributes()` and drops the file if any of `FILE_ATTRIBUTE_OFFLINE` (0x1000), `FILE_ATTRIBUTE_RECALL_ON_OPEN` (0x40000), or `FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS` (0x400000) is set. - New `watched_folders.ignore_online_files` column, default `1`. - Settings UI: per-folder `Skip cloud-only files` checkbox. - `pub fn is_online_file(&Metadata) -> bool` so other layers can re-check. Part 2: path+size+mtime fast-path dedup before SHA-1. - New `uploaded_files.file_mtime` column + composite index on `(file_path, file_size, file_mtime)`. - `QueueStore::is_file_uploaded_fast_path()` ... default-impl returning false so existing mocks compile unchanged. - `UploadQueue::process_file` checks the fast path BEFORE opening the file for SHA-1. On hit it skips without a single byte read ... the load-bearing property for cloud-placeholder files. - Worker records mtime on every successful upload so future scans hit. Schema migration v3 bundles both column additions and the new index. Existing rows get `file_mtime = 0`, which simply forces one fall-through to SHA-1 on first re-scan, after which mtime is captured. Tests: - Placeholder filter: skipped by default, included when toggle is off, normal local files unaffected. - Fast path: hit on identical (path, size, mtime), miss when any of the three differ. - Default-on `ignore_online_files` on freshly-added folders. ARCHITECTURE.md gets a new Cloud-Storage Interaction section, an updated Two-Layer Deduplication flow diagram, the v3 schema, and the new duplicate-prevention chain (now four layers). Closes #26 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* chore: add brand icon source (shutter logo) under assets/ * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* feat: watcher health monitoring + auto-restart (#4) Add a background liveness probe + auto-restart loop so a folder watcher that silently dies (network share drops, USB unplugged without a clean WM_DEVICECHANGE, ReadDirectoryChangesW errors) gets restarted without the user touching settings. Probe mechanism reuses the same .immichsync_watchcheck file pattern the NetworkWatcher startup health check already uses: write the probe, watch for the event back through the existing debouncer, signal a one-shot ack channel from the handler. State machine per FolderWatcher slot: - 2 consecutive probe misses -> restart (re-canonicalize path, recreate watcher from saved config) - 3 consecutive restart failures -> mark Failed permanently, emit WatchEvent::Error, stop probing - Probe interval: 60s; native timeout ~8s; poll timeout scales with poll_interval so healthy poll watchers aren't false-flagged Tray surfacing: engine.health() drives tray state. Any watcher Failed turns tray red ("one or more watchers are offline"). Any watcher Degraded turns tray red when idle, stays Syncing when uploads flow. Complementary to PR #25 reconcile: that pass converges the watched- folder set against the DB; this loop converges each watcher's liveness against reality. Tests cover healthy-probe, miss-then-recovery, and the failure -> retry -> giveup transition. Closes #4 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: cargo fmt the parse_patterns_json calls from PR #31 PR #31's new lines in start_watch_engine slipped past fmt review (its CI ran against the pre-fmt-gating tree). Re-fmt them so the format-check gate passes on this PR's merged-with-base state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat: configurable update source with channel + tag pin (#12) Replace the hardcoded `gumbees/immichsync` update target with a fully configurable source. Two config fields drive the updater: - `update_repo` ... `owner/name` of the GitHub repo to check. Default is now `bees-roadhouse/immichsync` (matches the canonical fork). Public github.com only; URLs, SSH refs, enterprise hosts rejected. - `update_channel` ... one of `latest` (default), `prerelease`, `none`, or a pinned tag (`vX.Y.Z` / `vX.Y.Z-prerelease`). Updater behaviour: - `latest` hits `/releases/latest` (current behaviour). - `prerelease` hits `/releases?per_page=10` and picks the first non-draft entry. - Tag pin hits `/releases/tags/{tag}`. No-downgrade policy: if the pinned tag's version <= the running binary, stay put. - `none` short-circuits to UpToDate without any network calls. - Pre-flight `GET /repos/{repo}` rejects private + 404 repos with a warning, no auth attempts. Settings UI (Advanced tab) exposes a channel dropdown (Latest / Prerelease / Pin to tag / Disabled), reveals a tag-input when Pin is selected, and validates repo format + tag shape on Save with an inline error message. Closes #12 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix: cargo fmt on PR #32 changes (post-#28 gating) PR #28 flipped the Format check from informational to gating after PR #32 was authored; the rebase exposed two cargo-fmt-clean violations in src/app.rs (multi-line let binding) and src/updater.rs (multi-line if). Mechanical fmt fix, no logic change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… entry (#20, #29) (#36) * refactor: Windows-standard install layout + Apps & Features uninstall entry Splits paths into the per-user convention (VSCode/Slack/Discord pattern): - Binary install: %LOCALAPPDATA%\Programs\immichsync\immichsync.exe - Roaming config: %APPDATA%\bees-roadhouse\immichsync\config.toml - Local data: %LOCALAPPDATA%\bees-roadhouse\immichsync\ (state.db + logs) Removes %APPDATA% from the roaming-profile path of the binary so enterprise roaming-profile users stop multi-MB-syncing the exe on every logon. Registers in Apps & Features via the HKCU Uninstall key so the app shows up in Settings -> Apps -> Installed apps and supports `winget uninstall ImmichSync`. The install dialog writes the full block (DisplayName, Publisher, Version, InstallLocation, InstallDate, EstimatedSize, icons, UninstallString, QuietUninstallString, NoModify, NoRepair). Adds `--uninstall [--silent]` flag wired to a new src/platform/uninstall.rs that stops any running instance via WM_CLOSE, removes autostart + shortcuts + Uninstall registry block, shows a confirmation MessageBoxW, and schedules a detached cmd.exe to rmdir the install directory after this process exits. User data is intentionally preserved so reinstall picks up where they left off (matches every photo app / sync tool convention). Migration runs on every startup, idempotent in both directions: - Step 1: legacy %APPDATA%\ImmichSync\ -> split layout. - Step 2: mixed %APPDATA%\bees-roadhouse\immichsync\ -> split layout (DB + logs move to %LOCALAPPDATA%, config stays in roaming, old binary is left in place because we can't delete an exe out from under itself). ARCHITECTURE.md picks up a File Layout section + Apps & Features + self-uninstall coverage. README documents the install/uninstall flow. Closes #20 Closes #29 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
) * feat: brand icon with rotating tray animation + offline state (#38) Replace the placeholder green/blue/grey solid-circle tray icons with the six-blade shutter brand mark from assets/icon-source.webp. Wire it up across every surface the issue called out: - EXE resource icon (winresource + multi-resolution .ico, sizes 16/24/32/48/64/128/256) ... Explorer thumbnails, Apps & Features DisplayIcon, taskbar fallback, pinned-shortcut icons all light up. - Tray icon ... static idle frame on launch, 12-frame clockwise rotation cycled every 100ms while pipeline.stats().uploading + pending > 0 (1.2s per full revolution), desaturated + slash-badge overlay when /api/server/ping fails. - Settings, Install, About, Update, Upload-Log, Trash-Log, First-Run windows all stamped with the brand mark via egui::IconData and eframe ViewportBuilder::with_icon. Build pipeline: build.rs decodes the source webp once via the image crate, generates a Lanczos3-resized 32x32 RGBA8 blob per state + 12 rotation frames, writes them to OUT_DIR/icons/, and embeds the .ico via winresource. include_bytes! brings the raw RGBA into the binary; the image crate is build-only so no runtime decode cost. State machine lives in src/ui/tray.rs. Syncing -> not-Syncing snaps the rotation cursor back to frame 0 (frame 0 is byte-identical to the idle bitmap so the swap is invisible). Long main-loop stalls skip frames rather than playing catch-up. Server-reachability is checked every 30s via the existing ImmichClient::ping(); uploads-in-flight win over an Offline display (uploads imply reachability). Tests: 9 new unit tests covering frame-set integrity (12 frames, all correct size, frame 0 == idle), state machine transitions (Syncing exit detection across Idle/Offline/Syncing-to-Syncing), and offline visual differentiation. Binary size: 11.96 MB release (vs 12.01 MB baseline on development). Embedded .ico is ~74 KB; the 14 raw RGBA blobs are ~4 KB each. Well inside the < 200 KB budget. Closes #38 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Rolls up the 0.1.8 -> 0.2.0 minor release: - feat(#3): per-folder include/exclude glob patterns (PR #31) - feat(#4): watcher health monitoring + auto-restart (PR #35) - feat(#12): configurable update source with channel + tag pin (PR #32) - feat(#26): ignore online cloud-placeholder files + path/size/mtime dedup (PR #33) - feat(#38): brand icon with rotating tray animation + offline state (PR #40) - refactor(#20, #29): Windows-standard install layout + Apps & Features uninstall entry (PR #36) - (#9 clippy gate + dead-code cleanup may also be included) - Plus infra: stable artifact headers, slim CI, fmt + clippy gating, artifact-regen workflow rewrite, auto-merge sweep Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor: clean up dead code and gate clippy in CI (#9) Delete fully-orphaned modules (api/auth.rs, platform/drives.rs, watch/device.rs) and the unused public-API surface that had accumulated across them (UserInfo, ServerInfo + server_info, AutostartError variants that nothing constructed, FirstRun/Settings unit structs, UpdateError variants, etc.). Drop the long-dead config helpers from the DB layer (get/set_config_value, requeue_failed, purge_completed) and the matching tests. Box the toml error variants in ConfigError so the whole call chain stops tripping clippy::result_large_err (~50 sites collapse to zero). Keep test- only or state-machine-completing items with #[cfg_attr(not(test), allow(dead_code))] / #[allow(dead_code)] plus an inline note that explains why the symbol stays. Sweep the mechanical clippy lints: is_some_and over map_or, is_multiple_of, io::Error::other, div_ceil, sort_by_key, while-let-loop, redundant borrow/closure, derive Default, collapsed-if, doc-list indent. Flip the CI clippy step from informational (continue-on-error: true with -W clippy::all) to gating (-D warnings). Verified clean against cargo build --release, cargo clippy --all-targets -- -D warnings, cargo fmt --all -- --check, and cargo test --locked (95 passed). Closes #9 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: regenerate SBOM and STRUCTURE --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Promotes the 0.2.0 wave to `release`. Supersedes #43, which was blocked by an unresolvable merge conflict on auto-generated artifacts (SBOM.md, STRUCTURE.md).
The conflict was a chicken-and-egg between release's stale Apr-26 artifact regen (`acdc566`) and development's post-#34 stable-headers format. Trying to back-merge into development twice (#44, #45) lost the ancestor link to squash both times. This PR sidesteps that: branched off release, merged development in locally, resolved artifacts in dev's favor.
Targets release, so the org Release Branch Protection ruleset forces merge-commit — no squash footgun this time.
Contents
Same 19-commit wave as #43:
Features: #3, #4, #12, #26, #38
Fixes: #16, #17, #18
Refactors: #8, #9, #19, #20, #29, #34, register check_runs after artifact-regen push
Improvements: #22, #30, #41 (bump to 0.2.0)
Chore: #37, plus #44/#45 back-merge attempts that produced the current artifact state
Test plan