Skip to content

feat(cypher): scope free-form intermediate MATCH failfast to #1263#1270

Merged
lmeyerov merged 3 commits intomasterfrom
feat/1263-freeform-intermediate-match
May 4, 2026
Merged

feat(cypher): scope free-form intermediate MATCH failfast to #1263#1270
lmeyerov merged 3 commits intomasterfrom
feat/1263-freeform-intermediate-match

Conversation

@lmeyerov
Copy link
Copy Markdown
Contributor

@lmeyerov lmeyerov commented May 4, 2026

Summary

Scope the free-form intermediate MATCH failfast to #1263 (LDBC SNB IC3 endpoint). This PR does NOT close #1263 — it sharpens the failfast wording and pins regression-locks for the gap, with a complete design doc as input for the closing slice.

Problem

_compile_bounded_reentry_query rejects any trailing MATCH whose first alias is not in the prefix WITH's carried set with the generic message "trailing MATCH currently requires the trailing MATCH to start from the same carried node alias". That covers a real gap (the LDBC SNB IC3 endpoint), but the wording is opaque — users can't distinguish this lane from the other open IC3 sub-cases (chained reentry, aggregate downstream, free-form + DISTINCT, etc.) the predecessors closed or partially closed.

What changed

graphistry/compute/gfql/cypher/lowering.py — replaced the generic gate message with a #1263-scoped error:

