Skip to content

Releases: albovsky/lethen

lethen 3.10.0

Choose a tag to compare

@github-actions github-actions released this 02 Oct 01:47
d7dec6c

lethen 3.10.0

Lethen 3.10.0 tells you how sure it is about each result and why it reports it, explains any declaration on request, and removes classes of false positives measured on a corpus of real projects. It requires Swift 6.3 (Xcode 26.4) or later, like 3.9.0.

Breaking changes

  • Managed SwiftPM scans reuse the previous build when Lethen can verify its index, and clean and rebuild when they cannot. --clean-build restores a clean build on every scan.
  • Lethen runs xcodebuild, swift, and bazel directly instead of through bash -c. Quotes and $VARIABLES in build_arguments, --build-arguments, and xcode_list_arguments are no longer interpreted by a shell: write each argument separately, such as --scratch-path and /tmp/Build Space. Lethen warns about build arguments still wrapped in quotes.
  • Bazel scans need the periphery module override in MODULE.bazel to be the same Lethen version as the binary, on Bazel 7.1 or later. Update the override's tag to 3.10.0 together with the binary.
  • lethen scan --bazel rejects --skip-build and --index-store-path, which it used to ignore. Scan an existing index store with --generic-project-config and --index-store-path.

Highlights

  • Confidence and reasons. Every result is certain or likely, with a one-sentence reason. --min-confidence certain reports only certain results, so --strict can fail CI only on findings Lethen is sure about. JSON and CSV output carry both fields.
  • lethen explain <name|usr> shows why a declaration is reported, the shortest chain of references that keeps it used, or the rule or comment that retains it.
  • Objective-C uses. Swift declarations used from .m files or headers are no longer reported as unused without --retain-objc-accessible.
  • Build configurations. --configurations debug release (SwiftPM) or --configurations Debug Release (Xcode) builds and scans each configuration together, so code used only behind #if DEBUG is kept. --skip-build --configurations Debug Release rescans an Xcode project from the indexes of Lethen's last completed build of each configuration, and stops with an error naming a configuration that has none; Xcode's own DerivedData index is never used in its place. Xcode scans name the configuration they compile and warn when the scheme runs with another.
  • Faster rescans. A SwiftPM rescan of Lethen with nothing changed takes 5.3 s instead of 33.8 s. --stats prints phase timings and throughput, and long builds print progress.
  • Integrations. The repository is a GitHub Action (uses: albovsky/lethen@3.10.0) that installs a verified release binary and annotates pull requests. The package ships a LethenPlugin command plugin for SwiftPM and Xcode, and mint install albovsky/lethen works.
  • Fewer false positives. Parameters of retained public API, of functions passed as values, and of witnesses of hidden standard library requirements; metatype parameters that select a generic type; result builder methods; property wrapper initializers; NSDocument classes named in Info.plist; and stored properties of encoded Encodable structs are no longer reported. On the precision corpus, sampled precision rose from 73 % to 84.0 %.
  • New findings. Enum cases that are matched but never constructed, unused subscript parameters, unused parameters of stored closures, and types used only by their own macro expansion are reported. --retain-public-targets keeps the public API of selected modules only.

Fixes

  • A project path, scheme name, Bazel filter, or build argument can no longer run shell commands during a scan.
  • lethen scan --bazel writes its generated package to a private directory in the workspace's Bazel output base instead of the shared /var/tmp/periphery_bazel.
  • The github-actions format escapes annotation fields, so a file name or message cannot inject workflow commands.
  • Linux tarballs link libxml2 statically and run on Ubuntu 26.04, including the swift:6.4 image.
  • Scans of an index with several versions of a file give the same results every run, and redundant conformance locations are listed in a fixed order.
  • Xcode scans lock the DerivedData directories they use, so concurrent scans wait for each other, and they rebuild a directory from clean unless its last build completed with the same project, schemes, configuration, and build arguments. Every directory is rebuilt once after upgrading.
  • Xcode builds with different build arguments no longer share one DerivedData directory, and swift package describe no longer waits forever on another SwiftPM process's lock.

