vcswatch reports that
this package seems to have a new changelog entry (version
4.2.3-1, distribution
UNRELEASED) and new commits
in its VCS. You should consider whether it's time to make
an upload.
Here are the relevant commit messages:
commit 6506729ae02ff150a11f351acff661d42cdd69cf
Merge: ecc2059 91db7e9
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Fri Oct 23 23:04:04 2026 +0500
Merge branch 'mr/build-fixes' into 'master'
Build and test fixes for 4.2.3-1
See merge request debian/bear!3
commit ecc20593d4102df13f132fe1597794c718978261
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Fri Oct 23 22:51:40 2026 +0500
Add salsa ci.
commit 91db7e9a3ba86154bcba71df562b3d4af0d3cae0
Author: Charles <boxabc1@proton.me>
Date: Fri Oct 23 16:54:29 2026 +0100
d/rules: install libexec.so non-executable
commit 4fafbdc78cd5d9b3aa30334c4370a8985c5da01f
Author: Charles <boxabc1@proton.me>
Date: Fri Oct 23 16:54:29 2026 +0100
d/tests/smoke: accept relative file entries (4.x records paths as-is)
commit 3ae2bc9c56a537204f296966d81162519cd1114d
Author: Charles <boxabc1@proton.me>
Date: Fri Oct 23 16:47:27 2026 +0100
d/control: point Vcs-* at debian/bear
commit 1ecd57efd3c3f890b2776bd6dd7e12d5a0a001e7
Author: Charles <boxabc1@proton.me>
Date: Fri Oct 23 16:47:27 2026 +0100
d/rules: pass CPPFLAGS to the cc crate
commit fd9f867979a966c27803dc6c7a7f8160822649a5
Author: Charles <boxabc1@proton.me>
Date: Fri Oct 23 16:47:27 2026 +0100
d/rules: run the signal (exit_codes) tests serially
commit 45dec03b4f89652022b3d60ff432c73f945ea57a
Author: Charles <boxabc1@proton.me>
Date: Fri Oct 23 16:46:38 2026 +0100
d/control: Build-Depend on procps for kill(1) in the signal tests
commit 205ce9ad6fb1e4070552e66df57d5e570a0d1c13
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Fri Oct 23 00:05:26 2026 +0500
Update changelog for new release.
commit 4f8629f4d765343a1da81e91243fe7e8793a6936
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Fri Oct 23 00:04:54 2026 +0500
Update bear install files.
commit 0119e62f1ee2f7df93b2e5da953c772eaee76817
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Fri Oct 23 00:04:14 2026 +0500
Update rules to build for Rust.
commit 77cb7252ce467cbda5c38283c14f55e919598ca2
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Fri Oct 23 00:03:28 2026 +0500
Update patch of not-installed.
commit 6ef37092b7661805d643ab0ab99594e8d7665b87
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Fri Oct 23 00:02:46 2026 +0500
Remove old lib install.
commit f07b33fc724e4b121229a6b7a680659450bb2f27
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Thu Oct 22 23:58:27 2026 +0500
Updates:
* Rust dependencies.
* New maintainers.
* Bump versions of debhelper-compact and Standards-Version.
* Remove Priority: optional.
commit 64791d0ae7a08fb9d5e852cd4a7f916a03139263
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Thu Oct 22 23:57:24 2026 +0500
Update debian package maintainers.
commit edc1cc5a2ef9f041f165e685e4a3c0b0ad48a70c
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Thu Oct 22 23:56:22 2026 +0500
Update d/watch file to version 5.
commit 8ffd6fc95780ad6dba119cb528f23aa6b258bdc0
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Thu Oct 22 23:55:49 2026 +0500
Add patch to relax dependency.
commit a983c14b3d5a1499d1cd31b53f1e332e9844b017
Merge: c649aa9 ec59379
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Thu Oct 22 23:24:06 2026 +0500
Update upstream source from tag 'upstream/4.2.3'
Update to upstream version '4.2.3'
with Debian dir 8c7d4e8a0519000d77dc476a1dd5b576ca0da264
commit ec59379c395f3983b1d97f63eb98e80a1f1da589
Merge: 7233aa0 9084d67
Author: Syed Shahrukh Hussain <syed.shahrukh@ossrevival.org>
Date: Thu Oct 22 23:24:04 2026 +0500
New upstream version 4.2.3
commit 9084d67616da9c995fbafad89ba485bc67646d1a
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Wed Oct 14 07:05:49 2026 +0000
docs(man): date the page for the 4.2.3 release
The page still carried the date of the 4.2.2 release. Set it to the
release date and regenerate; the roff diff is the date line only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 108379b77b3be06336ce55b74efc939bcdbdd43b
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Wed Oct 14 06:50:59 2026 +0000
chore: replace codespell with typos for spell checking
typos is a single Rust binary, so the devcontainer can install it the
same way as mdbook and it can run locally as a pre-commit check. CI and
the devcontainer pin the same version.
_typos.toml carries over the codespell skip list and allowed words, plus
the new false positives typos reports (HPE, -Iinclude, config.mak, ...).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit e486f0b03eff36f41bc02674444500fb1c45eb77
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Wed Oct 14 06:30:54 2026 +0000
chore: update dependencies
Refresh Cargo.lock to the latest semver-compatible versions before
the release. Notable: cc 1.8 (builds the preload shim), proptest 1.12
(dev only), serde-saphyr 1.3. encoding_rs 0.8.42 brings five small
crates into the shipped binaries via serde-saphyr. serde-saphyr 2.0
is left for a later cycle.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 5b4638312a0fd115f231a4027bee9d07a3799a97
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Wed Oct 14 05:48:27 2026 +0000
docs(requirements): errors name the file, the action and the cause
Diagnostics before the build used Rust's default `Error: ...` output
instead of the `bear: error:` format, and many messages stacked internal
layer names ("Failed to create consumer", "Serialization error",
"Generic IO error") around the real cause.
The format now covers every diagnostic, startup errors included, with
command-line usage errors left to the usage text. An error about a file
names it once with the action and the cause, and no internal names.
Requirement: cli-diagnostic-format
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 55b257a1255853cbc8e3c602d7eb8f2d9fe588b4
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 14:21:33 2026 +0000
fix(output): publish output files all or nothing
A build command that could not start left an empty compile_commands.tmp
behind (#718). The temp file was created before the build, and on a
build error the interceptor returned without joining its threads, so
nothing renamed or removed it.
Output files are now a transaction. AtomicFile creates the temp file up
front, so a bad destination still fails before the build. The
coordinator commits it only when the run ends without an error of
Bear's own. Dropping it rolls back. A build that runs and fails still
publishes what was captured.
- The events file follows the same rule.
- A failed replay no longer replaces a good database.
- The temp file has a random, hidden name next to the output, so it
cannot collide with an output named *.tmp or with another run.
- An existing non-regular output such as /dev/null is written in place
instead of being replaced.
Requirement: output-atomic-write
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit dc02b30e359a5697e2237e0a0706d2d205674756
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 12:31:41 2026 +0000
feat(compilers): recognize Intel icx-cl
icx-cl is Intel oneAPI's MSVC-compatible driver ("On Windows, icx-cl
provides Microsoft Visual C++ compatibility", oneAPI programming guide
2025.1). It takes `/` and `-` options alike, so a new intel_cl family
extends clang_cl and sets slash_prefix and msvc response files, which
extends does not carry over. Intel's /Q options found glue their value
(`/Qopenmp-targets:<arch>`), so no flags of its own.
Requirement: recognition-compiler-names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 081b762c935a7b4c69cb03f8426fca60d2902b79
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 12:30:43 2026 +0000
test(semantic): a configured family beats another family's name match
A configured `as:` is the user's fix when two vendors ship the same
name (f95 is gcc's, other Fortran vendors ship one too). Recognition
already checks configured hints first, but no test pinned it for a
name another family claims; the existing hint tests use names nothing
else matches. State the contract and pin it with f95 mapped to flang,
by full path and by bare filename.
Requirement: recognition-compiler-names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 6be673a8b0180396309841d8dac15b3bd13c1f8b
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 12:30:11 2026 +0000
docs(requirements): list zig as deliberately not recognized
zig is a subcommand dispatcher like swift: `zig cc` picks the compiler
by subcommand, not by executable name. A research sweep ranked it high,
so without a row it will be proposed again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit c769c89cfbaa1c148bc33d103b3dd84c0c16fad2
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 11:37:18 2026 +0000
feat(compilers): recognize Embarcadero C++Builder bcc64x, bcc64, bcc32x
These C++Builder drivers are Clang-based with Clang-style options, so
a new embarcadero family extends clang. The RAD Studio help lists no
vendor-only option with a separate value; the -t target switches are
single tokens. bcc32c and the classic bcc32 stay out.
Requirement: recognition-compiler-names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 55a5aae21e86955d80c4df040475c9655b3e1acd
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 11:37:18 2026 +0000
feat(compilers): recognize Arm Compiler for Linux armflang
armflang is the Fortran driver of Arm Compiler for Linux and is
Flang-based, so a new arm_flang family extends flang. The options
chapter of the 24.04 reference guide (101380) lists no option with a
separate value that the flang and gcc tables lack (-I, -J, -isystem,
-o, -D, -U, -L, -l, -Xlinker are known; the rest join with "="), so
the family adds no flags of its own.
Requirement: recognition-compiler-names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit c2b71d956de55aee8deb3f72b92d6df3c6550fb9
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 11:37:09 2026 +0000
docs(compilers): ask for a recipe page only when interception needs it
A page that only says "put the compiler on PATH and run Bear" holds for
every compiler and adds nothing; the generated supported-compilers page
already names each one. Keep the per-family recipe page for compilers
that need extra plumbing for interception.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 22f7bddec070274eeda1f3874f8163ba7afbfd1c
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 10:42:19 2026 +0000
docs(requirements): drop armcl from the not-recognized table
ti_cgt.yaml has recognized armcl (and cl7x) since 5a63cd32, so the
row contradicted the code and the TI integration test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 26d56b16b25ff2c06f801ec221a5964b3f008e9d
Author: dmfrpro <dmfr2021y@gmail.com>
Date: Sun Oct 11 20:41:42 2026 +0300
test: assert what Bear reports for popen/system, not the grandchild
The nix build sandbox's /bin/sh is a static busybox, so the shell child
never loads the preload library and the grandchild (cat, echo, or the
compiler wrapper) goes unrecorded. popen_interception and
system_interception asserted exactly those grandchild events and failed.
Bear's interposed popen()/system() reimplement the call via posix_spawnp
with a doctored envp and report the "sh -c <command>" execution
themselves, so assert that event instead: it is recorded on every
platform and is the interception these tests exist to prove.
hardened_system_after_unsetenv and hardened_popen_after_unsetenv failed
differently: interception of the compiler actually works in the sandbox
(the static busybox execs the nixpkgs gcc wrapper script, whose dynamic
interpreter picks the preload back up), but the first recorded event is
the real gcc with the distribution's injected flags, not the wrapper's
argv the tests asserted. Pin the compiled file, directory, and output
instead; the exact compiler argv is not what these tests protect. Their
docs also still described the long-gone "calls the real system()"
mechanism; bring them in line with the reimplementation.
commit a818a6bf2d5756cef7c5d5825c4477638e5d13a2
Author: dmfrpro <dmfr2021y@gmail.com>
Date: Sun Oct 11 20:34:37 2026 +0300
test: give the exec*p empty-env runs a PATH containing echo
The PATH-searching variants (execlp, execvp, execvpe, posix_spawnp) are
re-run under `env -` to prove interception survives a cleared
environment. With PATH unset, the real exec falls back to libc's
built-in default search path, which provides no echo in the nix build
sandbox (and only accidentally does on a NixOS host, where glibc's
_CS_PATH points at /run/current-system/sw/bin). The exec then fails with
ENOENT and the test exits 255. Pass PATH=<echo's directory> alongside
the cleared environment; the hardening property under test (Bear
restoring LD_PRELOAD/BEAR_INTERCEPT) is unaffected.
posix_spawnp_interception also gains the missing has_executable_echo
gate: the test spawns echo but never declared the dependency.
commit 87be810401f48bafd626baf27a4362fb1138a258
Author: dmfrpro <dmfr2021y@gmail.com>
Date: Sun Oct 11 20:31:42 2026 +0300
test: match the full argv in the parallel interception count
Counting events by executable name alone double-counts wherever the C
compiler is a wrapper script: nixpkgs' gcc execs the real gcc, so the
suite sees 8 events for 4 compiles and the exact-count assertion fails.
Pin each parallel invocation by its exact argument vector instead; only
the wrapper-level event carries the bare "gcc" argv the script issued.
commit c79ccf86ff14c9f767d3ec21ceae4a3567379f4c
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 13 08:29:13 2026 +0000
chore(devcontainer): install beads (bd) pinned to 1.3.1
Development tasks move from markdown plans to beads, a local issue
tracker that keeps state between agent sessions. GitHub issues stay
for user reports.
The binary comes from the release tarball and is checked against its
sha256, so upgrades (and any data migration they bring) happen only
when the pin moves. Usage metrics are on by default; BD_DISABLE_METRICS
switches them off.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit cd2946edd9334bb62cf41349b9d248c59e5a0b70
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Oct 8 07:00:10 2026 +0000
ci: run CodeQL static analysis
Clippy and the tests check that the code behaves as intended; they do
not look for security flaws. CodeQL does: memory and string handling in
the C preload shim, which runs inside every intercepted process,
injection risks in the Rust code, and unsafe patterns in the GitHub
workflows themselves. Running it on every push and pull request, and
weekly for newly added queries, catches these before a release ships.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit 729d0e14e59f67f2a40149ba9c03eea61b5901fc
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Oct 8 06:55:23 2026 +0000
docs: add a security policy
Without one, a reporter who finds a vulnerability has no private way to
reach the maintainer, and the default is a public issue that discloses
the problem before a fix exists. SECURITY.md names the private channel
(GitHub security advisories), which releases get fixes, and what Bear
treats as in scope, so a report can be handled before it is public.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit d6c93790540d1f0312668d9b5fcb022ff6ff31a1
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Oct 6 07:38:58 2026 +0000
chore(release): bump version to 4.2.3
commit 7238459f4d221e3a3ad1fff007ba78d6a04a10fd
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sat Sep 5 03:41:59 2026 +0000
docs(man): date the page for the 4.2.2 release
The page still carried the date of the last content change. Set it to
the release date and regenerate; the roff diff is the date line only.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit a5b2d8f2f4f7b0336b7ec3f30cd997df0719601e
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sat Sep 5 03:39:17 2026 +0000
chore(deps): refresh the lockfile before the 4.2.2 release
Nine packages had semver-compatible updates pending, four of them direct
dependencies: serde-saphyr 1.1.0 to 1.2.0, which 8.0.5 to 8.0.6, log
0.4.33 to 0.4.34, and cc 1.4.3 to 1.4.5. The rest are transitive.
Taking them now rather than after tagging keeps the released binary on
the versions the pre-release checks actually ran against. No manifest
requirement changes: every direct dependency already names the current
major, and an OSV query over all 127 locked packages reports no
advisories and nothing yanked, so this is drift, not a fix.
serde-saphyr is the one worth naming. It parses both the user config and
the compiler YAML at codegen time, and 1.2.0 is six days old on a crate
that reached 1.0 five weeks ago. The full check set passes on it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 410e9b49f398525e2280d97ef34cc8d5c3d703ea
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Sep 3 11:24:57 2026 +0000
feat(cli): accept --overwrite wherever --append is accepted
The flag is a no-op: it selects the behaviour that is already the
default, so nothing reads it yet. It exists so a script can state the
behaviour it depends on ahead of the release that makes appending the
default, and the parsing site carries a comment saying so, since an
argument that is parsed and never inspected otherwise reads as a bug.
Passing it with --append is a usage error rather than a precedence rule.
The two state opposite intents, and picking a winner would let the
contradiction survive the default change, where it would silently start
losing or keeping entries depending on which rule had been chosen.
Requirement: output-append
commit c07cced4cbbf748ad0fd9fb822c7c3f5902890dd
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Sep 3 11:24:50 2026 +0000
docs: name the overwrite behaviour before the default moves
Bear overwrites the compilation database unless asked to append, and a
run that captures nothing therefore replaces a good database with an
empty one. The fix is to make appending the default, but a script that
depends on today's behaviour has no flag to name it with, so the break
would land with no migration path.
Document --overwrite as naming the current default. It changes nothing
today; its value is the release of lead time it gives scripts before the
default flips. The rationale entry records the name choice and why the
two flags are rejected together rather than ordered by precedence.
Requirement: output-append
commit 63fb804008d45b67ee1caf143d7110277c23ba61
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Aug 20 11:56:35 2026 +0000
test: read the dispatch verdict, not the log line's substrings
The ambiguous-name probe test scanned bear's debug log with two plain
`contains` checks: a line holding both "gcc" and "Recognized(" meant the
probe had been bypassed. Both halves match text that says nothing about
dispatch. "NotRecognized(" ends in "Recognized(", and every verdict line
dumps the intercepted execution together with its environment, so a
build environment that merely mentions GCC satisfies the first half.
A Gentoo package build sets CC=x86_64-pc-linux-gnu-gcc and
CFLAGS=-frecord-gcc-switches, so the `coreutils_to_ignore` interpreter's
NotRecognized line tripped the assertion and failed the test on a run
where the probe had correctly dispatched to Clang (#716). Bear itself
was right; only the test's reading of the log was wrong.
Parse the OutputLogger line instead: take the interpreter id and the
verdict from their own positions, and compare the id exactly. The test
exports CFLAGS the way the Gentoo build does, so the false positive is
reproduced rather than left to the host, and a unit test pins the
parsing against a line from the reported log. CFLAGS rather than CC
because a program variable gets resolved on PATH in wrapper mode, and a
Gentoo triplet name would warn on every host that lacks that compiler.
Requirements: recognition-ambiguous-name-probe
Closes #716
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit a53148e080708da5fd7713d134e1ee1dc5b0c633
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Aug 20 11:56:35 2026 +0000
chore(release): bump version to 4.2.2
Open the 4.2.2 release branch. The bugfix commits that follow report
this version in their logs, which is what issue reports quote back.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit e1ade91ab0411e22aaa3ea37c9ec95dd8bcfd4c8
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 10:23:00 2026 +0000
docs(man): date the page for the 4.2.1 release
The manual changed since 4.2.0, so its date should say when, not
carry the previous release's stamp.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 6c003481a1f0f24a28e50a02147acc0c0ed62e3d
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 10:14:07 2026 +0000
ci: fold the license check into the audit job via cargo-deny
Restores the dependency license check that went away with the copyright
job, this time as a gate rather than a report. Every dependency is
statically linked into GPL-3.0-or-later binaries, so each one has to
carry a GPL-3.0-compatible license, and the alternative to checking is
hearing about it from a distribution packager after release.
cargo-deny covers advisories as well, so it replaces cargo-audit
outright and the two jobs become one. Verified equivalent on the
advisory side: against the lock this branch carried before 64967a78, it
reports RUSTSEC-2026-0204 on crossbeam-epoch 0.9.18 and exits non-zero,
which is what cargo audit did.
Pin unmaintained, unsound, and yanked in the config rather than
inheriting them. cargo-deny defaults unsound to the workspace alone and
yanked to a warning, both looser than the cargo audit --deny warnings
the job ran until now; stating all three keeps a later cargo-deny
upgrade from relaxing the gate without anyone noticing.
The allow list holds only what the current tree needs. BSD-3-Clause and
Unicode-3.0 each look droppable but sit inside AND expressions, where
the permissive alternative cannot satisfy the requirement alone.
cargo-deny reports an allowance nothing matches, so an entry that stops
being needed will say so.
Name the config .deny.toml. cargo-deny looks for deny.toml, .deny.toml,
then .cargo/deny.toml, so the dotfile needs no --config flag and matches
how .rustfmt.toml and .codespellrc already sit in the tree.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit eeb48a8c4d6c45559aff5225b8d4e3ba4cb04ca8
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 10:13:56 2026 +0000
ci: gate compile and test on lint instead of chaining them
Test waited on compile, which builds --release. That is a different
profile from the debug build test performs, so a green compile did not
imply a green test, and the edge cost about 77 seconds of serialized
latency on every run.
Lint is the better gate. Clippy compiles the whole workspace, so it
fails on code that does not build, and it finishes sooner than the
release build did. Compile and test now both hang off lint and run
alongside each other rather than in sequence.
Run cargo fmt before clippy for the same reason: formatting takes a
second to check and there is no point spending a clippy run to learn
the tree is unformatted.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 9b252c1631032e2fa6a636b6c1bd94d73074c264
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 09:06:36 2026 +0000
ci(pages): build the site once and deploy the artifact
The deploy job repeated every step of build: checkout, toolchain,
cargo install mdbook, and check-docs-site.sh. needs: build made the
build pass first and then deploy rebuilt the whole site from scratch,
so every master push compiled mdBook twice.
Move the post-processing and the artifact upload into build, and leave
deploy with nothing but deploy-pages. Deploy no longer checks anything
out, so it needs no contents scope, and the job-level block that had to
restate contents: read for its own checkout goes away with it.
Post-processing now runs on pull requests too. It previously executed
only on a master deploy, which meant a fault in
postprocess-docs-site.sh could not fail a review and would land
straight on the live site.
Uploading the artifact does not publish anything. Deployment happens in
deploy-pages alone, which is gated on a master push, runs in the only
job holding pages: write, and targets an environment whose branch
policy admits master and nothing else.
Bump upload-pages-artifact to v5 and deploy-pages to v5. v4 of the
former stopped including hidden files by default and mdBook emits
site/book/.nojekyll, so set include-hidden-files to keep the artifact
byte-for-byte what v3 produced.
Drop the two comment blocks describing the scripts. Both scripts open
with a far more detailed header covering the same ground, and the
postprocess comment did no more than point at the script header it
duplicated. Keep the mdBook version note: check-docs-site.sh tells
contributors to install the version pinned here, so the two files
depend on each other.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 14b819ed3de7c158f9911a0e8012031bf43a5768
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 08:44:21 2026 +0000
ci: tighten workflow hygiene and drop the copyright job
Bump actions/checkout from v6 to v7 in both workflows, and correct
macOS-latest to the canonical macos-latest spelling.
Constrain the GITHUB_TOKEN. Both workflows now default to contents:
read, which is all any job needs to check out and build. The Pages
deploy job keeps its own block because a job-level permissions key
replaces the default wholesale rather than merging into it; without
restating contents: read there, its checkout would run with the scope
set to none and work only by virtue of the repository being public.
Drop the copyright job. It ran cargo license and printed a report that
nothing consumed, so it could only fail if cargo-license itself broke.
It cost a from-source install on every push while asserting nothing. If
license compatibility is worth gating later, it needs a check that
fails on a license outside an allowlist, not a report.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit f2b8394f6522dadb8855a1e3b76f1b9d8bc7b7b7
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 08:44:13 2026 +0000
ci: run the security audit on every branch
The audit job was gated to main/master, so it never ran on an X.Y.Z-rc
branch. The release skill's only CI precondition is that the latest run
on the rc branch is green, and a skipped job reports green, which left
the release gate structurally blind to advisories. On master the job did
run, but only after the push that carries the tag, so its result arrived
too late to stop a release.
This was not hypothetical. Cargo.lock carried crossbeam-epoch 0.9.18
against RUSTSEC-2026-0204, published five weeks before the lock was next
touched, and the run for the commit that fixed it reported the audit job
as skipped.
Install from a prebuilt binary rather than building cargo-audit from
source, since the job now runs on every push instead of only on master.
Add the explicit toolchain step the other jobs already have, instead of
depending on whatever the runner image ships. Promote unmaintained,
unsound, and yanked advisories to failures with --deny warnings; the
current lock is clean under that flag, so it starts from a green
baseline rather than an inherited backlog.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 64967a7817f749afb19eb756f376c624fe263bde
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 07:58:32 2026 +0000
chore(deps): move serde-saphyr to 1.1 and refresh the lock
serde-saphyr was the one entry that could not move on its own. Cargo
treats every 0.0.z as its own breaking version, so "0.0.28" was an exact
pin while every other requirement in the table already permitted newer
releases. Bumping it to "1.1" is the only manifest edit; the remaining
twelve crates in the lock diff needed no change to their floors.
The 1.x API surface Bear uses is unchanged: from_str, from_reader,
to_string, and Error, across crates/bear/src/config and the build-time
codegen in build-support/compilers-codegen. The release also sheds a
wasm-bindgen and ahash subtree, taking the workspace from 135 packages
to 127.
Refreshing the lock also clears RUSTSEC-2026-0204, a null-pointer
dereference in crossbeam-epoch fixed in 0.9.20; the lock carried 0.9.18.
It reaches Bear only through assert_fs in the integration-test
dev-dependencies, so no shipped binary was exposed. CI did not catch it
because the security-audit job is gated to master and never runs on an
rc branch.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit cec161443b9aa7463dd7dd0db91d35e51ae13d03
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 06:58:10 2026 +0000
docs(requirements): say what path formatting really reaches
The contract claimed that paths inside the arguments array are not
transformed, and named output paths in flags as an example. Both halves
were false: the source argument and the output flag's value have long
been formatted with the same strategy as the file field, so an entry
cannot disagree with itself about a path a consumer may read from either
place. Only a path that is the payload of some other flag, an include
search path and its kind, is carried through as the build spelled it.
The code was right and the document was not, which is the dangerous way
round for a contract that tests are written against: nothing pinned the
real behaviour, so a later change could have "fixed" the converter to
match the text and broken every consumer that resolves a source path
from the arguments. The scenario is now written down and covered by a
test that fails when the formatting is removed.
The module doc carried the same claim, contradicting a comment ten lines
into the function it describes, so it is corrected here too.
Requirements: output-path-format
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 086816a688f1ba41eaefe25a7db7cdad744f627d
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Sun Aug 16 06:32:07 2026 +0000
fix(semantic): match the glued spelling MSVC actually documents
An output option is written four ways, and only two of them worked. The
glued and colon-glued forms landed correctly, a lone /Fo became an output
naming nothing, and the colon form that leaves its value in the next
argument lost that value: unclaimed, it was read as an object file input
and dropped from the entry.
Three rules per option cover all four. The colon rules carry the colon in
the flag itself, so "glued or separate" takes both colon spellings at
once. The bare rule classifies a valueless option as the plain flag it
is, which keeps it out of the output field and, more to the point, stops
an empty path from being resolved into the working directory once
`format.paths` is set. It has to stay above the prefix rule, which the
new test pins: the two flags are the same length, so the generated table
keeps whatever order this file gives them.
Requirements: output-compilation-entries
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 97e5746eae3df2455e40a14958bbcb9f7856a1ff
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Aug 13 13:01:07 2026 +0000
test(semantic): spell the rewritten path the platform's way
The glued-output test built its expectation as a literal string with a
forward slash, while the updater under test joins with `Path::join`,
which writes a backslash on Windows. The assertion beside it passed
there because `Path` equality compares components rather than bytes, so
only the string form failed, and only on Windows.
The point of the test is where the rewritten path lands, inside the
glued token rather than beside it, not how the platform spells the
separator, so the expectation now joins the same way the code does.
commit cd5f2fb5f39cc6713bd9eecb1252baa85f5ac285
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Aug 13 12:32:08 2026 +0000
fix(semantic): record the output flag the way the build wrote it
An entry's arguments are what the build ran, but the output flag was the
one argument Bear re-spelled. It stored the flag and the path apart and
always emitted them as two tokens, so `-omain.o` came back as `-o
main.o`. Harmless for GCC, which accepts both, and wrong for everyone
else: cl.exe documents that `/Fo` takes no space before its value, and
TI's long options glue theirs after `=`, so a database recorded a
command line those compilers would reject.
The observed spelling is now carried on the argument itself, and the
type that models it writes the tokens back, rather than handing out a
separator for the caller to join. The path stays a field of its own, so
it remains individually addressable: the path updater still reaches it,
and rewriting it under `format.paths` lands inside the glued token.
That also let the converter shed the token inspection it needed while an
output flag arrived as two tokens. It could not tell a flag from a path
by looking at the emitted string (`-omain.o` has an extension, and
formatting it would have produced `<dir>/-omain.o`), so it guessed. It
now passes one closure saying how to format a path and leaves the
decision of which arguments carry one where it belongs.
With the guessing gone, the filter it needed goes too: every path now
reaches the resolver, the same one the `output` field already used
unfiltered. An extension-less relative output such as `-o program` was
previously left alone in the arguments while the `output` field of the
same entry was resolved, so one entry gave two answers for one path.
Requirements: output-compilation-entries, output-header-entries
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 0334bdf0e86daa8942386891aa2c287344bb3e3a
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Aug 13 11:27:05 2026 +0000
fix(semantic): match the glued spelling MSVC actually documents
cl.exe glues the value to every /F-family and /Y-family option, and the
compiler reference says so outright: "Don't put a space between the
option and pathname". The flag table only had the ':' spelling, so a
glued /FoCMakeFiles\x.obj fell through to /F (set stack size), was
classified as a link-stage option, and was stripped from the entry. Both
CMake and Meson emit the glued form, so a real MSVC build lost its object
name and its output field on every entry.
/Yc and /Yu were worse. Their filename is optional, yet the ':' pattern
also accepted a separate argument, so a bare /Yc consumed the source that
followed it and the compilation vanished from the database entirely.
A prefix rule is the only form in the pattern language that takes the
glued spelling, still handles the ':' one (the output extractor strips
it), and consumes exactly one token, so a valueless option cannot swallow
a source. /F is tightened to its documented separate value, which stops
it absorbing the longer options and leaves an unlisted /F... retained as
unrecognized rather than stripped as link-stage. /FA joins /Fa: it
selects listing contents, takes no path, and differs only by case.
Requirements: output-compilation-entries
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit cd4749b0adfa1ff960cf41efcc11ebb779140d20
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Aug 13 09:47:12 2026 +0000
docs(site): move a recipe's wildcard from the shell to make
A recipe that spells its sources `*.c` reaches parse-sh as a glob: `-n`
prints the line as written and the shell that would have expanded it
never ran, so the database gets an entry whose file is `*.c` and the
real compilations are missing. Nothing in the text says otherwise, so
the run is silent and exits 0.
Only the shell-glob form has this problem. `$(wildcard *.c)` expands
when make reads the Makefile, before any recipe is printed, so the dry
run already carries the file names and the entries come out right. The
two recipes build the same thing; only the expansion moves, which makes
this a portability note rather than a workaround. Interception is the
answer when the Makefile is not yours to change: the shell expands
before the compiler starts, so the observed exec() names every source.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 5a63cd3227e90a17dec7e8bccb23236dffba8051
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Aug 13 09:25:30 2026 +0000
feat(semantic): recognize TI's classic Code Generation Tools
Code Composer Studio still generates makefiles that drive armcl, cl6x,
cl7x, cl2000, cl430, and clpru, and Bear produced no entry for any of
them: not a wrong entry, none. Forcing one of these through as: gcc did
not help either, because the dialect differs where it matters most, an
output file being --output_file=main.obj rather than -o main.obj.
The six drivers share one option dialect that is not derived from GCC's,
so the family stands alone rather than extending one. Every driver name
and the shared dialect were taken from TI's own manuals (SPNU151,
SPRU187, SPRUIG8, SPRU514, SLAU132, SPRUHV7), which are cited per
recognition entry.
Two classifications needed a decision. The -pp<x> options that write a
side file mean "preprocess only" on their own, but Code Composer Studio
always pairs them with --preproc_with_compile, which resumes the
compilation; a flag table cannot express "unless -ppa is also present",
and dropping every CCS compile is the worse error, so they stay
non-terminal. --obj_directory names a directory rather than a file, so
it configures the compile instead of filling the output field, which
only --output_file does.
Requirements: recognition-compiler-names
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 3d2dd3e1272daa184c4938a549e11f9db786695c
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Thu Aug 13 09:03:13 2026 +0000
docs(site): tell the reader how to capture a complete dry run
bear parse-sh records what the dry-run text contains, so an empty or
short database is almost always the build system printing less than the
user expected. The man page stated that as a limitation and stopped
there, which left the reader with a symptom and no next step. It is also
the largest cluster of bug reports in the trackers of the tools that
solve this problem by regex-scraping the same text, so it is the failure
Bear inherits from make rather than from its own parser.
The new recipe covers the causes a flag can fix (an already-built tree,
a stopped build, an unannounced top-level directory, a translated
locale) and the ones no flag can (a recursion make does not follow under
-n, a ninja dry run that prints progress instead of commands, a log
already captured without them), and points at interception as the path
with none of them. Troubleshooting keeps the symptom and routes here.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
commit 1207209e21cf3c20841f5be26ee28737e3d626e9
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Wed Aug 12 07:52:31 2026 +0000
fix(semantic): accept clang's -F with a separated framework path
Clang's -F is a JoinedOrSeparate option, so `-F /Frameworks` and
`-F/Frameworks` name the same framework search path. The flag table
spelled it as a prefix match, which only covers the joined form. Given
the separated form, the operand fell through to source classification,
was rejected as a binary source, and was dropped from the entry -- the
recorded command kept a standalone `-F` that no compiler can consume,
and the search path was silently lost.
SwiftPM emits the separated spelling on macOS, which is how this
surfaced; it reproduces on any captured invocation and through parse-sh.
Spelling it `-F{ }*` matches both forms, the same way gcc.yaml already
spells -I, -D and -L, and swift.yaml and nasm.yaml already spell -F.
The four families that extend clang inherit the fix; none override -F.
Requirement: output-compilation-entries (flags that configure compiling
are kept in the entry).
Closes #715
commit e29efe137731d8b125bd20ba1ea9fe94e86a9ead
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Aug 11 11:56:40 2026 +0000
docs(site): rule out narrating a page to its reader
The habit that just got swept out of site/src had no rule against it,
only rule 4's narrower ban on a page discussing its own verification.
State the general form, with the two kinds of self-reference that stay
and the test that separates them: a sentence that sends the reader
somewhere is routing, a sentence that describes where they already are
is narration.
Rule 8 gains the other half of the same review. The recipe index and
SUMMARY.md are two hand-maintained lists of the same pages and only the
second is checked, which is how the multilib recipe stayed off the index
after it landed.
commit 72ce1735980beca7ea26f220ccae2543df8b9e2d
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Aug 11 11:53:33 2026 +0000
docs(site): stop narrating the pages to the reader
A page states facts about Bear, not facts about itself. Several pages
opened with a roadmap of their own headings ("The rest of this page
covers ...") or announced their editorial relationship to another
document, which tells the reader nothing they cannot see from the
headings and costs them the first paragraph, the one lifted into the
meta description.
Cut the roadmaps and the two places where the text defended a writing
decision instead of stating a fact. Reword the link glosses that
referred to the page containing them, so a Related list names tasks and
databases rather than pages.
Kept the tutorial "By the end of this page ..." openings, which promise
the reader an outcome, and the scope boundaries that send someone to a
different page before they read the wrong one.
commit b86169e0fe954357f3606de0faf115cdb25db232
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Aug 11 11:51:45 2026 +0000
docs(site): list the multilib recipe in the recipe index
The recipe index promised one page per task while omitting
guides/recipes/multilib.md, which SUMMARY.md has carried since the page
landed. A reader browsing the index had no path to it at all.
Replace the opening line as well. It stated the collection's editorial
rule rather than telling the reader what they will find, and the same
rule is already glossed on the two pages that link here.
commit 832d4b48ebef04e27d7b0937aa3084ece4e4e143
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Aug 11 11:37:35 2026 +0000
docs(release): look past commit subjects when drafting notes
The 4.2.1 work changed the wording of the invalid compiler-spelling
error and how a launcher name echoes back, but every commit carrying
those changes is subjected `refactor:` or `docs:`. Drafting from
`git log --pretty=%s` alone would have shipped a release that silently
changed output a user could be matching on.
Point the drafter at commit bodies and at rationale entries added since
the previous tag, which is where an accepted user-visible cost is
already written down, and add the command that lists them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
commit 798db042dde1c2ad843c6177562c149dcd38abdb
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Aug 11 11:36:39 2026 +0000
test: pin configured compilers replacing PATH discovery
In wrapper mode a non-empty compiler list switches interception away
from scanning PATH. Two supervisor unit tests already covered the gate,
but neither cited the requirement, so searching for what protects
`interception-wrapper-mechanism` turned up seven tests and none of them
this behavior. It reads like a bug to anyone meeting it cold, which is
exactly the kind of thing a later change "fixes" in passing.
The step that decides whether the list counts as non-empty had no test
at all: excluded entries are filtered out before the supervisor sees
them, so a configuration that only excludes compilers still gets the
PATH scan. That filter is now a named function with its own tests.
The integration test proves the composed behavior through the real
binary, which neither unit layer reaches. It runs one build script
twice and varies only the configuration, because an assertion that
nothing was intercepted also passes when the build script is broken.
The script calls the compiler by bare name, since a compiler named in
an environment variable is wrapped either way.
Requirements: interception-wrapper-mechanism
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
commit 7a341bb307db8a94b5ee7c541629f7aef88496be
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Aug 11 11:05:43 2026 +0000
docs: state that configured compilers replace PATH discovery
In wrapper mode, listing a compiler does more than hint at recognition:
it switches interception from scanning PATH to wrapping exactly the
listed executables. A user who adds one unusual compiler therefore
stops gcc and clang from being intercepted, which is intended but was
documented nowhere. Both the man page and the configuration reference
described the section purely as recognition hints.
Entries marked as excluded do not count, so a config that only ignores
compilers still gets the PATH scan.
Requirements: interception-wrapper-mechanism
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
commit 7003ed670a7baed5ce774d02d7fa431716b03ec1
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Aug 11 10:23:46 2026 +0000
docs: follow the semantic crate to its new home
The crate move left the guides describing a layout that no longer
exists: bear as the owner of semantic analysis, a build script it no
longer has, and compiler YAML under crates/bear. Routing that sends a
reader to the wrong directory is worse than no routing, since it reads
as current.
The new crates/semantic/CLAUDE.md states the constraints that are easy
to violate rather than listing files: the dependency boundary that is
the reason the crate exists, the deliberate public API, why the testing
feature is not cfg(test), and that compiler definitions are data.
docs/rationale/workspace-crate-layout.md records the durable reasoning
for the split and the config boundary, including the rejected
alternatives, the accepted costs, and the deferred question of folding
the application library into the driver. Two sibling rationale entries
described the serde deserializer this work removed; both now describe
startup resolution instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
commit 149fcd77203324f009baaa739afb6e38ccc71dd0
Author: Laszlo Nagy <rizsotto@gmail.com>
Date: Tue Aug 11 10:02:52 2026 +0000
refactor(semantic): extract semantic into its own crate
With the config dependency gone, the analysis core can live where the
compiler enforces its boundaries. `crates/semantic` now owns compiler
recognition, flag parsing, and the compilers/*.yaml definitions with
their codegen build script; `crates/bear` keeps the application layer
and gains a dependency on it. A back-edge from the driver into the
analysis core is now a dependency cycle rather than a convention.
The crate states a deliberate public API instead of inheriting the
module's blanket visibility. `interpreters::compilers` narrowed to
`pub(crate)`, so `CompilerType`, `CompilerId`, `CompilerInterpreter`,
the interpreter combinators and `IgnoreByPath` are unreachable from
outside; the driver sees only what it uses. The manifest lists what
analysis actually needs, which turned out to exclude serde entirely.
The `testing` module is feature-gated rather than `cfg(test)`, because
a dependency's test code is not compiled for its dependents' tests. The
gate is `any(test, feature = "testing")` so the crate's own fast test
loop still covers the module. `bear` enables the feature as a
dev-dependency; release builds carry no test factories.
Build scripts and scripts that read the YAML directory follow it:
intercept's env-key codegen, the codegen snapshot tests, the docs-site
generator, and the integration build script's rerun trigger.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>