Cypher MATCH after WITH does not yet admit a trailing MATCH whose first alias is not in the carried set (free-form intermediate MATCH; LDBC SNB IC3 endpoint, tracked under #1263). The carried-alias path requires the trailing MATCH source to be one of the prefix WITH's whole-row aliases.

The wording calls out the gap shape so users can identify which IC3 sub-lane they hit.

Tests

graphistry/tests/compute/gfql/cypher/test_lowering.py:

CHANGELOG.md:

  • Internal entry under [Development] describing the wording change and pointing at the design doc.

What's NOT in this PR

Closure of the actual gap — admitting the trailing MATCH as a fresh seed pattern that cross-joins with the carried row table at runtime, plus extending ReentryPlan with a per-stage free_form marker so the runtime branches between the carried-alias path and a new free-form cross-join path. The design is written but the implementation requires substantial runtime work that should land as its own focused slice.

Design: plans/1263-freeform-intermediate-match/design/freeform-admit-design.md (local-only / gitignored).

Validation

  • 787 cypher lowering tests pass (was 786 on master; +1 new test). No regressions.
  • ./bin/ruff.sh clean.
  • ./bin/mypy.sh on lowering.py clean.
  • Repro plans/1263-freeform-intermediate-match/repro/repro_ic3.py confirms the IC3 literal still fails at the slice 4.3a/b admit gate first (Site B) — the new free-form wording fires for shapes that bypass Site B.

Test plan

  • pytest -q graphistry/tests/compute/gfql/cypher/
  • ./bin/ruff.sh
  • ./bin/mypy.sh on touched files
  • Hosted CI green (push pending)

Refs

🤖 Generated with Claude Code

lmeyerov and others added 3 commits May 3, 2026 17:16
Replace the generic "trailing MATCH must start from the same carried node
alias" error in `_compile_bounded_reentry_query` with a #1263-scoped error
that names the LDBC SNB IC3 endpoint and identifies the gap shape. Users
hitting this gate can now distinguish the free-form intermediate-MATCH lane
from the other open IC3 sub-cases (chained reentry, aggregate downstream,
etc).

Tests:
- Add `test_string_cypher_failfast_rejects_simple_freeform_intermediate_reentry_match`
  — minimal single-alias-prefix shape that isolates the free-form gate
  (Site A from `plans/1263-freeform-intermediate-match/repro/findings.md`)
  without the slice 4.3a/b bare-ref interaction (Site B).
- Retarget `test_string_cypher_failfast_rejects_intermediate_reentry_match_with_no_carried_source`
  from the #1256-era wording to the new #1263 wording. The IC3-shaped query
  still hits the slice 4.3a/b admit gate first (because
  `_demote_secondary_whole_row_aliases` early-bails when the trailing MATCH
  isn't carried), so the matcher accepts either failfast site.

Closure of the gap (admitting the trailing MATCH as a fresh seed pattern
that cross-joins with the carried row table at runtime, plus extending
`ReentryPlan` with a per-stage mode marker) remains follow-up under #1263.
Design at `plans/1263-freeform-intermediate-match/design/freeform-admit-design.md`.

Refs #1263, #999 (IC3 partial), #989 (row-carrier IR umbrella).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wave-1 review flagged the regex matcher
`r"(free-form intermediate MATCH|carries non-source whole-row aliases)"`
as over-permissive: the test query as written hits Site A (the free-form
gate) only — `WHERE c.id = x.id` is property access, not bare reference, so
the slice 4.3a/b admit gate does not fire on this query. The OR branch was
dead.

Tighten to `r"free-form intermediate MATCH"` and update the docstring to
remove the inaccurate claim that the IC3 literal additionally hits Site B.
The IC3 literal (in `repro_ic3.py`) does hit Site B first; this simplified
test query does not.

Refs #1263.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lmeyerov lmeyerov marked this pull request as ready for review May 4, 2026 00:38
@lmeyerov lmeyerov merged commit 658dfdf into master May 4, 2026
93 checks passed
lmeyerov added a commit that referenced this pull request May 4, 2026
…e admit

Two #1263 regression-locks added in #1270 expected the carried-alias gate to
fire for free-form intermediate MATCH. The conservative admit landed in the
preceding commits flips the simple shape from rejection to positive
execution and tightens the rejection scope to the carried-property variant:

* ``test_string_cypher_failfast_rejects_intermediate_reentry_match_with_no_carried_source``
  → renamed to ``..._with_carried_property_in_trailing_where`` and pinned to
  the new scoped #1263 failfast (carried-alias property in trailing scope).
* ``test_string_cypher_failfast_rejects_simple_freeform_intermediate_reentry_match``
  → renamed to ``test_string_cypher_executes_simple_freeform_intermediate_reentry_match``
  and converted to positive: asserts the trailing MATCH binds correctly
  against the broadcast carried row table.
* New ``..._on_cudf_when_available`` mirror with ``pytest.importorskip("cudf")``
  for engine parity per coordinator def-of-done.

Refs #1263 #999 #989

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lmeyerov added a commit that referenced this pull request May 4, 2026
…e admit

Two #1263 regression-locks added in #1270 expected the carried-alias gate to
fire for free-form intermediate MATCH. The conservative admit landed in the
preceding commits flips the simple shape from rejection to positive
execution and tightens the rejection scope to the carried-property variant:

* ``test_string_cypher_failfast_rejects_intermediate_reentry_match_with_no_carried_source``
  → renamed to ``..._with_carried_property_in_trailing_where`` and pinned to
  the new scoped #1263 failfast (carried-alias property in trailing scope).
* ``test_string_cypher_failfast_rejects_simple_freeform_intermediate_reentry_match``
  → renamed to ``test_string_cypher_executes_simple_freeform_intermediate_reentry_match``
  and converted to positive: asserts the trailing MATCH binds correctly
  against the broadcast carried row table.
* New ``..._on_cudf_when_available`` mirror with ``pytest.importorskip("cudf")``
  for engine parity per coordinator def-of-done.

Refs #1263 #999 #989

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lmeyerov added a commit that referenced this pull request May 4, 2026
* feat(cypher/ir): add ReentryPlan.free_form marker for intermediate MATCH (#1263)

Adds a `free_form: bool = False` field to `ReentryPlan` so the runtime can
distinguish the LDBC SNB IC3 free-form intermediate MATCH shape from the
existing whole-row and scalar-only prefix shapes.

When the trailing MATCH after a prefix `WITH` introduces aliases none of
which is in the carried set, no carried alias anchors the seed pattern.
The runtime needs to broadcast carried columns onto the base node table
(single-prefix-row) or fall back to per-row union (multi-prefix-row) so
the trailing MATCH cross-joins implicitly via the row pipeline.

Default value preserves existing whole-row and scalar-only behavior.
Compile + runtime branches that consume this marker land in subsequent
commits.

Refs #1263 #999 #989

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

* feat(cypher): admit free-form intermediate MATCH at compile (#1263)

Lifts the failfast at the trailing-MATCH-first-alias check in
``_compile_bounded_reentry_query`` for the free-form case (LDBC SNB IC3
endpoint): when the trailing MATCH binds aliases none of which is in the
prefix WITH's carried whole-row set, treat every carried alias as
non-source and use the trailing MATCH's first alias as the carrier label
for downstream rewrites.

The existing ``_collect_non_source_alias_property_refs`` /
``_rewrite_reentry_expr_to_hidden_properties`` machinery (slice 4.3a/b
from #1248) materializes carried-alias property references as hidden
columns; with this change the same machinery covers free-form cases by
passing all whole-row aliases as ``non_source_alias_names``.

The ``ReentryPlan`` constructed for free-form sets
``free_form=True`` (no ``CarriedAlias`` entry has
``is_reentry_alias=True``) so the runtime can branch into a broadcast
path. The runtime change lands in a follow-up commit; until then,
free-form queries compile but return wrong rows because the existing
``_compiled_query_reentry_state`` still seeds from the wrong alias's
node ids — the regression is gated by the failfast tests (which fail
intentionally at this commit and are retargeted alongside the runtime
commit).

Also tightens the surviving guard from ``first_alias is None or
first_alias != reentry_alias`` to ``first_alias is None`` since the
admit branch now sets ``reentry_alias = first_alias`` for the
previously-rejected case.

Refs #1263 #999 #989

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

* feat(cypher): runtime broadcast for simple free-form + scoped failfast (#1263)

Lands the runtime half of the #1263 conservative admit:

* New ``_compiled_query_freeform_reentry_state`` in ``gfql_unified.py``
  branches on ``ReentryPlan.free_form``. For a single-row prefix WITH
  it broadcasts every ``__cypher_reentry_*`` hidden column from the
  prefix row onto every base node and returns ``start_nodes=None``, so
  the trailing MATCH runs as a regular MATCH and inherits the carried
  values via the row pipeline. Multi-row prefix raises a clear
  failfast pointing at the multi-row free-form follow-up slice.

* Compile gate added in ``_compile_bounded_reentry_query``: when
  ``free_form`` is True AND the trailing scope references any carried
  alias property (e.g. ``WHERE country.id IN [x.id, y.id]`` in literal
  IC3), raise a scoped ``#1263`` failfast pointing at the rewrite-order
  refactor follow-up. The double-rewrite that emerges from composing
  ``_demote_secondary_whole_row_aliases`` (#1071) with
  ``_rewrite_reentry_expr_to_hidden_properties`` (#1248) under
  free-form is deferred to its own focused slice.

End-to-end:
* Simple free-form (``MATCH (a) WITH a MATCH (c)-[:T]->(d) RETURN ...``)
  compiles + executes vectorized on pandas.
* IC3-shape with carried-property WHERE rejects with a scoped #1263
  failfast (clear error pointing at the follow-up).

Refs #1263 #999 #989

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

* test(cypher): retarget free-form failfast tests for #1263 conservative admit

Two #1263 regression-locks added in #1270 expected the carried-alias gate to
fire for free-form intermediate MATCH. The conservative admit landed in the
preceding commits flips the simple shape from rejection to positive
execution and tightens the rejection scope to the carried-property variant:

* ``test_string_cypher_failfast_rejects_intermediate_reentry_match_with_no_carried_source``
  → renamed to ``..._with_carried_property_in_trailing_where`` and pinned to
  the new scoped #1263 failfast (carried-alias property in trailing scope).
* ``test_string_cypher_failfast_rejects_simple_freeform_intermediate_reentry_match``
  → renamed to ``test_string_cypher_executes_simple_freeform_intermediate_reentry_match``
  and converted to positive: asserts the trailing MATCH binds correctly
  against the broadcast carried row table.
* New ``..._on_cudf_when_available`` mirror with ``pytest.importorskip("cudf")``
  for engine parity per coordinator def-of-done.

Refs #1263 #999 #989

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

* test(cypher): add multi-prefix-row free-form failfast regression (#1263)

Wave 1 review (single CONFIRMED IMPORTANT): the runtime failfast at
gfql_unified.py for multi-prefix-row free-form admit was untested. Adds a
positive regression-lock that builds a 2-row prefix and asserts the scoped
``single-row prefix WITH only`` failfast wording.

Refs #1263

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

* docs(changelog): #1263 simple free-form intermediate MATCH admit

Records the conservative #1263 close: simple free-form admit + scoped
failfast for the carried-property-in-trailing-WHERE variant + runtime
broadcast helper + retargeted regression tests + three TCK admits.

Refs #1263 #999 #989

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

* test(cypher): Wave 2 amplification — multi-carried + empty prefix free-form (#1263)

Wave 2 review per agents/skills/review/SKILL.md confirmed convergence
(two consecutive non-significant-advance waves) and surfaced two
amplification SUGGESTIONs that the reviewers verified produce correct
behavior. Locking the contract:

* test_string_cypher_executes_freeform_intermediate_reentry_match_with_multi_carried_aliases
  — covers `WITH a, b MATCH (c)-[:T]->(d)` shape (multi-carried-aliases admit).
* test_string_cypher_executes_freeform_intermediate_reentry_match_with_empty_prefix
  — covers `_compiled_query_freeform_reentry_state`'s empty-prefix
  early-return path.

Refs #1263

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lmeyerov added a commit that referenced this pull request May 4, 2026
* feat(cypher/ir): add ReentryPlan.free_form marker for intermediate MATCH (#1263)

Adds a `free_form: bool = False` field to `ReentryPlan` so the runtime can
distinguish the LDBC SNB IC3 free-form intermediate MATCH shape from the
existing whole-row and scalar-only prefix shapes.

When the trailing MATCH after a prefix `WITH` introduces aliases none of
which is in the carried set, no carried alias anchors the seed pattern.
The runtime needs to broadcast carried columns onto the base node table
(single-prefix-row) or fall back to per-row union (multi-prefix-row) so
the trailing MATCH cross-joins implicitly via the row pipeline.

Default value preserves existing whole-row and scalar-only behavior.
Compile + runtime branches that consume this marker land in subsequent
commits.

Refs #1263 #999 #989

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

* feat(cypher): admit free-form intermediate MATCH at compile (#1263)

Lifts the failfast at the trailing-MATCH-first-alias check in
``_compile_bounded_reentry_query`` for the free-form case (LDBC SNB IC3
endpoint): when the trailing MATCH binds aliases none of which is in the
prefix WITH's carried whole-row set, treat every carried alias as
non-source and use the trailing MATCH's first alias as the carrier label
for downstream rewrites.

The existing ``_collect_non_source_alias_property_refs`` /
``_rewrite_reentry_expr_to_hidden_properties`` machinery (slice 4.3a/b
from #1248) materializes carried-alias property references as hidden
columns; with this change the same machinery covers free-form cases by
passing all whole-row aliases as ``non_source_alias_names``.

The ``ReentryPlan`` constructed for free-form sets
``free_form=True`` (no ``CarriedAlias`` entry has
``is_reentry_alias=True``) so the runtime can branch into a broadcast
path. The runtime change lands in a follow-up commit; until then,
free-form queries compile but return wrong rows because the existing
``_compiled_query_reentry_state`` still seeds from the wrong alias's
node ids — the regression is gated by the failfast tests (which fail
intentionally at this commit and are retargeted alongside the runtime
commit).

Also tightens the surviving guard from ``first_alias is None or
first_alias != reentry_alias`` to ``first_alias is None`` since the
admit branch now sets ``reentry_alias = first_alias`` for the
previously-rejected case.

Refs #1263 #999 #989

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

* feat(cypher): runtime broadcast for simple free-form + scoped failfast (#1263)

Lands the runtime half of the #1263 conservative admit:

* New ``_compiled_query_freeform_reentry_state`` in ``gfql_unified.py``
  branches on ``ReentryPlan.free_form``. For a single-row prefix WITH
  it broadcasts every ``__cypher_reentry_*`` hidden column from the
  prefix row onto every base node and returns ``start_nodes=None``, so
  the trailing MATCH runs as a regular MATCH and inherits the carried
  values via the row pipeline. Multi-row prefix raises a clear
  failfast pointing at the multi-row free-form follow-up slice.

* Compile gate added in ``_compile_bounded_reentry_query``: when
  ``free_form`` is True AND the trailing scope references any carried
  alias property (e.g. ``WHERE country.id IN [x.id, y.id]`` in literal
  IC3), raise a scoped ``#1263`` failfast pointing at the rewrite-order
  refactor follow-up. The double-rewrite that emerges from composing
  ``_demote_secondary_whole_row_aliases`` (#1071) with
  ``_rewrite_reentry_expr_to_hidden_properties`` (#1248) under
  free-form is deferred to its own focused slice.

End-to-end:
* Simple free-form (``MATCH (a) WITH a MATCH (c)-[:T]->(d) RETURN ...``)
  compiles + executes vectorized on pandas.
* IC3-shape with carried-property WHERE rejects with a scoped #1263
  failfast (clear error pointing at the follow-up).

Refs #1263 #999 #989

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

* test(cypher): retarget free-form failfast tests for #1263 conservative admit

Two #1263 regression-locks added in #1270 expected the carried-alias gate to
fire for free-form intermediate MATCH. The conservative admit landed in the
preceding commits flips the simple shape from rejection to positive
execution and tightens the rejection scope to the carried-property variant:

* ``test_string_cypher_failfast_rejects_intermediate_reentry_match_with_no_carried_source``
  → renamed to ``..._with_carried_property_in_trailing_where`` and pinned to
  the new scoped #1263 failfast (carried-alias property in trailing scope).
* ``test_string_cypher_failfast_rejects_simple_freeform_intermediate_reentry_match``
  → renamed to ``test_string_cypher_executes_simple_freeform_intermediate_reentry_match``
  and converted to positive: asserts the trailing MATCH binds correctly
  against the broadcast carried row table.
* New ``..._on_cudf_when_available`` mirror with ``pytest.importorskip("cudf")``
  for engine parity per coordinator def-of-done.

Refs #1263 #999 #989

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

* test(cypher): add multi-prefix-row free-form failfast regression (#1263)

Wave 1 review (single CONFIRMED IMPORTANT): the runtime failfast at
gfql_unified.py for multi-prefix-row free-form admit was untested. Adds a
positive regression-lock that builds a 2-row prefix and asserts the scoped
``single-row prefix WITH only`` failfast wording.

Refs #1263

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

* docs(changelog): #1263 simple free-form intermediate MATCH admit

Records the conservative #1263 close: simple free-form admit + scoped
failfast for the carried-property-in-trailing-WHERE variant + runtime
broadcast helper + retargeted regression tests + three TCK admits.

Refs #1263 #999 #989

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

* test(cypher): Wave 2 amplification — multi-carried + empty prefix free-form (#1263)

Wave 2 review per agents/skills/review/SKILL.md confirmed convergence
(two consecutive non-significant-advance waves) and surfaced two
amplification SUGGESTIONs that the reviewers verified produce correct
behavior. Locking the contract:

* test_string_cypher_executes_freeform_intermediate_reentry_match_with_multi_carried_aliases
  — covers `WITH a, b MATCH (c)-[:T]->(d)` shape (multi-carried-aliases admit).
* test_string_cypher_executes_freeform_intermediate_reentry_match_with_empty_prefix
  — covers `_compiled_query_freeform_reentry_state`'s empty-prefix
  early-return path.

Refs #1263

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lmeyerov added a commit that referenced this pull request May 4, 2026
…is defaults (#1280)

* phase1: validators, deep ring axis checks, and persist axis defaults

* fix: satisfy mypy for dataset_id URL refresh helper

* fix: make validate_settings typing compatible with python 3.8

* refactor: centralize axis field constants and typed dict contracts

* docs(changelog): record settings/axis validation + persist defaults work

* refactor(validate): centralize ring axis payload validators

* types(validate): add named url params/react settings aliases

* types(url_params): propagate named URLParamsDict across APIs

* feat(cypher): admit simple free-form intermediate MATCH (#1263) (#1279)

* feat(cypher/ir): add ReentryPlan.free_form marker for intermediate MATCH (#1263)

Adds a `free_form: bool = False` field to `ReentryPlan` so the runtime can
distinguish the LDBC SNB IC3 free-form intermediate MATCH shape from the
existing whole-row and scalar-only prefix shapes.

When the trailing MATCH after a prefix `WITH` introduces aliases none of
which is in the carried set, no carried alias anchors the seed pattern.
The runtime needs to broadcast carried columns onto the base node table
(single-prefix-row) or fall back to per-row union (multi-prefix-row) so
the trailing MATCH cross-joins implicitly via the row pipeline.

Default value preserves existing whole-row and scalar-only behavior.
Compile + runtime branches that consume this marker land in subsequent
commits.

Refs #1263 #999 #989

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

* feat(cypher): admit free-form intermediate MATCH at compile (#1263)

Lifts the failfast at the trailing-MATCH-first-alias check in
``_compile_bounded_reentry_query`` for the free-form case (LDBC SNB IC3
endpoint): when the trailing MATCH binds aliases none of which is in the
prefix WITH's carried whole-row set, treat every carried alias as
non-source and use the trailing MATCH's first alias as the carrier label
for downstream rewrites.

The existing ``_collect_non_source_alias_property_refs`` /
``_rewrite_reentry_expr_to_hidden_properties`` machinery (slice 4.3a/b
from #1248) materializes carried-alias property references as hidden
columns; with this change the same machinery covers free-form cases by
passing all whole-row aliases as ``non_source_alias_names``.

The ``ReentryPlan`` constructed for free-form sets
``free_form=True`` (no ``CarriedAlias`` entry has
``is_reentry_alias=True``) so the runtime can branch into a broadcast
path. The runtime change lands in a follow-up commit; until then,
free-form queries compile but return wrong rows because the existing
``_compiled_query_reentry_state`` still seeds from the wrong alias's
node ids — the regression is gated by the failfast tests (which fail
intentionally at this commit and are retargeted alongside the runtime
commit).

Also tightens the surviving guard from ``first_alias is None or
first_alias != reentry_alias`` to ``first_alias is None`` since the
admit branch now sets ``reentry_alias = first_alias`` for the
previously-rejected case.

Refs #1263 #999 #989

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

* feat(cypher): runtime broadcast for simple free-form + scoped failfast (#1263)

Lands the runtime half of the #1263 conservative admit:

* New ``_compiled_query_freeform_reentry_state`` in ``gfql_unified.py``
  branches on ``ReentryPlan.free_form``. For a single-row prefix WITH
  it broadcasts every ``__cypher_reentry_*`` hidden column from the
  prefix row onto every base node and returns ``start_nodes=None``, so
  the trailing MATCH runs as a regular MATCH and inherits the carried
  values via the row pipeline. Multi-row prefix raises a clear
  failfast pointing at the multi-row free-form follow-up slice.

* Compile gate added in ``_compile_bounded_reentry_query``: when
  ``free_form`` is True AND the trailing scope references any carried
  alias property (e.g. ``WHERE country.id IN [x.id, y.id]`` in literal
  IC3), raise a scoped ``#1263`` failfast pointing at the rewrite-order
  refactor follow-up. The double-rewrite that emerges from composing
  ``_demote_secondary_whole_row_aliases`` (#1071) with
  ``_rewrite_reentry_expr_to_hidden_properties`` (#1248) under
  free-form is deferred to its own focused slice.

End-to-end:
* Simple free-form (``MATCH (a) WITH a MATCH (c)-[:T]->(d) RETURN ...``)
  compiles + executes vectorized on pandas.
* IC3-shape with carried-property WHERE rejects with a scoped #1263
  failfast (clear error pointing at the follow-up).

Refs #1263 #999 #989

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

* test(cypher): retarget free-form failfast tests for #1263 conservative admit

Two #1263 regression-locks added in #1270 expected the carried-alias gate to
fire for free-form intermediate MATCH. The conservative admit landed in the
preceding commits flips the simple shape from rejection to positive
execution and tightens the rejection scope to the carried-property variant:

* ``test_string_cypher_failfast_rejects_intermediate_reentry_match_with_no_carried_source``
  → renamed to ``..._with_carried_property_in_trailing_where`` and pinned to
  the new scoped #1263 failfast (carried-alias property in trailing scope).
* ``test_string_cypher_failfast_rejects_simple_freeform_intermediate_reentry_match``
  → renamed to ``test_string_cypher_executes_simple_freeform_intermediate_reentry_match``
  and converted to positive: asserts the trailing MATCH binds correctly
  against the broadcast carried row table.
* New ``..._on_cudf_when_available`` mirror with ``pytest.importorskip("cudf")``
  for engine parity per coordinator def-of-done.

Refs #1263 #999 #989

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

* test(cypher): add multi-prefix-row free-form failfast regression (#1263)

Wave 1 review (single CONFIRMED IMPORTANT): the runtime failfast at
gfql_unified.py for multi-prefix-row free-form admit was untested. Adds a
positive regression-lock that builds a 2-row prefix and asserts the scoped
``single-row prefix WITH only`` failfast wording.

Refs #1263

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

* docs(changelog): #1263 simple free-form intermediate MATCH admit

Records the conservative #1263 close: simple free-form admit + scoped
failfast for the carried-property-in-trailing-WHERE variant + runtime
broadcast helper + retargeted regression tests + three TCK admits.

Refs #1263 #999 #989

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

* test(cypher): Wave 2 amplification — multi-carried + empty prefix free-form (#1263)

Wave 2 review per agents/skills/review/SKILL.md confirmed convergence
(two consecutive non-significant-advance waves) and surfaced two
amplification SUGGESTIONs that the reviewers verified produce correct
behavior. Locking the contract:

* test_string_cypher_executes_freeform_intermediate_reentry_match_with_multi_carried_aliases
  — covers `WITH a, b MATCH (c)-[:T]->(d)` shape (multi-carried-aliases admit).
* test_string_cypher_executes_freeform_intermediate_reentry_match_with_empty_prefix
  — covers `_compiled_query_freeform_reentry_state`'s empty-prefix
  early-return path.

Refs #1263

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (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.

Cypher/GFQL: free-form intermediate MATCH after WITH (LDBC SNB IC3 endpoint)

1 participant