-----
<!-- Only tick a checkbox once you've done it; honesty keeps reviews smooth. -->
<!-- Tick with [x] before creating, or click the boxes afterwards. -->
<!-- Don't delete these checkboxes or this pull request is closed automatically. -->
- [x] Have you followed our [Contributing](https://github.com/Homebrew/brew/blob/HEAD/CONTRIBUTING.md) guidelines?
- [x] Have you checked for other open [Pull Requests](https://github.com/Homebrew/brew/pulls) for the same change?
- [x] Have you explained what your changes do? Performance claims (e.g. "this is faster") must include [Hyperfine](https://github.com/sharkdp/hyperfine) benchmarks.
- [x] Have you explained why you'd like these changes included, not just what they do?
- [ ] For bug fixes, have you given step-by-step `brew` commands to reproduce the bug?
- [ ] Have you written new tests (excluding integration tests)? [Here's an example](https://github.com/Homebrew/brew/blob/HEAD/Library/Homebrew/test/PATH_spec.rb).
- [x] Have you successfully run `brew lgtm` (style, typechecking and tests) locally?
-----
- [ ] AI was used to generate or assist with generating this PR.
<!-- If ticked, explain below how AI was used and how you verified the changes. Non-maintainers may only have one AI-assisted PR open at a time. See https://docs.brew.sh/Responsible-AI-Usage for guidance. -->
-----
License tag for OCI image limit 256 chars by documentation but it is actually failed with 256 chars. I have tested my own private repo for this and 255 is fine to use.
`mesa` is failed because of this,
- https://github.com/Homebrew/homebrew-core/pull/294670
When connected via SSH, `launchctl list <label>` only searches the
system domain, so it won't find services loaded in the `gui/<uid>`
domain. This caused `Utils::Service.running?` to incorrectly return
false for running services, which in turn made `brew upgrade` print
"brew services start" instead of the correct "brew services restart".
Consolidate the "is this service running?" logic into a single source
of truth: `Homebrew::Services::System.launchctl_service_running?`.
This iterates `candidate_domain_targets` to try domain-qualified
`launchctl print <domain>/<label>` before falling back to a bare
`launchctl list <label>`. Both `Utils::Service.running?` and
`FormulaWrapper#loaded?` now use this method.
Refactor `FormulaWrapper#status_output_success_type` to also iterate
`candidate_domain_targets` instead of only trying the single
`domain_target`, which over SSH returns `user/<euid>` and misses
services loaded in the `gui/<uid>` domain.
- reject mixing formula install hooks in every tap
- autocorrect legacy step methods and keywords
- retain stable serialised API values for compatibility
- document canonical Formula and Cask step authoring
- remove the resolved Cask sandbox deprecation reminder
- Discover CPython wheels already packaged in each keg.
- Expand PyPy bootstrap archives packaged in `libexec`.
- Resolve dependency paths without loading formula source.
- Validate helper executables before attempting to run them.
- Enforce source independence with RuboCop and API-loaded tests.
- Keep the internal JSON API unchanged and minimal.
- Ignore intentional bootstrap constant reassignments, RBI declarations
and OS-specific method overrides.
- Allow valid names unavailable to the project-only index.
- Retain absolute core constants where inherited lookup can make the
indexed autocorrection unsafe.
Also updates rubocop-sorbet (0.13.2 -> 0.14.0) and json (2.21.1 ->
2.21.2), which rubocop depends on.
Two suppressions can go away thanks to bug fixes in this release:
- rubocop/rubocop#15438 and rubocop/rubocop#15442 stop
`Style/ArrayIntersect` firing when the `include?` receiver in a block
is not an array literal, so the cop is re-enabled. It still cannot
guarantee the *outer* receiver is an `Array`, and in
`cask/artifact/abstract_uninstall.rb` that receiver is the `Enumerator`
from `Pathname#each_filename`, which has no `intersect?`. Convert with
`to_a` there rather than taking the autocorrect verbatim.
- rubocop/rubocop#15452 fixes the `Layout/HashAlignment` false positive on
multi-line hash keys, so the two `delegate` disable comments in
`formula.rb` are dead and removed.
One suppression is added: rubocop/rubocop#15493 makes
`Style/IfUnlessModifier` respect `Layout/LineLength`'s exemptions rather
than its `Max`. Several of our exemption patterns are unescaped regexes
(`"#{version."` matches `#{version}`, `#{version_text}` and
`#{version_info[...]}`), so the cop demanded modifier form for statements
that then ran to 179 characters. Disable the cop. Reported upstream as
rubocop/rubocop#15531.
rubocop-sorbet 0.14.0 widens `Sorbet/SetterReturnType` to cover setters
taking splat and keyword arguments, so several `depends_on` and ENV
setters switch to `.void`. Under `HOMEBREW_SORBET_RUNTIME` a `.void`
method returns the sentinel `T::Private::Types::Void::VOID`, which breaks
the two callers that consumed a setter's return value. Sorbet does not
catch either statically:
- `DependsOn#load` stored the result of `send(:"#{key}=", ...)` into the
delegated hash, so the whole `depends_on` stanza became `VOID`. Read the
value back through the matching reader instead.
- `Superenv#cc=` assigned `super` to `HOMEBREW_CC`, raising `TypeError:
no implicit conversion of Module into String`. Assign from `val`.
Drop `extend/ENV/shared.rbi`, which existed to widen `[]=` to accept
`Pathname` and `PATH`. Without it `[]=` resolves to Sorbet's own
`ENVClass#[]=`, which takes `T.nilable(String)`, so the ENV assignments
convert explicitly with `to_s`/`&.to_s`. Both `Pathname` and `PATH`
define `to_str`, so Ruby was already converting implicitly and behaviour
is unchanged.
The remaining changes are new offenses in this release:
- `Lint/UselessAssignment` (rubocop/rubocop#12269) catches the
`root_url = root_url =` workaround in `dev-cmd/tap-new.rb`. The Ruby
`assigned but unused variable` warning it silenced no longer fires on
our vendored Ruby, so drop it.
- `Style/RedundantParentheses` (rubocop/rubocop#15472) and
`Layout/MultilineMethodCallIndentation` autocorrections.
The redundant `T.let` on `GitHub::API::ERRORS` is also dropped.
Claude-Session: https://claude.ai/code/session_01AdSQcU5MmY4VWiFdfrPeu2
A crate cargo reports as installed from a local origin is still dumped
as a registry crate, but without warning about the origin that could
not be expressed, which is noise for anyone who is content with the
crate they have.
- Run each complete cask step block in one isolated subprocess and all
generated completions in another phase-scoped sandbox.
- Share sandbox selection, fork fallback, install-hook rules and child
error reporting with formula build, post-install and test processes.
- Restrict home, network and filesystem access while preserving `brew`
and supporting explicit command write paths.
- Keep JSON payloads compact and independent of cask Ruby files.
- Remove the completed official-tap migration plan.
Neither a local path nor a file:// URL resolves on another machine, so
both are rejected when the Brewfile is parsed. A crate cargo reports as
installed from one is dumped as a registry crate rather than dropped,
with a warning naming the origin that could not be expressed.