Repository navigation
v0.7.0
The production-readiness release. It ships the correctness fix main had
been sitting on for twelve days, and closes the gaps between "the analysis is
correct and published" and "a team can depend on this in their CI": the
supply chain, the release, the platform coverage, and the semver rule that
decides what a field addition costs.
Added
-
Windows is gated in CI, and the README says which platforms are
supported. The word did not appear anywhere in this repository — not a
support statement, not an exclusion, not a job — while the README said the
analysis "runs anywhere". A Windows user had no way to tell whether a
failure was worth reporting.It mostly does run anywhere: the job found three bugs, two of which are
below and one of which madelearnpanic outright. The analysis,check,
the artifact round-trip, the schemas and the CLI contract are gated on
Windows now.The four terminal views are not, and that is stated rather than
skipped: under ConPTY the PTY suites time out waiting for a frame boundary
while the screen they print is the right screen, fully painted — two
different suites show it, so it is about how that console delivers what an
application wrote rather than about what these views render. #162 holds the
root cause, which needs a Windows machine to reduce..gitattributespins
the working tree to LF, which is the other half of thelearnfix.Components are named explicitly in that job rather than left to
rust-toolchain.toml: the channel installed on the runner and its
componentsdid not, and the failure surfaced three crates later as the
driver's build script reporting a missingrustc-dev— the right message
from the wrong layer.
Fixed
-
cargo reconverge learnpanicked on Windows, for all four lessons.
The prose arrives throughinclude_str!, which embeds the working tree's
bytes. A checkout withcore.autocrlf=true— the default on Windows —
gives\r\n---\r\n, so the page split found no separator, every lesson
collapsed to one page, and the page-metadata assertion fired. A surviving
\rwould have rendered as a glyph too. Line endings are normalized before
the split now, and the regression test is written against the bytes rather
than the platform, because a Linux clone of a repository whose files were
committed with CRLF has the same problem..gitattributespins the tree to
LF as well, for the golden files the PTY suites compare byte-for-byte. -
reconverge-driverrefused to build on Windows withrustc-dev
installed. The build script that turns a missing component into one
actionable line looked in<sysroot>/libforlibrustc_driver*, which is
the Unix layout — windows-msvc putsrustc_driver-<hash>.dllunder
<sysroot>/bin, so a correct toolchain was reported as missing the
component and the build stopped. That is exactly what the script's own
documentation promises not to do.The same check was also a false negative everywhere:
librustc_driver-<hash>.sois in<sysroot>/libon any toolchain, because
it is the shared library rustc itself links — measured against a stable
1.98.0 with norustc-dev, one match there and zero in
lib/rustlib/<host>/lib. It now looks for the component's.rmetain
<sysroot>/lib/rustlib/<host>/lib, which is whererustc-devinstalls on
every platform, so the guard fires when it should and only then.
Added
-
Releases carry binaries, and the action has a version to pin. Two gaps
that were really one:release.ymlcompiledcargo-reconverge,
reconverge-driverandreconverge-tuifor Linux and macOS on every
release and then left them in workflow artifacts, which expire and need a
GitHub login to reach —v0.6.1shipped with zero assets. So the only
supported install wascargo install, which compiles a rustc-driver, and
the GitHub Action pays that on every consumer's run because it deliberately
never caches.github-releasenow creates the release from this version'sCHANGELOG.md
section — not from generated commit subjects — and attaches one
reconverge-<tag>-<host-triple>.tar.gzper platform with a.sha256
beside it.float-major-tagthen repointsv0through the API, after the
publish, so the floating tag can never name a release that did not reach
crates.io.README.mdandaction/README.mddocument@v0instead of@main. That
was the sharper half of the problem: the ref decides which analyzer version
the action installs, so@mainre-decided it on every run of a consumer's
CI, and a merge here changed the gate in somebody else's pull request with
no notice and nothing to pin. -
--cctakes the CUDA spellings.sm_86is whatnvcc -archtakes,
whatptxasprints and what a PTX.targetdirective says;86is the
same thing without the prefix. Both now normalize to8.6, as dosm_120
and100— a capability is one or two major digits and exactly one minor
digit, so the last digit of a run is always the minor.launchboundhas accepted these two spellings since 2.0 and passes this
flag straight through to this parser, so the pair disagreed about the
spelling of their shared argument. Nothing else moved: normalization
rewrites the text and hands it to the same parser, so8.xis still
non-numeric and999.9still lands on the table message.One test changed its example rather than its assertion:
a_bad_value_answers_in_one_line_…used--cc 80, which now means 8.0.
Changed
-
termlens 0.11 in both PTY suites (
reconverge-tuiand
cargo-reconverge), and the vendored skill with it. 0.11 is termlens's
stability candidate: from it no promised item changes incompatibly before
its 1.0, so this requirement should hold for a while.Its one breaking change lands here as a simplification.
Screen::unsupported()returns a view instead of a slice ofArc<str>,
andunsupported_overflow()folds into it — so the pinned list and "the
record is not truncated" are now one assertion, because the view
compares equal to a slice only when the retained shapes match and
nothing overflowed the bound.tests/emulation.rsloses its
Vec<String>helper, and the three flow tests lose a separate overflow
assertion each.The comment in
tests/emulation.rswarning that termlens#320 reported
blink and strikethrough as unsupported when the shadow parser implements
them is gone: that was fixed upstream in 0.10.2, so an entry in this
list is now a real gap in every case. -
Uniformity is scoped now, and a barrier is checked against its own
participants (#133). A guard uniform within a block settles
sync_threadsand settles nothing wider:blockIdxand
cluster::block_rank()are constant on every thread of a block and
different on the next one, so#[cluster_launch(2, 1, 1)] pub fn only_rank_zero() { if cluster::block_rank() == 0 { cluster::cluster_sync(); } }
is entered by one block of the cluster and skipped by the other, and 0.6.x
reported nothing at all —exit 0, no findings, zero opaque. The same
shape one scope up (grid::sync()under ablockIdxguard) was equally
silent, which is how the report widened from a cluster quirk to the
general statement.The engine now carries a second lattice beside lane uniformity:
LaunchScope—Block ⊑ Cluster ⊑ Grid— recording how far each value is
actually constant, and the dialect answersbarrier_scopefor how far
each barrier reaches. A finding is raised when the guard's scope does not
cover the barrier's.Always
warning, never promoted. The witness interpreter replays the
lanes of one block and cannot execute the second block this needs, so
there is no concrete hang to confirm; calling itconfirmedwould be a
claim the evidence does not support.The precision half matters as much and is pinned by its own samples:
everything starts grid-constant and is narrowed only by what it reads, so
a kernel argument,blockDim, and arithmetic over either still decide a
grid-wide barrier, andcluster::cluster_idx()still decides a
cluster-wide one.blockDim/gridDim/nsmid/gridid/nwarpid/the
launch environment registers and the cluster's shape moved from
BlockUniformto the newGridUniform;smid,block_rankand the
cluster coordinates stayed block-scoped, which is what makes the check
fire where it should.
Breaking
-
reconverge-core:Callee,BarrierSiteandAnalysisgain fields
(Callee::scope,BarrierSite::{scope, cross_block_cause},
Analysis::{local_scopes, block_guard_scope}), andCallKindgains
ClusterUniformandGridUniformbesideBlockUniform.SimtDialect
gainsbarrier_scope, with aBlockdefault, so an existing dialect
keeps compiling and keeps the narrow answer. -
reconverge-artifacts: the four artifact roots,ToolInfoand
ReadErrorare#[non_exhaustive]. "Schemas are additive-only" and
"adding a field is not a breaking change" turned out to be different
promises, and only the first one held: a new key infindings.v1is
additive in JSON and a major break here, because a struct with public
fields can be built with a struct expression from anywhere. TheBreaking
entry above is that, twice, for threereconverge-corerecords.Which types close is decided by who builds the value, and the split was
measured rather than assumed. Marking all twenty-two records broke 42
construction sites inside this workspace alone, acrosscargo-reconverge,
reconverge-tuiand the driver — a downstream front-end that writes
artifacts would pay the same, so the leaf records (Finding,SourceSpan,
Step,Entryand the rest) stay plain deliberately. The roots do not:
a reader deserializes one rather than assembling it, a top-level key is the
likeliest thing a schema gains, and three of the four already had anew.
WitnessArtifactnow has one too, matchingFindingsArtifact::new.The vocabulary enums —
Confidence,LaneState,VerdictKind,
Uniformity,ValueSource— stay exhaustive on purpose: a_arm
over confidence tiers or lane states is a wrong answer that compiles, and
adding a variant is meant to make every reader decide. The rule is written
down in CONTRIBUTING §8 and in the crate docs, so the next reader does not
file the inconsistency as a bug.
Install
cargo install cargo-reconverge
cargo reconverge setupOr take a prebuilt archive below and put the three binaries
on your PATH in the same directory -- cargo-reconverge
finds the driver and the views as siblings of its own
executable. Verify it first:
shasum -a 256 -c reconverge-v0.7.0-<triple>.tar.gz.sha256