-----
<!-- 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
- 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.
Formula install-step paths now serialise only a base that was explicitly
specified. RuboCop prevents relative official-tap paths from relying on the
current working directory.
Run structured-only API post-installs from the current JSON data so old
formula snapshots embedded in bottles cannot restore the removed default.
Keep using bottle snapshots for formulae that still have Ruby hooks.
Two forms were accepted at parse time that `cargo install` cannot act
on, so the failure surfaced later and less clearly.
`--git` takes a URL and rejects an scp-style remote outright, naming
the `ssh://` form to use instead, so require a scheme rather than also
accepting anything ending in `.git`.
Only a `branch`, `tag` or `rev` query is restored as a `cargo install`
flag. Any other query was accepted and then silently dropped, which
left the installed origin unequal to the `Brewfile` entry and so made
`brew bundle check` report the crate missing on every run.
`cargo "name"` could only install from crates.io. Accept a `source:`
option naming a git URL or a local path, mirroring the `uv` extension,
and install with `cargo install --git` or `cargo install --path`.
`cargo install --list` reports the origin of anything not installed
from a registry, so dumped Brewfiles round-trip. The resolved commit is
dropped, since a dumped entry has to compare equal to a hand-written
one, while a branch, tag or revision chosen at install time is carried
in the URL query and restored with `--branch`, `--tag` or `--rev`.