CI review batch

28 Sept 2026 · py-mkt, mono-volt, next-ops, crowdvolt-infra · everything below links to its PR

What shipped, what is waiting for your review and in which order to merge it, plus two mono-volt decisions only you can make.

  • Shipped. Every py-mkt deploy and every PR-label run now posts one Snorlax card in #ci-integration, named by app. Child jobs no longer post their own messages.
  • Waiting on you. Five PRs: the API journeys suite, a testing guideline backed by a suite audit, a slim CLAUDE.md, and the mono-volt and next-ops agent files.
  • Biggest finding. About 12k of 17.5k py-mkt tests never run in CI. Run locally, 527 of them fail or error, and most of those failures are real rot.
  • Blocked on you. mono-volt web production has not updated since 26 Sept. Fifteen merges are built but unpromoted because its Jenkins deploy trigger points at a dead host.

Waiting on review, in merge order

None of these are merged. The order avoids dead links and conflicts between them.

PRWhatSizeState
py-mkt #4147Backend E2E becomes API journeys: 4 tests to 39, across sync and async APIs25 files, +2,759 / -1,1573 real runs green
py-mkt #4145Test-writing guideline and a fix to the stale integration-test skillDocsready
py-mkt #4144CLAUDE.md and AGENTS.md cut to the rules every task needs417 to 145 linesafter #4145
mono-volt #2975Mobile rollout and worktree rules move into mono-voltDocswith #4144
next-ops #1794First CLAUDE.md for next-ops: entity pickers, backend catalogsDocswith #4144

API journeys replace the 4-test backend E2E

The old gate ran 4 checkout tests. There is no k6 anywhere in our repos, only a stale manual Locust file, so the suite stays in pytest on top of the existing real sign-in and Stripe test-mode plumbing. It runs against the same per-build test stack, in parallel with integration.

39tests, up from 4
55 to 63stest time on builds 987, 988, 990
3m 06s to 3m 20swhole job, same as the old suite, far under integration's 8 to 15 min
JourneyWhat it proves
Auth and sessionOTP, sign-up to /me, refresh, logout revokes on both APIs, forged and missing tokens rejected
BrowseEvent list by venue in date order, details and order book follow a new lowest listing, venue pages agree
Buy9 wallet cases with literal buyer totals and seller payouts, order cards, transfer status, book quantity, buy limits
SellListings created through the real API, edits and cancels visible everywhere, conflict and range errors
OffersPlace, withdraw, and a seller filling an open offer on the bidder's own payment intent
AuthorizationOne member cannot see or change another member's listing, cart, offer or order
MoneyA sale credits the seller as pending, withdrawal rules, notifications to both sides
Home and accountHome, feed and explore show upcoming events for the area, saved events and notifications across both APIs

The suite also turned up five API behaviour bugs, written up in #4147 and not fixed there. Read those before merging.

Kept on purpose: the Jenkins job path, the ci/e2e status and the ci/run-e2e label, because JCasC and other repos use them.

Testing guideline, built on an audit

An audit of about 17.5k tests in 1,699 files found the problems below. Each one maps to a rule in docs/testing/README.md, and every good and bad example in it comes from our own code.

~12ktests never run in CI
527of those fail or error when run on main, about 190 from a stale local schema
1,116mock references despite the no-mocks rule
158sleeps and no fake clock anywhere
ProblemRule that answers it
Integration job runs one directory plus a hand-kept file listEvery test runs in CI, no parked tests
Tests insert rows and assert the read path echoes themArrange through production paths and shared builders
1,038 call-count asserts, 1,058 private attribute readsAssert observable outcomes with literal expectations
Constructor drift in tests nobody runsFakes behind interfaces, and CI inclusion so drift fails fast
Wall-clock time, literal dates and IDsInject now, relative dates, generated IDs
About 257 tests skipped wholesale for monthsEvery skip has a reason, issue, owner and date
Money-moving services with little or no coverageUnit and integration coverage required for money and ticket paths

Proposed next: a non-blocking CI lane that runs every test directory, fix or delete failures area by area, then make it blocking. After that a lint that stops new mock imports, with today's files as a shrinking allowlist.

Agent docs: one short core, detail on demand

The root CLAUDE.md, which AGENTS.md links to, loaded about 10k tokens into every Claude and Codex task, mostly procedure for specific jobs. The new core keeps the rules every task needs and links the rest. Every moved section went verbatim, and #4144 maps each old section to its new file.

417 to 145lines in the root file
5,518 to ~1,100words loaded every task
0rules dropped
MovedNew home
cvdev manual, ports, modes, mobile tailnet, seed commands, branch-name mathdocs/dev/stack.md
RBAC endpoint stepsdocs/rbac/adding-endpoints.md
Ohm category stepsdocs/ohm/adding-a-category.md
Data-layer query referencedocs/data-layers.md
Deferred-import internalsdocs/ci-cd/deferred-imports.md
Mobile rollout and worktree rulesmono-volt CLAUDE.md
Entity pickers, RBAC and Volt Desk catalogsnext-ops CLAUDE.md

Already shipped

One card per PR-label run

infra #253py-mkt #4142mono-volt #2974
  • Suite, e2e, integration, parity, prod-replica and visual runs post one card with a row per job, the PR title and author, and Argos results for visual runs.
  • Children run with NOTIFY_SLACK off, so the repeated per-job messages stop. The first run of each child job may still post once while Jenkins registers the parameter.

App name in every deploy headline

infra #254
  • Deploy cards read "Deploying py-mkt" and "py-mkt deployed to production". PR cards read "Checking mono-volt #2974: visual".

Two mono-volt decisions

Vercel builds every mono-volt merge but assigns the domain only when something promotes a build. Jenkins mono-volt cd is meant to do that, but it has never run: its GitHub webhook still points at the retired Jenkins host and every delivery fails. Production is still on 8f91bf7 from 26 Sept.

  1. Promote now. Ships the 15 waiting merges, including the sell flow's "Add new" and the flag-gated billing ZIP. Vercel keeps an instant rollback to 8f91bf7.
  2. Turn the pipeline on. Repoint the webhook to the live Jenkins and fix deploy-prod's Cloudflare credential id, so each merge runs web integration and promotes. Then mono-volt gets its own Snorlax deploy card.