The full list is in CHANGELOG.md.

Verification and limits

The release commit must pass the Required checks gate: the Swift 6.4 / Xcode 27 baseline (.github/scripts/verify-swift-6.4.sh), the macOS 6.3 / Xcode 26.4 job, Linux 6.3 and 6.4, Bazel on macOS and Linux, and the Linux release tarballs smoke-tested on Ubuntu 22.04, 24.04, and 26.04 images.

The verified combinations table still lists the 3.9.0 binaries and release run; it has no 3.10.0 row, so nothing in it is evidence for this release. The precision scorecard records how precision is sampled; its target is 95 %. Intel source builds are not tested in CI.

Platforms and installation

Platforms: macOS release binaries and Homebrew are Apple silicon only (macOS 15 or later). Intel Macs build from source with a supported Xcode 26.x; see the platform policy. Linux x86_64 and aarch64 can use the release tarballs, which need glibc 2.35 or later and a Swift 6.3 or newer toolchain, or build from source.

Install with brew install albovsky/tap/lethen, or download the arm64 zip and checksums. Xcode or the Command Line Tools must be installed. On Linux, download lethen-3.10.0-linux-x86_64.tar.gz or lethen-3.10.0-linux-aarch64.tar.gz. The installation guide includes checksum verification; the README shows how to install a Linux tarball.

Source installation

Select a full Xcode installation on macOS, for example sudo xcode-select -s /Applications/Xcode.app/Contents/Developer, then:

git clone --branch 3.10.0 --depth 1 https://github.com/albovsky/lethen.git
cd lethen
swift build -c release --product lethen
lethen_bin_dir="$(swift build -c release --show-bin-path)"
"$lethen_bin_dir/lethen" version
mkdir -p "$HOME/.local/bin"
install -m 755 "$lethen_bin_dir/lethen" "$HOME/.local/bin/lethen"
export PATH="$HOME/.local/bin:$PATH"
lethen scan --project-root /path/to/your/project --disable-update-check

Keep the PATH export in your shell profile. Stable builds are offered stable releases by the optional update checker.

lethen 3.9.0

Choose a tag to compare

@github-actions github-actions released this 26 Sep 06:21
878ea7c

lethen 3.9.0

Lethen 3.9.0 requires Swift 6.3 (Xcode 26.4) or later and is the first release with Linux tarballs. Signed, notarized Apple silicon binaries and Homebrew installation continue alongside source builds.

Lethen supports the current Xcode major and the final release of the previous major, the Swift toolchains they ship, the same Swift minors on Linux through the official containers, and the current and previous Bazel LTS. Swift 6.1 and 6.2 are no longer supported; use a source build of 3.8.1 with them.

Changes since 3.8.1

  • Breaking: the minimum supported Swift version is 6.3 (Xcode 26.4). macOS release binaries and the Homebrew formula are Apple silicon only; Intel Macs build from source within the supported Xcode 26 window.
  • Linux tarballs for x86_64 and aarch64, for glibc 2.35 or later and Swift 6.3 or newer. The tarball's bin/lethen loads the indexing library of the active swiftc, including swiftly installs.
  • The update check no longer crashes the process on Linux with Swift 6.4.
  • Xcode scans of two or more schemes reuse one DerivedData directory, so builds are incremental again and orphaned directories no longer accumulate. Caches left under the old names are not migrated; lethen clear-cache removes them.
  • The csv format quotes fields that contain commas, quotes, or line breaks, so every row keeps eight columns. The json, codeclimate, and gitlab-codequality formats write keys in sorted order, so identical scans produce byte-identical output.
  • The mise build task produces only a stripped arm64 binary, and the benchmark runs the executable the build task returns.

The full list is in CHANGELOG.md.

Verification and limits

