Skip to content

[inline-learn lib 2/3] Reconcile multi-query inline expectations - #23012

Draft
d10c wants to merge 3 commits into
d10c/learn-inline-expectations-libfrom
d10c/multi-query-ql-reconciliation
Draft

d10c wants to merge 3 commits into
d10c/learn-inline-expectations-libfrom
d10c/multi-query-ql-reconciliation

Conversation

@d10c

@d10c d10c commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

What problem does it solve?

Inline-expectation learning needs to reconcile annotations owned by several .qlref tests that share source files.

Why is the problem a problem?

A selected query sees only its own results. Without complete cohort ownership, learning can remove another query's qualification, collapse a shared annotation too early, or rewrite an annotation that belongs to an unselected sibling.

How does the solution work?

The postprocessor accepts repeated cohortMember metadata, models each qualified atom as one producer, and renders the annotation from the complete surviving producer set. Bare atoms represent full-cohort ownership. Invalid producer qualifiers, including whitespace-bearing multi-ID forms, are rejected rather than guessed. Ignored annotations and unrelated complete qualified sets are preserved.

Tagged .qlref membership is used because it exposes complete directory ownership without compiling every unselected sibling.

Why does the solution solve the problem?

Each query updates only the producer facts it owns while the renderer retains facts owned by the rest of the cohort. The complete membership list provides the information needed to decide when qualification can be removed safely.

Why is this a good solution?

The change extends the existing expectation grammar and edit relation with a narrow metadata input. It preserves current single-query behavior, fails safely for ambiguous syntax, and leaves more general producer-list syntax as a separately designed feature.

Testing

Go library fixtures cover shared ownership, selected-query updates, producer qualification and collapse, ignored annotations, problem queries, and invalid qualifier rejection.

This PR is based on an upstream mirror of the exact head of #22228. GitHub does not allow the fork-origin parent PR itself in a Stack object; the follow-up PRs are linked in Stack #23015. Followed by #23013.

@d10c
d10c changed the base branch from d10c/learn-inline-expectations-lib to main November 4, 2026 12:42
@d10c
d10c added this pull request to stack #23014 November 4, 2026 12:42
@d10c d10c changed the title d10c/multi query ql reconciliation Reconcile multi-query inline expectations Nov 4, 2026
@d10c
d10c removed this pull request from stack #23014 November 4, 2026 12:45
@d10c
d10c changed the base branch from main to d10c/learn-inline-expectations-lib November 4, 2026 12:45
@d10c
d10c added this pull request to stack #23015 November 4, 2026 12:45
@d10c
d10c requested an auto review from Copilot November 4, 2026 12:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Expectation-rewriting bugs can delete unselected sibling queries’ annotations and incorrectly infer ownership for unsupported qualifier syntax.

3 open issues
What changed in this PR

Extends the shared inline-expectation learner to reconcile annotations across .qlref queries that share source files, using cohort metadata to track ownership.

Changes:

  • Adds producer reconciliation and bare-versus-qualified annotation rendering.
  • Preserves ignored annotations and complete qualified sets, with guards for unsupported syntax.
  • Adds Go fixtures for shared ownership, problem queries, and qualifier handling.
File Description
shared/​util/​codeql/​util/​test/​InlineExpectationsTest.qll Implements cohort-aware expectation reconciliation.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query/​q2.qlref Connects q2 to inline postprocessing.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query/​q2.ql Defines q2 shared and query-specific results.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query/​q2.expected Records q2 result baseline.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query/​q1.qlref Connects q1 to inline postprocessing.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query/​q1.ql Defines q1 shared and query-specific results.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query/​q1.expected Records q1 result baseline.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query/​code.go Supplies ownership and annotation fixtures.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-problem/​q2.qlref Configures q2 problem postprocessing.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-problem/​q2.ql Defines the second shared problem query.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-problem/​q2.expected Records q2 problem results.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-problem/​q1.qlref Configures q1 problem postprocessing.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-problem/​q1.ql Defines the first shared problem query.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-problem/​q1.expected Records q1 problem results.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-problem/​code.go Combines a shared alert with an ignored annotation.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-invalid-qualifier/​q2.qlref Configures q2 qualifier-fixture postprocessing.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-invalid-qualifier/​q2.ql Defines q2's shared result.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-invalid-qualifier/​q2.expected Records q2 qualifier-fixture results.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-invalid-qualifier/​q1.qlref Configures q1 qualifier-fixture postprocessing.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-invalid-qualifier/​q1.ql Defines q1's shared result.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-invalid-qualifier/​q1.expected Records q1 qualifier-fixture results.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-invalid-qualifier/​code.go.invalid Supplies unsupported whitespace-bearing qualifier syntax.
go/​ql/​test/​library-tests/​inline-expectations/​multi-query-invalid-qualifier/​code.go Supplies valid separate producer qualifiers.

Review effort: Balanced (auto)

Comment on lines 1203 to 1209
not exists(string tags, string queryId |
inCohortMode() and
hasExpectation(comment, TDefaultColumn(), _, tags, _) and
not tags.matches("%,%") and
parseQualifiedTag(tags, _, queryId) and
queryId.regexpMatch(".*\\s+.*")
)
parseQualifiedTag(tags, base, queryId) and
cohortMember(queryId) and
parseLocationString(comment.getLocation().getRelativeUrl(), relativePath, line, _, _, _) and
isCollapsedAtom(relativePath, line, base, value)
string queryId
|
inCohortMode() and
hasExpectation(comment, TDefaultColumn(), _, full, value) and
@d10c d10c changed the title Reconcile multi-query inline expectations [inline-learn lib 2/3] Reconcile multi-query inline expectations Nov 4, 2026
@github-actions github-actions Bot added the Go label Nov 4, 2026
d10c and others added 3 commits November 4, 2026 14:05
Read cohort membership through query metadata and derive producer sets from comments re-extracted between serialized query passes. Render full-cohort atoms bare, qualify partial atoms, and normalize existing qualified sets while preserving foreign and named-column expectations.

Add a focused Go-pack fixture for kind-less qualified matching and preservation behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d6e9cf9f-9b2e-487b-b28d-a79029d09ea8
When a bare atom becomes partial, render the surviving sibling producers with query-ID qualifiers instead of deleting their expectation. Carry forward only tags the current query understands, accept only non-empty single-ID qualifiers as cohort syntax, and leave default-column comma groups or whitespace-bearing qualifiers untouched because they cannot express one producer unambiguously.

Treat a complete qualified producer set as equivalent to its collapsed bare atom when deciding whether a comment needs an edit. This preserves useful query provenance on otherwise-correct comments; comments requiring another repair still use canonical bare rendering.

Extend the Go fixtures with bare-to-partial, ignored-tag, complete-qualified-set, and unsupported multi-ID mutation cases, then regenerate their expected output.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d6e9cf9f-9b2e-487b-b28d-a79029d09ea8
Leave unsupported qualified syntax untouched, collapse sibling qualifications only when the rewritten comment emits the covering bare atom, and carry sibling ownership in the original expectation column. Cover invalid qualifier forms and default, MISSING, and SPURIOUS reconciliation through the Go inline-expectation fixtures.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 1adfa307-c48e-43f5-94e3-8286e4a8c083
@d10c
d10c force-pushed the d10c/multi-query-ql-reconciliation branch from 5b1df91 to 3baabf9 Compare November 4, 2026 14:00

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants