Skip to content

Observe nextMetaId across a multi-event, multi-board matchstick run - #289

Open
thedavidmeister wants to merge 2 commits into
mainfrom
2026-08-25-issue-229
Open

Observe nextMetaId across a multi-event, multi-board matchstick run#289
thedavidmeister wants to merge 2 commits into
mainfrom
2026-08-25-issue-229

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Closes #229.

The matchstick suite never ran a second handleMetaV1_2 event against one store, and never loaded a MetaBoard back to look at nextMetaId. So everything the counter does — start at zero, advance by one per meta, persist that advance, and count only the metas of the board it belongs to — was unobserved. Two tests now observe it.

What changed

Test-only. subgraph/src/metaBoard.ts is untouched.

  • subgraph/tests/metaBoard.test.ts: Test MetaBoard nextMetaId counter, two tests, both driving their batch through handleNewMetaV1Events — the helper subgraph/tests/utils.ts has exported since it was written and no test ever called, which is the issue's observation 3.
    • nextMetaId counts one per meta the board has seen: three events on one board, then MetaBoard.load(...).nextMetaId == 3 and entityCount(MetaV1) == 3.
    • Each metaboard counts only its own metas: two events on one board and one on another, then entityCount(MetaBoard) == 2 and each board's own counter, 2 and 1.
  • subgraph/tests/utils.ts, subgraph/tests/address.ts: createNewMetaV1Event takes the emitting board instead of hardcoding CONTRACT_ADDRESS, and there is a second board address to hand it. A test cannot reach a two-board store otherwise. These two hunks are byte-identical to Scope the MetaV1 entity id to its metaboard #282's — see below.

The prettier-rainix pre-commit hook collapsed a pre-existing multi-line import { MetaV1_2 } in the test file. That is the hook's rewrite, not an edit of mine; the commit does not land without it.

How this stacks on #282

#282 (issue #206) changes the MetaV1 id from the bare counter to <board>-<counter> and adds two tests of its own. The overlap, and what I did about it:

QA

subgraph-test runs matchstick under docker compose and there is no docker on this machine. I ran the matchstick 0.6.0 binary-linux-22 release directly against subgraph/ instead — the version matchstick-as@0.6.0-beta.2 in subgraph/package.json targets — after forge soldeer install && forge build && npm ci && graph codegen. The MetaBoard Subgraph CI lane on this branch is the authority, and it has since run green on this commit — the docker matchstick reports the same All 12 tests passed, the two new tests included. Baseline before the change (direct binary): All 10 tests passed.

  • Discriminating tests: nextMetaId counts one per meta the board has seen and Each metaboard counts only its own metas. Neither can fail on base, because the behaviour they assert is not a defect — base is correct and unobserved. So each was verified against mutants of the base behaviour instead, below: M1/M2/M3 fail both, M4 fails only the first, M5 fails only the second. Every one of the 10 pre-existing tests stays green under M1–M5, which is the gap the issue filed.
  • Mutations applied (each a full re-run of the matchstick suite against subgraph/src/metaBoard.ts on this branch; "existing" = the 10 tests already in the file):
    • M1 metaBoard.nextMetaId = metaBoard.nextMetaId.plus(BigInt.fromI32(1)) -> line deleted -> 2 failed, 10 passed. Killed by both new tests (entityCount(MetaV1) 3 != 1, and nextMetaId 0 != 2); every existing test green. The issue's mutant 1.
    • M2 same line -> plus(BigInt.fromI32(2)) -> 2 failed, 10 passed. Killed by both new tests (nextMetaId 6 != 3 and 4 != 2); every existing test green. The issue's mutant 1.
    • M3 the final metaBoard.save(); -> deleted -> 2 failed, 10 passed. Killed by both new tests; every existing test green. The issue's mutant 1.
    • M4 new MetaV1(metaBoard.nextMetaId.toString()) -> new MetaV1("0") -> 1 failed, 11 passed. Killed by nextMetaId counts one per meta the board has seen on entityCount(MetaV1) 3 != 1 — three events, one surviving entity. The issue's mutant 2. The two-board test correctly does not fire: it makes no MetaV1 claim.
    • M5 MetaBoard.load(event.address) -> MetaBoard.load(Bytes.fromHexString("0xfb84…6928")), i.e. one global board rather than one per emitting address -> 1 failed, 11 passed. Killed by Each metaboard counts only its own metas on entityCount(MetaBoard) 2 != 1. The issue's observation 4. The single-board test correctly does not fire.
    • M6 metaBoard.nextMetaId = BigInt.fromI32(0) -> BigInt.fromI32(1) -> 3 failed, 9 passed. Killed by both new tests and by the existing Checks MetaV1 entity data.
    • M7 the metaBoard.save(); inside the if (!metaBoard) block -> deleted -> 12 passed, SURVIVES. Equivalent mutant: the metaBoard.save() at the end of the handler persists the same entity, so the inner save is unobservable by construction. Recorded as equivalent, not claimed as covered.
  • Oracle: subgraph/schema.graphql, where nextMetaId: BigInt! sits on MetaBoard and so counts per board, and the handler's one-event-one-MetaV1 contract. The expected values are literals (3, 2, 1) read off the number of events each test emits, not computed the way the mapping computes them, so a test cannot agree with the mapping by restating it. Nothing here reads back a value the mapping wrote to decide what it should be.
  • Category check: the issue asks for four things — (1) nextMetaId's increment and its final save() observed, (2) the MetaV1 id not collapsible to a constant, (3) the unused handleNewMetaV1Events batch helper exercised, (4) the two-board path exercised. Covered: (1) by M1/M2/M3, (2) by M4 via entityCount rather than an id literal — deliberately, so the assertion survives Scope the MetaV1 entity id to its metaboard #282's id-scheme change — (3) both new tests drive their batch through it, (4) by the second test and M5. The issue's closing line also floats asserting "the second MetaV1 id"; that literal is the one assertion that would pin the id scheme Scope the MetaV1 entity id to its metaboard #282 is changing, so it is left to Scope the MetaV1 entity id to its metaboard #282, which already spells out FIRST_BOARD_SECOND_META_ID. Cross-board MetaV1 identity is likewise out of scope here: on main those ids collide, and asserting the count main produces would write MetaV1 entity id collides across metaboards: the indexer implied by IDescribedByMetaV1 can lose retrieval-by-hash #206's defect into the suite.
  • subgraph/tests/.bin/metaboard.wasm is a tracked matchstick build artifact last written in 2024 and already stale against test changes since. My runs rewrote it; I restored it rather than commit a rebuild, as Scope the MetaV1 entity id to its metaboard #282 did.
  • Not run locally: the forge suite and the Rust crates. Nothing here is Solidity or Rust; CI on this branch covers them.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 52 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d7f23977-f9d7-42b4-96e6-ca3f2fcc571d

📥 Commits

Reviewing files that changed from the base of the PR and between 0512d52 and 084f784.

📒 Files selected for processing (1)
  • subgraph/tests/metaBoard.test.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

#282 and #291 landed the id-scoping work this branch was written
alongside. Both sides appended a describe block to metaBoard.test.ts;
the resolution is the union. The utils.ts and address.ts hunks here were
written byte-identically to #282's and reached main with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

subgraph: matchstick suite never observes nextMetaId or any multi-event path

1 participant