Skip to content

Fix CI on main, and a mongo store bug it was hiding - #41

Merged
juicycleff merged 8 commits into
mainfrom
fix/ci-module-versions-and-docs-format
Sep 3, 2026
Merged

Fix CI on main, and a mongo store bug it was hiding#41
juicycleff merged 8 commits into
mainfrom
fix/ci-module-versions-and-docs-format

Conversation

@juicycleff

@juicycleff juicycleff commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Four CI failures on main, and one of them turned out to be a real bug in the mongo store rather than a build-hygiene problem.

The mongo store never keyed a pending ask correctly

Two conformance cases were failing, A2AClaimPendingAskConcurrency and A2AExpiredAsks, and they had one cause. The model tagged its key grove:"reply_with,pk" bson:"_id", and grove keys a document off its own column name, so the token never reached _id. Mongo assigned an ObjectID instead. Every claim by token found nothing, and listing expired asks failed trying to decode an ObjectID into a string.

Naming the grove column id, the way every other model in that file does, is the whole fix.

Why it reached main at all

The mongo backend had never been run. It cannot be, on a current machine: the pinned image refuses to start on a Linux kernel of 6.19 or newer, which is what Docker Desktop ships now.

ERROR: Detected Linux kernel 7.0.12-linuxkit. MongoDB has compatibility issues
with the allocator it uses on kernel v6.19 and newer, so this container will
not start by default on v6.19+.

The container exits 1 before mongod runs, so the suite never gets a database and every mongo test fails on container startup. CI's runner kernel is older and does not hit the guard, which is why the store's own tests looked fine while nothing had exercised them.

CORTEX_TEST_MONGO_IMAGE now overrides the pin, so the suite is runnable on a desktop:

CORTEX_TEST_MONGO_IMAGE=mongo:7 go test ./store/mongo/

CI keeps the pin. With the override, the whole mongo package passes, including all seven a2a cases.

Two tests hung instead of failing

TestEngineStartCarriesMessagesWithoutADrain and TestWorkersDeliverWithoutADrainCall waited on a channel with no timeout. When one of them did not get its signal, the package sat until Go's ten minute limit and reported nothing about which step never happened. Both waits are bounded now and say what they were waiting for.

The build hygiene, which is what the check was actually complaining about

Three requires named v0.0.0-00010101000000-000000000000, the placeholder go writes when a replace covers a module nobody has released. It builds locally because the replace answers first, and go get on any of them fails with "unknown revision". They name v1.6.1 now, which is what every other module in the tree names, and the replace still keeps local builds on the working copy.

The docs lint was failing on two counts. Biome's config named schema 2.4.1 while the lockfile pins the CLI at 2.4.3, and biome treats that mismatch as an error rather than a warning; biome migrate settles it. Two meta.json files had single-line page arrays the formatter wanted broken up.

The generated protobuf files were also not gofmt clean, because protoc-gen-go's import grouping is not what gofmt produces on this Go version. They are formatted, and generate.sh formats what it generates so regenerating will not bring it back.

Reconciling the versions with the module split

Main moved while this sat in review. The module split landed, fabriq 1.6.4 published, and testcontainers went to 0.44, and all of that collided with the grove and shield bumps this branch was carrying. Both go.mod files were merged by hand instead of taking one side: the root now runs grove 1.6.3 across all three drivers, shield 1.6.3 and go-utils 1.2.2, sitting on main's split layout and its newer testcontainers. The fabriq integration keeps main's wiring, because fabriq/core v1.6.4 is the published module that replaced the old local path.

Two go.sum files followed from that. extension was stale against main's testcontainers bump, and inttest picks up sqlitedriver 1.6.3 through its replace of the root module. That clears the Verify tidy failures on the api and extension sub-modules, which had been red since the split and were never caused by anything here.

That local replace is gone as well. The root go.mod carried replace github.com/xraph/fabriq/core => ../../../TwinOS/fabriq/core, pointing at a path that exists on exactly one machine. Nothing in the root module requires fabriq/core, so go was already ignoring the line, and taking it out changed go.sum by zero lines. With fabriq/core v1.6.4 published, it was residue from the split.

The runtime deps moved at the same time: weave 1.6.3, nexus 1.6.4, mongo-driver 2.8.2 and sqlite 1.58.0, with every sub-module tidied to match. extension would not build until that happened, because its go.sum had no entry for the new nexus.

Verification

go build ./... and go vet ./... across every module, and every module is tidy-clean. go test green on engine, a2a, a2aremote, grpcbind, postgres and sqlite, and on mongo under the override, all of it after the driver bumps. inttest vets under its integration tag. gofmt -l empty, golangci-lint clean, pnpm lint clean.

