Skip to content

Bring the mobile client to parity with the web app #22

Bring the mobile client to parity with the web app

Bring the mobile client to parity with the web app #22

Workflow file for this run

name: Combat parity
# The golden vectors in `contracts/test-vectors/` are what AGENTS.md calls the
# cross-language enforcement for combat-simulator parity — and until this workflow
# existed, nothing ran them. Coverage covers backend/frontend/shared, Verifier covers
# `verifier`, and the three suites that actually replay the vectors were covered by
# neither:
#
# protocol tests/combat/goldenVectors.test.ts (the canonical TS engine)
# protocol tests/combat/equipmentVectors.test.ts (gear, roadmap §4)
# services/indexer-go internal/combat/combat_golden_test.go (the independent Go port)
# services/indexer-go internal/combat/equipment_golden_test.go (gear, the same file)
# contracts/ethereum test/XpFormula.test.ts (the XP fixture)
#
# `equipment.json` is read by the two live ports only — the frozen Solana port predates
# equipment and never applies it, so it is not a witness to that file. Its first case
# reproduces a `battle.json` row, which is how an ungeared fight is proven unchanged.
#
# §F's circuit breaker only has value while the TS and Go ports are independent and both
# match the vectors. A drift that CI never runs is a circuit breaker nobody armed.
#
# Deliberately not path-filtered. A parity break is caused precisely by changing one side
# and not the other, so filtering on either side's paths would skip the run that matters.
# See the image-generator workflow for what path filtering costs here.
#
# Anchor's frozen Rust suite is the fourth witness and is NOT run here: it needs a Solana
# toolchain this runner does not have. That gap is real — those tests are the only
# remaining independent evidence that the vectors describe what actually settled on chain.
on:
pull_request:
branches: [main]
push:
branches: [main]
permissions:
contents: read
concurrency:
group: parity-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
typescript:
name: protocol + contracts
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
# Hardhat 3 needs >= 22.10. It calls `.flatMap` on the iterator from
# `Map.values()`, which is an Iterator Helpers method that does not exist
# before Node 22, so `compile` dies with a TypeError rather than a version
# check. Do not drop this back to 20 to match the other workflows.
node-version: 22
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
# The canonical engine, including tests/combat/goldenVectors.test.ts.
- name: Protocol tests
run: pnpm --filter @cryptopets/protocol test
- name: Protocol lint
if: always()
run: pnpm --filter @cryptopets/protocol lint
# MIT boundary: protocol must not import from a PolyForm package, or the public
# verifier that depends on it cannot be distributed. Enforced by its own test, run
# above — this step exists so the typecheck failure is separately legible.
- name: Protocol typecheck
if: always()
run: pnpm --filter @cryptopets/protocol typecheck
- name: Compile contracts
if: always()
run: pnpm --prefix contracts/ethereum compile
- name: Contract tests
run: pnpm --prefix contracts/ethereum test
go:
name: indexer-go
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: services/indexer-go/go.mod
cache-dependency-path: services/indexer-go/go.sum
- name: Vet
working-directory: services/indexer-go
run: go vet ./...
# Unit tests only. The Postgres-backed tests are gated on TEST_DATABASE_URL and
# truncate tables, so they are deliberately not given one here.
- name: Test
working-directory: services/indexer-go
run: go test ./...
- name: Build
working-directory: services/indexer-go
run: go build -o /dev/null ./cmd/indexer