The release commit must pass the Required checks gate, which includes the Swift 6.4 / Xcode 27 baseline (.github/scripts/verify-swift-6.4.sh: the full suite, clean, warm, and native fixture scan comparisons, and a strict self-scan), the macOS 6.3 / Xcode 26.4 job, Linux 6.3 and 6.4, Bazel 9.x on macOS and Linux, and the Linux release tarballs built with Swift 6.3 and smoke-tested with the Swift 6.3 and 6.4 images and a swiftly toolchain on x86_64 and aarch64. The GitHub release records the final commit and its CI run.

The verified combinations separate toolchain, project type, host, and evidence. Intel source builds are not tested in CI. Running a Swift 6.4-built binary or the release binary on macOS 15 is unverified; release binaries are built with Xcode 26.4. A Swift release that moves to a newer LLVM needs a new Lethen release for the Linux tarballs.

Platforms and installation

Platforms: macOS release binaries and Homebrew are Apple silicon only (macOS 15 or later). Intel Macs must build from source with supported Xcode 26.x; Xcode 27 cannot link lethen for Intel. See the platform policy for the support window. Linux x86_64 and aarch64 can use the release tarballs or build from source.

Install with brew install albovsky/tap/lethen, or download the arm64 zip and checksums. Xcode or the Command Line Tools must be installed. On Linux, download lethen-3.9.0-linux-x86_64.tar.gz or lethen-3.9.0-linux-aarch64.tar.gz. The installation guide includes checksum verification and zip installation commands; the README shows how to install a Linux tarball.

Source installation

Select a full Xcode installation on macOS, for example sudo xcode-select -s /Applications/Xcode.app/Contents/Developer, then:

git clone --branch 3.9.0 --depth 1 https://github.com/albovsky/lethen.git
cd lethen
swift build -c release --product lethen
lethen_bin_dir="$(swift build -c release --show-bin-path)"
"$lethen_bin_dir/lethen" version
mkdir -p "$HOME/.local/bin"
install -m 755 "$lethen_bin_dir/lethen" "$HOME/.local/bin/lethen"
export PATH="$HOME/.local/bin:$PATH"
lethen scan --project-root /path/to/your/project --disable-update-check

Keep the PATH export in your shell profile. Stable builds are offered stable releases by the optional update checker.

lethen 3.8.1

Choose a tag to compare

@albovsky albovsky released this 25 Sep 22:15
2188620

lethen 3.8.1

The first lethen release. Lethen is an independent, MIT-licensed fork of Periphery 3.8.0. Distribution is source-only. Tags through 3.8.0 retain upstream Periphery history and attribution; they are not lethen releases.

This is the last release that supports Swift 6.1 and 6.2. Lethen supports the current Xcode major and the final release of the previous major, the Swift toolchains they ship, the same Swift minors on Linux through the official containers, and the current and previous Bazel LTS; 3.9.0 applies that policy and requires Swift 6.3 (Xcode 26.4).

Changes since 3.8.0

  • Reliable scanning on Swift 6.4 / Xcode 27: managed SwiftPM scans resolve the active binary directory and enable indexing explicitly, including release builds; a missing store fails with an actionable error; existing products are rebuilt to rule out a stale index. Use --skip-build with --index-store-path for an index you know is current.
  • Analysis fixes reproduced during a private-project audit: generated SwiftUI state projections are connected to their source property, and properties read only by synthesized Equatable and Hashable conformances are no longer reported as assign-only when a value reaches a comparison. Top-level code in main.swift no longer attributes its references to a nearby declaration.
  • Crash paths are reported errors: the guided setup with no detectable project or with input that ends, --project on Linux, a missing or unparseable Swift toolchain, and errors from concurrent indexing jobs. The Linux update-check teardown crash is fixed.
  • Lethen naming in user-facing text, the guided setup, the bug report template, and the mise tasks; the historical upstream guide is stripped of commercial and sponsor material. Existing .periphery.yml files, // periphery: comment commands, the PeripheryKit library, and the periphery Bazel module remain supported.
  • The update checker reads lethen's releases. Bazel mode warns when MODULE.bazel has no source override for periphery, and lethen scan --setup prints the snippet for the installed version.