Three requires pointed at v0.0.0-00010101000000-000000000000, the
placeholder go writes when a replace covers a module nobody has
released. It builds here because the replace answers first, and it fails
for anyone running go get: there is no such revision. The requires now
name v1.6.1, which is what every other module in the tree names, and
the replace still keeps local builds on the working copy.

The docs lint was failing on two counts. Biome's config named schema
2.4.1 while the lockfile pins the CLI at 2.4.3, and biome treats that
mismatch as an error rather than a warning; biome migrate settles it.
Two meta.json files also had single-line page arrays that the formatter
wanted broken up.

The generated protobuf files were not gofmt clean, because
protoc-gen-go's import grouping is not what gofmt produces on this Go
version. They are formatted now and generate.sh formats what it
generates, so regenerating will not bring it back.
The two conformance failures had one cause. The model tagged its key
grove:"reply_with,pk" bson:"_id", and grove keys a document off its own
column name, so the token never reached _id. Mongo assigned an ObjectID
instead, every claim by token found nothing, and listing expired asks
failed trying to decode an ObjectID into a string. Naming the grove
column id, as every other model in the file does, is the whole fix.

This is also the first time the mongo backend has been exercised. It
could not be: the pinned image refuses to start on a Linux kernel of
6.19 or newer, which is what current Docker Desktop ships, so the
container exits 1 before mongod runs and the suite never gets a
database. CI's older runner kernel does not hit the guard, which is why
this reached main. CORTEX_TEST_MONGO_IMAGE now overrides the pin, and
all seven a2a cases plus the rest of the package pass against mongo:7.

Two tests also waited on a channel with no timeout, so a failure became
a ten minute hang that reported nothing about which step never
happened. Both are bounded now and say what they were waiting for.
…city

The docs build was failing on invalid YAML, and it was mine. A
description read "REST endpoints: agents, runs, ...", and an unquoted
YAML scalar containing a colon and a space parses as a nested mapping,
so js-yaml threw and turbopack stopped. Rephrasing without the colon
fixes it, and every other frontmatter block in the tree was checked for
the same shape.

The sqlite conformance failures were the claim races meeting sqlite's
default locking. One writer at a time and fail immediately means the
losing claimant gets SQLITE_BUSY where the test expected a clean loss,
so it reported an unexpected error instead of saying whether the claim
is atomic. The test store now opens with WAL and a busy timeout, which
is what the docs already tell anyone deploying on sqlite to do, because
the messaging dispatcher writes while runs write. The engine's store
gets WAL for the same reason.
This case has failed on CI and passed everywhere it could be run by
hand, including with every message forced to share one timestamp, so
one shifted row is all the evidence there has been. The window is now
dumped alongside the assertion: duplicates point at a write that ran
twice, a gap points at ordering, and a short window points at the
limit. Verified by breaking the expectation on purpose and reading what
it printed.
Main took fabriq 1.6.4 and testcontainers 0.44 while this branch carried
the grove and shield bumps, so the two go.mod files were merged by hand
instead of taking one side. The root module now runs grove 1.6.3 across
all three drivers, shield 1.6.3 and go-utils 1.2.2, on top of main's
split layout and its newer testcontainers. The fabriq integration keeps
main's wiring, since fabriq/core v1.6.4 is the published module that
replaced the old local path.

Two go.sum files follow from that. extension was stale against main's
testcontainers bump, and inttest picks up sqlitedriver 1.6.3 through its
replace of the root module. That also clears the Verify tidy failures on
the api and extension sub-modules, which have been red since the split.

Every module builds and vets. Postgres, sqlite, a2a, a2aremote and
engine pass, and mongo passes on mongo:7.
@juicycleff
juicycleff force-pushed the fix/ci-module-versions-and-docs-format branch from 991fba9 to be3cd3c Compare September 3, 2026 14:53
weave 1.6.3, nexus 1.6.4, mongo-driver 2.8.2 and sqlite 1.58.0, with
every sub-module tidied to match. extension needed that most, since it
was carrying a go.sum with no entry for the new nexus and would not
build without it.

The root go.mod also loses `replace github.com/xraph/fabriq/core =>
../../../TwinOS/fabriq/core`. Nothing in the root module requires
fabriq/core, so go was already ignoring the line, and taking it out
changed go.sum by zero lines. It pointed at a path that exists on one
machine, and fabriq/core v1.6.4 is published now, so it was residue from
the split.

Postgres, sqlite, engine, a2a, a2aremote and grpcbind pass, and mongo
passes on mongo:7. Every module builds, vets and is tidy-clean. gofmt,
golangci-lint and the docs lint are all clean.
@juicycleff
juicycleff merged commit a5218f4 into main Sep 3, 2026
17 checks passed
@juicycleff
juicycleff deleted the fix/ci-module-versions-and-docs-format branch September 3, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant