Skip to content

chore(sync): develop → main — the Tracker↔Core seam is now tested by CI - #145

Merged
beyondnetPeru merged 1 commit into
mainfrom
develop
Aug 5, 2026
Merged

chore(sync): develop → main — the Tracker↔Core seam is now tested by CI#145
beyondnetPeru merged 1 commit into
mainfrom
develop

Conversation

@beyondnetPeru

Copy link
Copy Markdown
Contributor

Brings #144 to main.

core-integration asserts the six interfaces of the Tracker↔Core pair and had never run in this pipeline — it needs the Core, another product, which nothing here deployed. The seam was verified by hand or not at all. The first time it ran against a real stack it found three defects invisible to every other suite, two of them product defects, one in each repository.

CI now pulls the Core's three service images from GHCR at a pinned SHA (never latest, so a defect merged in the other repo cannot turn these pull requests red), deploys them with a minimal fixture of this repo's own, runs the full robot suite, and retires the fixture immediately — it is scaffolding for one step, and leaving it standing changes the conditions of every step after.

Verified on the runner: 242 passed · 0 failed, core-integration included.

🤖 Generated with Claude Code

…d by CI (#144)

* feat(ci): deploy the Core from GHCR so the Tracker↔Core seam is tested by CI

`core-integration` asserts the SIX interfaces of the pair and had never run
in this pipeline: it needs the Core, another product, which nothing here
deployed. So the seam was verified by hand or not at all. The first time
it ran against a real stack it found three defects invisible to every
other suite, two of them product defects — one in each repository.

The Core already publishes all three service images to GHCR on every
merge to its main, tagged with the commit SHA as well as `latest`. That
SHA tag is what makes this safe to wire.

PINNED, not `latest`, and the file says why: following the Core's tip
would turn this repository's pull requests red for a defect merged
minutes earlier by someone who has never seen this pipeline. A pinned SHA
moves that failure into a diff with a reviewer. The accepted cost is that
`core-image.sha` goes stale on purpose and somebody has to raise it — the
same discipline the charts already use for their own tags.

The Core is deployed by a MINIMAL manifest of this repository's own, not
by vendoring its charts: those live in the other repo, would drift here,
and would drag in OPA sidecars, HPAs and IngressRoutes this test neither
needs nor can maintain. It is a fixture, and it says so. It pins uid 1001
because pinning 1000 is what made the deployed MCP unable to read its own
policy.wasm (evolith_arch32#425).

`core-integration` enters the robot list only when the Core is actually
present, and when it is absent the run SAYS so instead of quietly
shrinking — a suite that silently drops its only cross-product robot
reads exactly like one that passed it.

The gateway also joins the local install: steps 1-4 of that robot go
through it, which is part of why the robot was excluded.

Verified on a live kind cluster, not argued: the Core rolls out from the
pinned refs, the gateway reaches it by in-cluster DNS, and the full suite
runs 11 robots — 242 passed, 0 failed, `core-integration` 13/13. Both
branches of the inclusion predicate were exercised.

NOT verified here, and stated rather than implied: the `docker pull`
itself. The packages are PRIVATE, which the first local attempt proved by
answering `unauthorized` — and that failure is what exposed the two things
missing from this wiring, now fixed: `packages: read` on the workflow and
a GHCR login step before the pull. The local run used the same image refs
loaded by hand, so everything downstream of the pull is proven and the
pull is exercised the first time this lands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(ci): one local key, not three, for the same deployment

CI ran the seam for the first time and failed on exactly one check:
`POST /assistant/converse` → 502. The cause is a three-way mismatch that
existed before this change and could not be seen until now.

The same local deployment carried three different credentials: this
script wrote `local-only-not-a-real-key-core` and
`local-only-not-a-real-key-runtime`, while the gateway chart defaults to
`local-dev-key`. With the Core outside the cluster nobody ever
authenticated against it, so nothing disagreed. The moment the Core came
in, every step that goes THROUGH the gateway passed — both ends were
`local-dev-key` — and the one step that goes straight from tracker-api to
the agent-runtime got 401.

What made it expensive to read: that 401 reaches the caller as 502
(LV-26), so a credential problem arrives dressed as an availability
problem. It cost time on a laptop two days ago and it cost this run.

One key everywhere now. It is a local test credential and its name says
so; the value does not matter as long as all three agree.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(ci): point tracker-api at the Core this pipeline deploys

Step 6 of `core-integration` kept returning 502 and the previous commit
blamed the wrong thing. Aligning the local keys was correct on its own —
three credentials for one deployment is a defect — but it was not this.

`values-local.yaml` points the tracker-api at
`evolith-runtime-evolith-agent-runtime.evolith-local`: the service names
the CORE's Helm chart generates, in the Core's own namespace. This
pipeline has neither. It deploys a minimal fixture as `core-agent-runtime`
in `evolith-core-local`, so the tracker-api was calling a host that does
not resolve — and an unresolvable host surfaces as 502, which reads as
"the runtime is down" rather than "the URL points nowhere".

I set these by hand on a laptop two days ago and never wired them into
`install()`. CI ran the path I had only ever run manually, and that is
precisely what it is for.

Set unconditionally, including when the Core is absent: it is
configuration, not a boot dependency, and a nonexistent host fails
exactly as the previous one did.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(ci): retire the Core fixture before the production redeploy

The robots pass — 242, 0 failed, `core-integration` included — and the
step AFTER them broke: the production redeploy timed out with
`context deadline exceeded`.

Not resource pressure, which is what I assumed first. The log names it:
the tracker-api's readiness probe runs a `core-capabilities` health check
that calls the Core, and under the PRODUCTION profile `networkPolicy` is
enabled, blocking egress to the Core's namespace. The call hangs until it
cancels, the pod never reaches Ready, and helm --wait gives up after five
minutes. Without a Core the same URL simply does not resolve and fails
fast, which is the condition that step was written under and why it has
been green on develop for months.

So the fixture is retired as soon as the test that needs it is done. It
was never part of the Tracker's deployment; it is scaffolding for one
step, and leaving it standing changed the conditions of every step after.

`if: always()` so a failing robot run still cleans up and the production
steps are judged on their own terms.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@beyondnetPeru
beyondnetPeru merged commit 705457b into main Aug 5, 2026
16 checks passed
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