changelog

{data.name} Sami Fouad made a commit to samifouad/cqx

Every rule names its language; every finding names what encloses it

Two fields the rule card needs, and the second frontend will need more.

language is written down from the first frontend rather than assumed and retrofitted from the second. It prefixes the rule's name everywhere it is shown — [rust/discarded-check] — and names its page in the documentation. Not patchable: a rule's language is a fact about the rule, not a setting.

item says which function, method or impl a finding sits inside, so a reader can zoom out to the thing that is wrong rather than the line it happens to be on. The span was already in the graph — a symbol is joined to whatever contains it by a Contains edge, and that edge's evidence is the symbol's own extent — so this asks the graph rather than making the extractor write anything new down.

It is answered in one pass over every finding rather than at each of the twenty places one is made. A rule that forgot to ask would be a rule whose card quietly offers one zoom fewer than the others, which is the kind of gap nobody files.

The innermost enclosing item wins: a call inside a closure inside a method is most usefully shown as the method, not as the impl block that also contains it.

Scoring cqx with itself: 16 of 18 findings now carry an item, and the two that do not are about whole files, which is correct.

Not Verified
+110 -1
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

The wrapper is @samifouad/cqx

npm refused cqx-cli — not because it is taken, but as too similar to cp-cli and cpy-cli, which is its typosquatting guard. That check applies to unscoped names only, and the unscoped name we would actually want, cqx, belongs to an unrelated package.

So the wrapper joins the four platform packages under the scope it already depends on. npx @samifouad/cqx is a few characters longer and is written once per workflow.

Not Verified
+15 -401
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

The packaging test builds into its own directory

build.mjs wipes its output directory, and the test called it with the default — so running the test left npm/dist holding five packages built from stub binaries, one real one and three that exit 3. Publishing after a test run would have put those on the registry.

It takes an output directory now and the test passes a scratch one.

Not Verified
+30 -18
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

Tell gh which repository, since publish never checks one out

The publish job downloads artefacts and nothing else, so there is no git repository for gh to infer from and every gh release call failed with "not a git repository". Naming it is cheaper than cloning a tree to answer one question.

Not Verified
+4 -0
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

v0.1.15

Every command that reports a problem now exits like it — score and query printed errors and exited zero, and score is the one CI gates on.

Built and published for four platforms rather than one, each from its own build cache, each run before it is kept.

And cqx can be built on Windows, which it never could: the pinned zega revision held a file whose name contains a colon.

Not Verified
+10 -10
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

A command that reports a problem has to exit like it

cqx score printed "No such file or directory" to stderr and exited zero. It is the command a CI job gates on, so a mistyped --facts path did not fail a build — it passed one, without having measured anything. Every error path in score now sets the exit code, which is what the FAILED flag beside them was already for.

cqx query had no exit code at all. cqx-store was missing from the list the binary takes a maximum over, so nothing it reported could ever fail a script.

And a build without the graph backend answered a query request by printing a node count and exiting zero. --zql and --named are advertised in --help, this build cannot honour them, and a script could not tell that from a query that ran and matched nothing. It says so now, and exits one. Counting still works, because --stats is a different question.

Found by packaging the CLI for npm and asking what a consumer sees. The tests are what the tool is for: extract, history, export and config were already right, and it was the two the CI story depends on that were not.

Not Verified
+859 -9
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

The environment follows the trigger

A dispatch was running the build jobs in release, which holds the token that can write to cqx-releases, cqx-wasm and the product bucket. Those jobs compile; compiling needs the build cache and nothing else. So they now take public-ci unless the run came from a tag push, and public-ci cannot reach anything but the caches — which r2-check proves rather than asserts.

Publishing says what it means: a push, to a tag beginning with v. It was previously reachable by dispatching with dry_run turned off, which made a release something one could do by hand with the right checkbox. The input is gone, so a dispatch can only ever build and smoke test.

ci push main, pull_request, dispatch → public-ci release dispatch → public-ci (build only) release push tag v* → release (build, publish)

Not Verified
+8 -14
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

Move the zega pin forward so Windows can check it out

cqx cannot be built on Windows, and never could. The pinned revision of the zega git dependency contains a file called `:memory:/wal.bin`, and a colon is not a legal character in a Windows filename — so cargo fails while checking the source out, before compiling anything:

cannot checkout to invalid path ':memory:/wal.bin'

It fails even though the dependency is optional and the feature is off, because cargo fetches a git source to resolve the graph regardless.

zega deleted that file some time ago; cqx was simply pinned behind it. The lockfile now points at a revision with no such path, and the zega feature still builds and the workspace still tests.

And the matrix stops hiding its own results: one failing runner cancelled the other three, so a dry run cost two attempts to learn one thing.

Not Verified
+10 -6
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

A dry run builds what is in front of us

Dispatching against v0.1.14 checked out a tree from before this workflow existed, so every job failed looking for composite actions that were not there yet. The tag was not the problem — building an old tag to test a new pipeline was.

A dry run now builds the commit it was dispatched from and takes the version from the manifest. A real release still builds the tag, and still refuses to start if the tag and the manifest disagree.

Not Verified
+26 -11
Sep 19

{data.name} Sami Fouad made a commit to samifouad/cqx

Build cqx for every platform it is distributed on

One tag, four binaries — linux-x64, darwin-x64, darwin-arm64, windows-x64 — each built with its own sccache bucket, each run before anyone is asked to download it. --version is the smoke test because it is the one answer that proves the thing linked and started rather than merely existing, and it is checked against the tag: a binary that reports a version nobody can find is the one mistake that cannot be fixed afterwards.

The tag and Cargo.toml must agree before anything builds, for the same reason. npm would refuse the second publish at a number the first one already took.

Published three ways, because they answer different questions. Attached to the GitHub release, where people look. Mirrored to cqx-releases under the tag, because an installer wants a versioned URL on a CDN rather than a redirect chain through a release page, plus a latest.json that does not move. And the wasm to cqx-wasm, which is the bucket browsers read.

A dispatch defaults to a dry run: build and smoke test every platform, publish nothing. Four platforms cannot be proved any other way, and proving them should not require spending a version number.

The sccache checks are portable now. Asking the AWS CLI whether a bucket is reachable meant installing it, which is a different incantation on each of three runners; asking sccache what it thinks its own cache is costs nothing and reports the view that actually governs the build. A companion action checks afterwards that writing worked, because sccache treats an unreachable bucket as a cache miss — bad credentials compile everything, write nothing, and pass.

Not Verified
+288 -74
Sep 19