Skip to content

Drift check: harden classifier and add coverage/infra-failure buckets#27

Merged
dkijania merged 1 commit into
fix/account-with-token-and-schema-refreshfrom
feat/two-layer-drift-check
May 27, 2026
Merged

Drift check: harden classifier and add coverage/infra-failure buckets#27
dkijania merged 1 commit into
fix/account-with-token-and-schema-refreshfrom
feat/two-layer-drift-check

Conversation

@dkijania
Copy link
Copy Markdown
Member

Stacked on #26 — review/merge that one first; rebase this on master afterward.

Summary

Two-layer schema-drift checker:

  1. Introspection diff (Layer 1) — now also detects argument-type changes (e.g. UInt64 → TokenId) and inputField-type changes that the previous version silently passed. The exact bug fixed in Fix GET_ACCOUNT_WITH_TOKEN type + refresh schema snapshot #26 is the kind of drift this layer is supposed to catch.
  2. Live query check (Layer 2) — parses src/mina_sdk/daemon/queries.py, sends each operation with sentinel variables, classifies GraphQL errors. Drift patterns are matched against the message before the path-based runtime fallback (Mina attaches path to many validation errors, so the previous path-first short-circuit dropped real drift to runtime). Bare "expected type" was removed from drift patterns (false-positives on value coercion); a regex for the "expected on field X, found Y" shape routes those to runtime.

Hardening (from internal review)

  • httpx.Client with 30 s timeout
  • HTTP status check (non-2xx → error; was silently treated as "OK" when body parsed but had no errors key)
  • normalize_schema raises on error envelopes — no silent fake-empty schema that flagged every type as REMOVED
  • _name_of safe against null / non-dict entries in introspection arrays
  • kind nil-guard avoids spurious <None> -> X diffs
  • _OP_RE filters to bodies that actually start with query|mutation|subscription, so unrelated triple-quoted constants don't get probed
  • _VARS_RE anchored to body start so inner field-arg parens like bestChain(maxLength: 1) can't bind
  • Connection / HTTP errors counted as infra failures, not drift; always exit 1
  • SKIPped ops (stale sentinel table) fail in --strict

Test plan

  • Clean run against compatible-latest-lightnet in --strict: exit 0, 11 ok, 0 drift, 2 runtime, 0 skipped, 0 infra-failures.
  • Same negative cases as the Go PR (arg-type drift, inputField-type drift, unknown-field, unknown input type, unreachable port) all behave as expected.

🤖 Generated with Claude Code

Two-layer schema-drift checker for the SDK:

1. Introspection diff: compare src/mina_sdk/schema/graphql_schema.json
   to the live __schema; now also detects argument-type changes
   (e.g. UInt64 -> TokenId) and inputField-type changes that the
   previous version silently passed.

2. Live query check: parse src/mina_sdk/daemon/queries.py, send each
   operation with sentinel variables, classify GraphQL errors as
   either schema drift (parse/validation) or runtime (auth, value-
   validation). Drift patterns are matched against the message
   BEFORE the path-based runtime fallback - Mina attaches `path` to
   many validation errors, so a path-first short-circuit silently
   drops real drift to the runtime bucket. Bare "expected type"
   was removed from drift patterns (false-positives on value
   coercion); a regex for the "expected on field X, found Y"
   shape now routes those to runtime explicitly.

Hardening from internal review:
- httpx.Client with 30s timeout (was bare httpx.post call per request)
- HTTP status check (non-2xx -> error; was relying on raise_for_status
  in one path and silently treating empty errors[] as OK in another)
- normalize_schema raises on error envelopes - no silent fake-empty
  schema that then flags every type as REMOVED
- _name_of sort key safe against null / non-dict entries
- kind nil-guard avoids spurious "<None> -> X" diffs
- _OP_RE filters to bodies that actually start with an operation
  keyword, so unrelated triple-quoted constants don't get probed
- _VARS_RE anchored to body start, so inner field-arg parens like
  `bestChain(maxLength: 1)` can't bind
- Connection / HTTP errors counted as infra failures, not "drift";
  always exits 1 (we can't trust the result either way)
- SKIPped ops (stale sentinel table) fail in --strict

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dkijania dkijania merged commit fa70dc8 into fix/account-with-token-and-schema-refresh May 27, 2026
@dkijania dkijania deleted the feat/two-layer-drift-check branch May 27, 2026 19:22
@dkijania dkijania mentioned this pull request May 27, 2026
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