The full list is in CHANGELOG.md.

Verification and limits

The release commit must pass the Required checks gate, which includes the Swift 6.4 / Xcode 27 baseline (.github/scripts/verify-swift-6.4.sh: the full suite, clean, warm, and native fixture scan comparisons, and a strict self-scan), the macOS 6.3 / Xcode 26.4 job, Linux 6.1 to 6.3, and Bazel 9.x. The GitHub release records the final commit and its CI run.

The private-project audit reviewed a deterministic sample of 30 findings, fixed seven false positives, and verified 11 retained controls. It does not establish that every finding is correct or every unused declaration is found. Assign-only storage may intentionally control object lifetime; package APIs may have consumers outside the scanned scheme. Synthesized-equality modeling is conservative.

The verified combinations separate toolchain, project type, host, and evidence. Intel macOS, universal or signed binaries, and running a Swift 6.4-built binary on macOS 15 are unverified.

Source installation

Select a full Xcode installation on macOS, for example sudo xcode-select -s /Applications/Xcode.app/Contents/Developer, then:

git clone --branch 3.8.1 --depth 1 https://github.com/albovsky/lethen.git
cd lethen
swift build -c release --product lethen
lethen_bin_dir="$(swift build -c release --show-bin-path)"
"$lethen_bin_dir/lethen" version
mkdir -p "$HOME/.local/bin"
install -m 755 "$lethen_bin_dir/lethen" "$HOME/.local/bin/lethen"
export PATH="$HOME/.local/bin:$PATH"
lethen scan --project-root /path/to/your/project --disable-update-check

Keep the PATH export in your shell profile. Stable builds are offered stable releases by the optional update checker. Binary signing and publishing automation remains disabled.

