Skip to content

feat(conformance): engine conformance harness + adjudicated TiDB scoreboard (slice 1)#371

Merged
vsai12 merged 33 commits into
mainfrom
feat/conformance-harness
Jul 8, 2026
Merged

feat(conformance): engine conformance harness + adjudicated TiDB scoreboard (slice 1)#371
vsai12 merged 33 commits into
mainfrom
feat/conformance-harness

Conversation

@vsai12

@vsai12 vsai12 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Why

Manager directive: full compatibility across engines, proactive rather than customer-request-driven — so we measure first. This PR lands the measuring instrument and the first measurement. The bar it tracks: GAP = 0 on the upstream lane at pinned engine versions (omni never falsely rejects SQL the engine accepts); OVER (over-accepts) is triaged, not chased; INDETERMINATE is surfaced, never silently dropped. Full design: 2026-07-07-omni-full-compatibility-conformance-design.md in the workspace plans directory (not in this repo).

What

harness/conformance/ — a standalone Go module (replace => ../.., so it always sweeps the working-tree omni):

  • fetch_corpus.sh sparse-clones pingcap/tidb at v8.5.5 into a gitignored dir (fetch-don't-vendor).
  • A go/ast extractor harvests every pre-labeled {src, ok} testCase literal from the upstream parser tests — 3,838 statements, zero-loss over self-labeled test tables ({src, ok} / {src, err}; elements it cannot read statically become SKIP rows with provenance instead of vanishing; loop-generated runtime cases appear as unexpanded generator-site SKIP rows, counted on the board).
  • Every statement gets an omni verdict (panic-safe: a panic is a reject with a marker, and itself a finding).
  • -adjudicate probes every non-agreeing row against a live pinned TiDB container: fresh session per row (session state would change how later statements parse); SHUTDOWN/KILL/RESTART variants never reach the shared oracle.
  • Output: committed deterministic scoreboard (scoreboards/tidb.md — its git history is the progress report) + gitignored full-provenance JSONL (out/tidb.jsonl, meta line first; the JSONL retains raw codes/messages/labels, so reclassification needs no container re-run).

CI-invisible: the sweep is a binary, not a test; in-repo tests are unit tests plus a -short-gated corpus smoke. Omni CI never touches Docker.

First adjudicated TiDB scoreboard

3,838 harvested → 57 duplicates dropped → 3,781 statements, all divergences container-adjudicated:

class statements clusters
AGREE_ACCEPT 2,001
AGREE_REJECT 479
GAP (TiDB accepts, omni rejects) 1,133 71 (container-confirmed)
OVER (TiDB rejects, omni accepts) 158 45
INDETERMINATE 9
SKIP 1

Top GAP clusters (full ranked burn-down list = the GAP table in scoreboards/tidb.md):

cluster count exemplar
TiDB operational stmts (SPLIT/BACKUP/TRACE/CALIBRATE/…) 173 trace begin
SELECT 112 SELECT SCHEMA();
ADMIN 76 admin show ddl;
CREATE sequence/binding/statistics 73 create sequence seq
ALTER TABLE misc syntax 68 ALTER TABLE db.t RENAME db1.t1

Caveat: the largest clusters are coarse family buckets, not single grammar items — omni's uniform "syntax error at or near …" text under-splits distinct gaps, so 71 clusters is a lower bound on distinct grammar work items; the JSONL supports finer slicing when scoping burn-down PRs.

INDETERMINATE 9 = 3 KILL variants (unsafe to execute against the shared oracle), 1 LOAD STATS + 3 PLAN REPLAYER local-file infra refusals (not parse verdicts), 2 label-vs-container disagreements.

Verdict lattice, not 1064-only

TiDB rejects at parse time with 26 distinct error codes, enumerated from the parser source in the pinned v8.5.5 corpus checkout (yacc 1064/1149, AppendError/return-1 grammar-action aborts, ast-validator codes) and verified by live PREPARE-oracle probes. 47 label-reject rows carry non-1064 parse-abort codes — 44 through the specific-code arms, 3 through 1149. A 1064-only classifier would have mis-queued all 47 as label/container disagreements. Codes that also occur at runtime fail closed to INDETERMINATE, never a silently wrong class.

Reviews

Every task went through a two-stage review (spec compliance + code quality) with container-grounded verification; determinism proven by byte-identical scoreboard re-sweeps against fresh containers.

Next

  • Slice 2: MariaDB mtr extractor — context threading (sql_mode / .opt server flags / ANSI_QUOTES changes lexing); --error annotations give a labeled reject-space.
  • Slice 3: StarRocks FE-test extraction.
  • Burn-down sequencing decided after all three engines are measured (cluster counts are the work metric).
  • Follow-up: harvest curated []string parser tables (TestTableSample-class — labels live in consuming assertions, needs per-site verification); bundle with the first corpus-tag re-baseline.

🤖 Generated with Claude Code

vsai12 and others added 15 commits July 7, 2026 13:33
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ardening

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Walks corpus/tidb/pkg/parser/*_test.go and extracts every []testCase{src,
ok, restore} composite literal into CorpusEntry rows (positional and keyed
forms, raw-string and "a"+"b" concatenated literals). Non-literal srcs
skip with a reason instead of crashing. Short-gated smoke test guards
extraction health against the fetched corpus: 3838 entries (3192 accept /
645 reject / 1 skip), matching a whole-file AST cross-check of all 55
tables.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rows

Non-composite []testCase elements now emit a provenance-carrying
non_composite_element skip entry instead of vanishing, and the smoke test
gains an independent flat whole-file element count (sees package-level
tables too) asserted equal to the extracted-entry count — the review's
out-of-band zero-loss check is now a regression gate for corpus tag bumps.
Fixture adds the two most fidelity-sensitive literal shapes (interpreted
escapes incl. \r\n and escaped quotes; multi-line raw string) with
exact-bytes assertions, plus a bare-identifier element row. Documents the
name-only syntactic match assumption on isTestCaseSlice.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
omniTiDBVerdict runs one statement through the omni tidb parser and
maps the result to a Verdict. Panics are recovered into a reject with a
PANIC: marker — corpus statements must never crash the sweep, and
panics are themselves findings.

go mod tidy wires github.com/bytebase/omni via the existing replace;
the harness build compiles only tidb/{parser,ast} + stdlib (the go.sum
entries beyond that are sums for tidb/parser's testcontainers-based
test imports, not build deps).

Full-corpus containment probe (throwaway, deleted): 3838 entries =
2193 accept / 1644 reject / 0 PANIC / 1 skipped(no sql).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st main

First committed TiDB scoreboard (upstream lane, pre-adjudication).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…edup conflict guard

- clusterRows: exemplar tie-break made total (shortest SQL, then
  lexicographic; first-row sentinel via Count==1 so an empty SQL cannot
  be stolen) — rendering no longer depends on row order
- clusterRows: skip non-upstream lanes, matching the headline counts
- buildRows: dropped duplicate with a conflicting upstream label flips
  the kept row to INDETERMINATE (duplicate_label_conflict); counted in
  run meta as duplicate_label_conflicts (zero in this corpus)
- scoreboard: rename duplicate_count -> duplicates_dropped (wire name),
  add duplicate_label_conflicts line
- truncate: rune-safe (back off to a rune boundary)
- writeJSONL: buffered writer, flush + explicit close error propagation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Renamed counts lines, duplicate_label_conflicts (0), and 3 tied-cluster
exemplars now resolved by the total tie-break. Counts unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
-adjudicate probes every non-agreeing row (GAP/OVER/INDETERMINATE)
against the pinned pingcap/tidb:v8.5.5 container and reclassifies with
the container as ground truth. Agreeing rows are untouched.

Verdict lattice grounded in the vendored v8.5.5 parser source and
verified against the live oracle: parse-reject = 1064/1149 plus the
grammar-action and ast-validator abort codes (partition shape errors,
ErrWrongUsage, ...) that TiDB emits for parse-time rejections with
MySQL-compatible specific codes. Runtime collisions on those codes fail
closed into INDETERMINATE label_container_disagree.

Hazards handled:
- DSN is normalized to multiStatements=true (multi-statement corpus
  rows would otherwise false-reject the whole batch) with bounded
  dial/read/write timeouts; a driver timeout is a non-MySQL error and
  lands fail-closed in INDETERMINATE infra_error.
- Unsafe statements (first keyword SHUTDOWN/KILL/RESTART; the corpus
  literally contains them) are marked unsafe_to_adjudicate and never
  touch the container; if the container dies anyway, the sweep aborts
  naming the current and previous statement instead of poisoning the
  remaining rows.
- duplicate_label_conflict rows drop their arbitrary first-seen label
  before adjudication so the container becomes sole truth.
- Every row runs on a fresh connection (no idle reuse), so session
  state such as SET sql_mode cannot leak into later parse verdicts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Container-adjudicated run against pingcap/tidb:v8.5.5 (digest in meta):
1300 divergence rows probed in 8s. GAP 1141 -> 1133, OVER 159 -> 158,
INDETERMINATE 0 -> 9 (3 unsafe_to_adjudicate KILL variants, 4
infra_error driver-side LOCAL-file rows, 2 label_container_disagree).
OVER clusters collapse 101 -> 19 pre-lattice-fix, 45 after engine-
message re-keying. Fresh-container reruns are class-deterministic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- adjudicateTiDB was at cognitive complexity 19 (house gate <=15) and is
  the clone-seam for the next engines: extract probeRow (Exec + infra
  fold + container-death abort) and adjudicationCandidates, invert the
  prepare guard to an early continue. Behavior identical; existing
  tests unchanged and green.
- start_tidb.sh: export prefix on the TIDB_CONTAINER_DIGEST line (the
  documented copy-paste flow otherwise yields an unexported var and the
  scoreboard silently loses its provenance digest), and fail loudly if
  TiDB never listens within 60s.
- Lattice comment: note the fail-closed collision net requires an
  upstream label (H3-cleared rows classify from the container alone).
- Test pins: mid-batch "select 1; shutdown" stays first-statement-only
  (container-death abort is the backstop); 1102 lattice membership.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…g engines)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vsai12 vsai12 requested a review from rebelice as a code owner July 7, 2026 23:59
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1cd50d6d9a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread harness/conformance/extract_tidb.go Outdated
Comment thread harness/conformance/scoreboards/tidb.md Outdated
Comment thread harness/conformance/go.mod Outdated
Comment thread harness/conformance/adjudicate_tidb.go
vsai12 and others added 3 commits July 7, 2026 17:30
…probes

Two extraction/safety fixes from PR review:

- The extractor matched only []testCase{...} slice literals; the 12 bare
  testCase{...} composite literals in append(...) calls were silently
  omitted, violating the zero-loss invariant (a future labeled append-form
  row would be lost without a SKIP trace). Add the bare-literal arm to the
  extractor and mirror it in the countTestCaseElements cross-check; smoke
  moves 3838->3850 entries, 1->13 skips (all 12 new rows are fmt.Sprintf
  srcs, so non_literal SKIP).
- Extend the unsafe-to-adjudicate predicate with a SET PASSWORD arm
  (first keyword SET + second keyword PASSWORD): the corpus contains
  SET PASSWORD statements (parser_test.go:1386-1387), and probing one as
  root would change the oracle's credentials mid-sweep. Other SET forms
  stay adjudicable; ping-abort + disposable container remain the backstop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
go 1.26 -> go 1.25.7, exactly the omni root module: the harness uses no
1.26 features, and the higher directive blocked GOTOOLCHAIN=local users
on the repo's 1.25 toolchain. go mod tidy -diff is empty.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The committed board recorded an intermediate branch commit as omni_sha —
unreachable from main after a squash-merge. This branch never touches the
parser, so the parser under test is exactly the merge-base. Document the
rule (committed boards record a main-reachable omni_sha; harness-only
branches use `git merge-base origin/main HEAD`) and regenerate the
adjudicated board at f7991e5.

Board delta vs the previous adjudicated run: SKIP 1 -> 13 and total
3781 -> 3793 (the 12 newly-captured append-form rows, all non_literal
SKIPs); GAP/OVER/AGREE/INDETERMINATE counts and every cluster table are
byte-identical.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 78d6a96c92

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread harness/conformance/adjudicate_tidb.go Outdated
Comment thread harness/conformance/start_tidb.sh Outdated
Comment thread harness/conformance/adjudicate_tidb.go Outdated
Comment thread harness/conformance/start_tidb.sh Outdated
…scan, schemaless DSN, loopback bind

Codex round 2. Connection-scope errors are not parse verdicts: a probed
batch that mutates credentials (SELECT 1; SET PASSWORD) leaves the
container alive, so the ping-abort never fires — instead every later
fresh connection fails its handshake with 1045, which the classifier
mapped to VerdictAccept: silent verdict poisoning.

- classifier: 1045 -> VerdictNone (infra), routed to probeRow's
  ping-abort which names the culprit statement; 1049/1046/1044 stay
  statement-level "parsed" (test-pinned, reasoning in comments)
- unsafeToAdjudicate: scan every statement in the batch, not just the
  first; the naive `;` split can only over-match (documented
  false-positive direction), never miss
- SET arm: also unsafe on GLOBAL / PERSIST / @@global... / @@persist...
  (parse-affecting for every later probe, e.g. sql_mode ANSI_QUOTES);
  NAMES / sql_mode / @@session.x / @v stay adjudicable
- DSN: no default schema (droppable by adjudicated DDL -> handshake
  1049 poison); normalizeTiDBDSN forces DBName empty on user DSNs
- start_tidb.sh: bind 127.0.0.1 only (passwordless root)

Live-verified against the container: USE nonexistent -> 1049,
unqualified name -> 1046, both classify parsed; full adjudicated
re-sweep at merge-base f7991e5 regenerates the committed board
byte-identical (only gitignored JSONL raw codes shift 1146 -> 1046).

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7c8a4db59c

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread harness/conformance/adjudicate_tidb.go Outdated
Comment thread harness/conformance/adjudicate_tidb.go
Comment thread harness/conformance/extract_tidb.go
Comment thread harness/conformance/go.mod
vsai12 and others added 4 commits July 7, 2026 18:36
…obes

Two unsafe-scan escapes, both container-verified on the pinned oracle:

- /*! SET PASSWORD = 'x' */ and /*!40101 SET GLOBAL ... */ are EXECUTED
  by TiDB/MySQL but were stripped as comments before the deny-list ran.
  Executable-comment markers and their matching */ closers are now
  blanked first, so the content survives as scannable SQL; ordinary
  /* ... */ comments still strip.

- CREATE/ALTER/DROP/RENAME USER can rewrite the identity every later
  fresh connection handshakes with (ALTER USER root IDENTIFIED BY 'x'
  verified: all later handshakes fail 1045 while the container stays
  up, so the ping-abort backstop never fires). GRANT/REVOKE stay
  adjudicable: verified unable to touch connection identity (user
  auto-create refused with 1410; GRANT ... IDENTIFIED BY on an existing
  user leaves credentials untouched).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Task 4 deferred the two []testErrMsgCase tables in parser_test.go
(:5185, :5191); promote them. Semantics grounded in the corpus's
RunErrMsgTest: a non-nil err demands terror.ErrorEqual against a real
parse error (parse-reject), a nil err demands NoError (parse-accept) —
the err value only pins the message upstream, so its non-nil-ness is
the verdict. The extractor gains a third match arm (keyed and
positional; nil ident or omitted keyed err = accept, any other
expression = reject; non-literal src = provenance-carrying SKIP), and
the zero-loss cross-check counts the same arm.

Smoke movement: 3850 -> 3856 entries (+3 accepts, +3 rejects, skips
unchanged): commentMsgCases 4 rows (1 accept / 3 rejects),
funcCallMsgCases 2 rows (2 accepts).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
harness/conformance is its own Go module, so the root go test ./...
never compiles it — a compile break there shipped silently. One
-short step after the root tests: hermetic (no corpus, no Docker) and
fast; the container lane stays out of CI per the design doc.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full adjudicated sweep against the pinned oracle (1302 rows probed).
Movement vs the previous board:

- testErrMsgCase harvest (+6 rows, 1 duplicate): +3 AGREE_ACCEPT,
  +2 OVER — both the same omni bug class, over-accepting an
  unterminated /* block comment (container 1064); one joins the
  existing DELETE cluster, one opens OVER cluster 46 (`select 1/*`).
- User-account DCL deny-list: 20 GAP rows (17 CREATE USER + 3 ALTER
  USER) now INDETERMINATE unsafe_to_adjudicate instead of being
  executed against the oracle; the 4 GRANT ... IDENTIFIED BY rows
  correctly stay adjudicable (GAP).
- Executable-comment scan moved no corpus rows — prophylactic only.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2bc0ac2c4f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread harness/conformance/adjudicate_tidb.go Outdated
Comment thread harness/conformance/adjudicate_tidb.go Outdated
Comment thread harness/conformance/adjudicate_tidb.go
…mments)

unsafeToAdjudicate's pre-pass was not comment-robust (one root cause,
three bypasses): it neutralized only /*! executable markers while omni's
own splitter (tidb/parser/split.go, Segment.Empty) also treats /*T! as
executable TiDB SQL, and it stripped only LEADING ordinary comments while
the server treats comments as whitespace anywhere — so
/*T! SET GLOBAL ... */, SET /*c*/ PASSWORD = 'x', and
CREATE /*c*/ USER ... all tokenized past the deny-list.

Restructure into one normalization pipeline: (1) neutralize executable
markers — /*! and /*T!, both grounded in split.go, plus optional version
digits — keeping their content scannable; (2) strip ALL remaining
ordinary comments (/* */ anywhere, -- and # to EOL) to a single space,
skipping string literals and backtick identifiers so a comment opener
inside a literal cannot swallow the real statements that follow;
(3) THEN split on ; and scan each statement — so a ; inside an ordinary
comment no longer fabricates a phantom segment, and commented-out unsafe
text is correctly not flagged (the server never executes it). The now-
redundant leading-comment strip in unsafeStatement is removed
(classifyFamily's own leadingComment use is untouched).

Board impact: zero — old-vs-new diff over all 3799 adjudicated rows
shows no unsafe-status flips (the 29 corpus /*T! rows carry only DDL
attributes), so the fix is purely prophylactic and the committed
scoreboard stands.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a999786114

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread harness/conformance/adjudicate_tidb.go
Comment thread harness/conformance/adjudicate_tidb.go
Comment thread harness/conformance/adjudicate_tidb.go
Comment thread harness/conformance/adjudicate_tidb.go Outdated
vsai12 and others added 2 commits July 8, 2026 13:19
Round-5 review fixes for the unsafe-statement scan, each grounded on the
pinned oracle (corpus v8.5.5 scanner source + live container probes):

- /*T![feature_id,...] bracket groups are part of the executable-comment
  marker (scanFeatureIDs, corpus lexer.go:972-1015): blank a well-formed
  group along with the marker so the gated content - which the server
  executes, even when the comment is unterminated - reaches the keyword
  scan. Malformed groups stay visible instead: the oracle re-scans them as
  content whose leading bracket junk parse-errors the whole batch, so
  nothing in them executes. /*! takes only version digits, never a bracket
  group (corpus lexer.go:530-535).
- Nested block comments: refuted against the oracle and pinned instead of
  changed. TiDB's scanner ends every block comment at the FIRST */ with no
  depth counter (corpus lexer.go:578-600; container-verified: the text
  after the first */ of an unterminated nested comment executes). omni's
  own lexer/splitter DO nest - an omni-vs-TiDB divergence the board
  measures; a nesting-aware strip would mirror omni instead of the oracle
  and wave a live KILL through.
- SET CONFIG joins unsafeSetTarget: it mutates dynamic cluster/component
  configuration, which outlives the probe's session. The arm keys on the
  CONFIG keyword because the target may be a string literal.
- probeRow: pin why whole-batch Exec is verdict-correct for multi-statement
  rows - TiDB parses the FULL batch before executing anything (verified
  live: CREATE TABLE t(a int); SELECT FROM -> 1064, not 1046, and the
  CREATE provably never executes).

Board impact: the six upstream SET CONFIG rows flip GAP -> INDETERMINATE
unsafe_to_adjudicate; no other flips.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pped

Full adjudicated re-sweep against the pinned oracle at merge-base
omni_sha. GAP 1113 -> 1107, INDETERMINATE 29 -> 35: the six SET CONFIG
rows leave the probe path (unsafe_to_adjudicate) and the SET GAP cluster
shrinks 14 -> 8. All other counts byte-identical.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89869a5b06

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread harness/conformance/adjudicate_tidb.go
Comment thread harness/conformance/adjudicate_tidb.go
Comment thread harness/conformance/adjudicate_tidb.go
Comment thread harness/conformance/adjudicate_tidb.go Outdated
vsai12 and others added 5 commits July 8, 2026 14:05
…eutralizer, feature-gate union, multi-assignment SET)

QUERY WATCH ADD/REMOVE persists runaway-query watch rules server-side; an
ACTION KILL rule can kill later probes matching the watched SQL text/digest,
so the sweep becomes order-dependent (container stays up, ping-abort never
fires). Block the arm (first keyword QUERY + second WATCH).

Make neutralizeExecutableComments string-aware: a `/*` inside a string
literal is data, so it must skip quoted regions with the same skipQuoted
helper stripComments uses. Otherwise `SELECT '/*'; /*! SET PASSWORD='x' */`
reads the in-string `/*` as an ordinary comment and jumps past the real
`/*!` marker, which stripComments then removes as ordinary -> the SET
executes unseen.

Feature-gate union scan: TiDB ignores the whole `/*T![feature] ... */` block
when the feature id is unsupported and executes the SQL that follows. Without
the version feature table, scan BOTH interpretations (content-visible and
content-stripped) when a `/*T![` marker is present and flag unsafe if either
trips. Plain `/*!`/`/*T!` digit forms execute unconditionally, so their
single view stays exact.

Multi-assignment SET: scan ALL comma-separated targets, not just the first,
so `SET @v=1, @@GLOBAL.sql_mode='ANSI_QUOTES'` is caught. Comma split is
naive (a comma inside a quoted value over-matches into a conservative skip).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
adjudicateTiDB now snapshots parse-affecting global state at sweep start and
re-verifies it at sweep end (verifyNoDrift). Drift means a probed statement
bypassed the deny-list and mutated shared state, so the board would be
order-dependent: the sweep fails loudly, naming the drifted variable
(before -> after) and instructing container recreation, instead of committing
a possibly poisoned board. main.go already fatals on the adjudicateTiDB error
before any JSONL/board write, so a tripped canary leaves no partial artifact.

Snapshot list (all six confirmed present on v8.5.5): @@global.sql_mode,
character_set_server, collation_server, default_week_format,
sql_require_primary_key, tidb_skip_isolation_level_check — small and skewed to
state that changes how a later row parses or what is accepted. An auth canary
(fresh Ping) proves the root credentials still authenticate after the sweep.

The deny-list is best-effort enumeration; the canary + 1045-abort + schemaless
DSN + loopback bind + disposable container are the guarantees — a bypass is a
detected loud failure, not silent corruption (README).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ipped

Regenerated on a fresh pinned container after the round-6 deny-list arms. The
14 QUERY WATCH GAP rows move from GAP to INDETERMINATE unsafe_to_adjudicate
(GAP 1107 -> 1093, INDETERMINATE 35 -> 49); the 4 AGREE_REJECT QUERY WATCH
rows are non-candidates and unchanged. Canary reported no drift end to end.
omni_sha and container_digest unchanged (merge-base == committed sha).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rites, trailing newline

Codex round 7 (reporting accuracy + hygiene):

- Scoreboard surfaces unexpanded generator sites: non_literal SKIP rows are
  loop-built runtime srcs each standing for multiple upstream cases, so the
  committed totals measure the static literal corpus, not full
  runtime-upstream coverage (expansion = static mini-interpreter, out of
  scope). README + PR body scope the zero-loss claim the same way.
- Label-only runs no longer overwrite the committed adjudicated board: the
  board lands in gitignored out/tidb.scoreboard.md unless -adjudicate or the
  new -write-scoreboard (intentional label-only baseline) is set; decision
  pinned by TestWriteCommittedBoard.
- renderScoreboard ends with exactly one trailing newline (git diff --check
  flagged a blank line at EOF on the committed board).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full adjudicated sweep on a fresh pinned container (merge-base omni_sha
f7991e5, digest unchanged): picks up the generator-site line (13) and the
single-trailing-newline render. All counts and clusters byte-identical to the
previous board — zero movement.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39add1599f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread harness/conformance/extract_tidb.go
Name the harvested shapes exactly ({src, ok} testCase / {src, err}
testErrMsgCase literals) in README and the extractor's top comment, and
enumerate the documented out-of-scope static shapes ([]string tables
labeled by consuming assertions, RunRestoreTest-style pairs, inline
Parse calls) as follow-up harvest candidates for the next corpus-tag
re-baseline. No behavior change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vsai12 vsai12 merged commit 917737b into main Jul 8, 2026
21 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e720e9d7e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +372 to +373
c := s[i+2]
return c == ' ' || c == '\t' || c == '\n' || c == '\r'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat all TiDB dash-comment whitespace as comments

When a row has -- followed by vertical-tab/form-feed before a newline, the pinned TiDB scanner treats that as a line comment because it uses unicode.IsSpace after the dashes, but this helper only recognizes four whitespace bytes. A candidate like --\v\nSET PASSWORD='x' is therefore considered safe here because the statement starts with -, while TiDB skips the comment and executes the password-changing SET, poisoning later fresh connections; mirror the oracle whitespace set before the unsafe scan.

Useful? React with 👍 / 👎.

second, _ := nextKeyword(rest)
return second == "WATCH"
}
return false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Block dynamic SQL from reaching the oracle

When a divergent batch prepares and executes dynamic SQL in the same fresh session, neither PREPARE nor EXECUTE is treated as unsafe here, so a row such as SET @s='SET GLOBAL sql_mode="ANSI_QUOTES"'; PREPARE p FROM @s; EXECUTE p reaches the shared oracle and mutates the global parse mode while the scanner only sees safe top-level statements. That can make the following fresh-session probes order-dependent before the end canary trips, or evade it if the batch restores the value; reject PREPARE/EXECUTE batches or inspect the prepared text/session variable flow.

Useful? React with 👍 / 👎.

}
sort.Slice(rows, func(i, j int) bool { return rows[i].StmtHash < rows[j].StmtHash })
for i := range rows {
if err := enc.Encode(&rows[i]); err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve non-UTF-8 SQL bytes in JSONL

When a corpus literal contains raw non-UTF-8 bytes, such as the pinned TiDB row select 111 as \xd6\xf7, encoding/json coerces the sql string to valid UTF-8 and writes replacement runes. The stmt_hash was computed over the original bytes and omni/container verdicts were produced from those bytes, so the JSONL artifact no longer contains a re-runnable statement and offline reclassification from the committed artifact can diverge; encode raw SQL bytes losslessly, for example with an escaped/base64 companion field.

Useful? React with 👍 / 👎.

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