Release evidence

  • Tag 3.8.1 points at commit 218862090084e7c6f34939c92f2221d23fd89a2d (the squash merge of #17 on master, after #16).
  • CI on that commit: run 36193249308, master profile (Swift 6.4 / Xcode 27 baseline script, macOS 6.3, 6.2 and 6.1, Linux 6.1 to 6.3, Bazel 8.x and 9.x, Lint, Required checks), all successful.
  • Fresh public-tag gates on Apple Swift 6.4 (swiftlang-6.4.0.34.1) / Xcode 27.0, arm64 macOS 27.0: git clone --branch 3.8.1 --depth 1, swift build -c release --product lethen succeeded, lethen version printed 3.8.1, a scan of Tests/Fixtures with the release binary completed with 435 findings, and the binary installed to a separate directory runs lethen scan --help.

lethen 3.8.1-dev.1

lethen 3.8.1-dev.1 Pre-release
Pre-release

Choose a tag to compare

@albovsky albovsky released this 19 Sep 20:19

lethen 3.8.1-dev.1

The first lethen development prerelease establishes reliable scanning on Swift 6.4 / Xcode 27. Distribution is source-only. Tags through 3.8.0 retain upstream Periphery history and attribution; they are not lethen releases.

Changes

  • Resolve the active SwiftPM binary directory and explicitly enable indexing, including release builds. Custom scratch roots, default/native builds, and explicit external stores remain distinct; missing stores fail with actionable errors.
  • Restore the working directory after thrown errors and report fixture setup/indexing failures through XCTest instead of crashing.
  • Update the four incompatible iOS fixture settings to 15.0 while preserving the other targets and assertions.
  • Connect generated SwiftUI state projections to source properties and model missing synthesized equality reads. Explicit custom equality and unused controls remain covered.
  • Require the exact-commit Swift 6.4 / Xcode 27 CI check, retaining the existing stable macOS/Linux and Bazel jobs.

Existing .periphery.yml settings, // periphery:ignore comments, library names, and attribution are preserved. No broad dependency upgrade or baseline suppression was used.

Verification and limits

The verified baseline passes 322 tests across all four targets, with no failures or compatibility skips. Clean, warm reused-index (--skip-build), and native fixture scans agree on 423 findings; strict clean self-scan passes. All 12 non-optional CI jobs pass on the code baseline, including macOS/Linux Swift 6.1–6.3 and Bazel 8.x/9.x. The exact versioned commit passed its final CI gate; evidence is recorded below.

The private-project audit reviewed a deterministic sample of 30 findings, fixed seven sampled false positives, verified 11 retained controls, and passed 60 tests after temporary removals. Restored clean/warm scans agree on 154 findings. This sample does not establish that every finding is correct or every unused declaration is found. Assign-only storage may intentionally control object lifetime or support external tooling; package APIs may have consumers outside the scanned scheme.

Automatic synthesized-equality modeling is conservative and relies on indexed source callers and visible custom witnesses. Broader --retain-equatable-properties / --retain-hashable-properties options remain available. Externally built automatic swiftbuild indexes require explicit --index-store-path; --skip-build discovery expects explicitly enabled indexes. Managed SwiftPM discovery builds rebuild existing products to prevent stale stores after external unindexed builds. This adds build time; use --skip-build only when the index is known to be current.

The compatibility table separates toolchain, project/build engine, host, and evidence. The local source-install baseline is Apple Swift 6.4 / Xcode 27.0 on arm64 macOS 27. Intel macOS, universal/signed binaries, and running a Swift 6.4-built binary on macOS 15 are unverified. The package minimum alone does not prove runtime compatibility. Snapshot jobs are not support promises.

Source installation

Select a full Xcode installation on macOS, for example:

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

Then install the explicit tag:

git clone --branch 3.8.1-dev.1 --depth 1 https://github.com/albovsky/lethen.git
cd lethen
swift build -c release --product lethen
lethen_bin_dir="$(swift build -c release --show-bin-path)"
"$lethen_bin_dir/lethen" version
"$lethen_bin_dir/lethen" scan --help
mkdir -p "$HOME/.local/bin"
install -m 755 "$lethen_bin_dir/lethen" "$HOME/.local/bin/lethen"
export PATH="$HOME/.local/bin:$PATH"
lethen scan --project-root /path/to/your/project --disable-update-check

Keep the PATH export in your shell profile. Build paths are queried because swiftbuild and native layouts differ. The optional update checker uses GitHub's stable /releases/latest endpoint and does not discover prereleases; install development tags manually.

Release gates include a clean detached candidate build, a real fixture scan with the installed release binary, exact-commit CI, and a fresh public-tag installation. The GitHub release records the final commit, CI link, and installation outcome. Binary signing/publishing automation remains disabled.

Final release evidence

  • Verified commit and annotated tag target: 04c6965c8a1f99d34a2ee71da20b0dbc6df4b031.
  • All 12 non-optional jobs passed in the final matrix run. The required exact-commit Xcode 27 check records 322 passing tests, 423 matching clean/reused/native findings, strict self-scan, and version 3.8.1-dev.1. Its swift-6.4-evidence artifact contains the logs and full comparison sets.
  • A separate full local suite passed all 322 tests on that exact commit. Final analysis preserved all 154 restored private-project findings.
  • A clean detached candidate and a fresh clone of the public 3.8.1-dev.1 tag each built with swift build -c release --product lethen. Each executable was located through --show-bin-path, checked with version and scan --help, installed, and used for a real default fixture scan matching all 423 findings. External fixture locations were compared by absolute identity across checkout depths; no findings were discarded.
  • Both installation checks ran on arm64 macOS 27.0 (26A428), Xcode 27.0 (27A266a), Apple Swift 6.4 (swiftlang-6.4.0.34.1). Public-tag release binary SHA-256: 3d311da45fc2f36898cebd1f1322c36f1c645777e6f23cd8be3b75f15a29d702. This is verification metadata, not a distributed binary asset.
  • The optional Linux main-snapshot job failed. Snapshot jobs are outside the release gate and support claims.
  • Final review was performed locally by the author as required by the implementation plan; no independent review is claimed. The pull request remains available for review.