Skip to content

feat: plan change-signature graph edits - #2049

Closed
vitali87 wants to merge 1 commit into
pr-split/split-pr1548-rebased/pr-4from
pr-split/split-pr1548-rebased/pr-5
Closed

vitali87 wants to merge 1 commit into
pr-split/split-pr1548-rebased/pr-4from
pr-split/split-pr1548-rebased/pr-5

Conversation

@vitali87

Copy link
Copy Markdown
Owner

Graph query support and planner orchestration for hierarchy definitions and callers.

Files changed

  • codebase_rag/cypher_queries.py
  • codebase_rag/editing/signature_planner.py
  • evals/cgr_graph.py

Diff stats

+261 additions, -0 deletions (261 LOC)

Dependencies

This PR depends on: pr-1, pr-2, pr-3, pr-4

Dependency graph

Merge in this order:

pr-1: feat: add change-signature types and constants
├── pr-2: feat: parse and render signature parameters
│   ├── pr-4: feat: rewrite signature definitions and call sites
│   │   └── pr-5: feat: plan change-signature graph edits  <-- this PR
│   │       └── pr-6: feat: expose change-signature via API, CLI, and MCP
│   │           ├── pr-7: test: cover change-signature units
│   │           │   ├── pr-8: test: cover change-signature acceptance flows
│   │           │   └── pr-9: test: cover change-signature regressions
│   │           └── pr-10: docs: document change-signature architecture
│   └── pr-5: feat: plan change-signature graph edits  <-- this PR
│       └── pr-6: feat: expose change-signature via API, CLI, and MCP
│           ├── pr-7: test: cover change-signature units
│           │   ├── pr-8: test: cover change-signature acceptance flows
│           │   └── pr-9: test: cover change-signature regressions
│           └── pr-10: docs: document change-signature architecture
├── pr-3: feat: map change-signature call arguments
│   ├── pr-4: feat: rewrite signature definitions and call sites
│   │   └── pr-5: feat: plan change-signature graph edits  <-- this PR
│   │       └── pr-6: feat: expose change-signature via API, CLI, and MCP
│   │           ├── pr-7: test: cover change-signature units
│   │           │   ├── pr-8: test: cover change-signature acceptance flows
│   │           │   └── pr-9: test: cover change-signature regressions
│   │           └── pr-10: docs: document change-signature architecture
│   └── pr-5: feat: plan change-signature graph edits  <-- this PR
│       └── pr-6: feat: expose change-signature via API, CLI, and MCP
│           ├── pr-7: test: cover change-signature units
│           │   ├── pr-8: test: cover change-signature acceptance flows
│           │   └── pr-9: test: cover change-signature regressions
│           └── pr-10: docs: document change-signature architecture
├── pr-4: feat: rewrite signature definitions and call sites
│   └── pr-5: feat: plan change-signature graph edits  <-- this PR
│       └── pr-6: feat: expose change-signature via API, CLI, and MCP
│           ├── pr-7: test: cover change-signature units
│           │   ├── pr-8: test: cover change-signature acceptance flows
│           │   └── pr-9: test: cover change-signature regressions
│           └── pr-10: docs: document change-signature architecture
└── pr-5: feat: plan change-signature graph edits  <-- this PR
    └── pr-6: feat: expose change-signature via API, CLI, and MCP
        ├── pr-7: test: cover change-signature units
        │   ├── pr-8: test: cover change-signature acceptance flows
        │   └── pr-9: test: cover change-signature regressions
        └── pr-10: docs: document change-signature architecture

@vitali87
vitali87 changed the base branch from feat/postcondition-contract to main September 20, 2026 21:57
@vitali87
vitali87 added this pull request to stack #2051 September 20, 2026 21:57
@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 8 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 8 included reviews 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: Repository: vitali87/code-graph-rag/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: d7f5f407-39f4-4ac1-8c9c-a2e51a2b59d3

📥 Commits

Reviewing files that changed from the base of the PR and between 7126da0 and b5c9ff1.

📒 Files selected for processing (14)
  • codebase_rag/constants/ast_nodes.py
  • codebase_rag/constants/ast_python.py
  • codebase_rag/constants/cli.py
  • codebase_rag/constants/graph.py
  • codebase_rag/constants/mcp.py
  • codebase_rag/cypher_queries.py
  • codebase_rag/editing/contract.py
  • codebase_rag/editing/signature_calls.py
  • codebase_rag/editing/signature_literals.py
  • codebase_rag/editing/signature_params.py
  • codebase_rag/editing/signature_planner.py
  • codebase_rag/editing/signature_rewrite.py
  • codebase_rag/editing/signature_types.py
  • evals/cgr_graph.py

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.

@vitali87
vitali87 removed this pull request from stack #2051 September 20, 2026 21:57
@vitali87
vitali87 changed the base branch from main to feat/postcondition-contract September 20, 2026 21:57
@vitali87
vitali87 added this pull request to stack #2052 September 20, 2026 21:57
@vitali87
vitali87 removed this pull request from stack #2052 September 20, 2026 22:21
@vitali87
vitali87 changed the base branch from feat/postcondition-contract to pr-split/split-pr1548-rebased/pr-4 September 20, 2026 22:21
@vitali87
vitali87 added this pull request to stack #2055 September 20, 2026 22:21
@vitali87
vitali87 marked this pull request as ready for review September 20, 2026 22:22
@greptile-apps

greptile-apps Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 2/5

Not safe to merge: signature rewrites can alter call bindings, produce invalid source, and change a Go API's calling contract.

Findings

  1. P1 Preserve C# named arguments ▶
  2. P1 Render valid parameters ▶
  3. P1 Retain Go variadic semantics ▶

Summary

This change adds graph-backed signature rewrite planning across definitions and call sites. The reproduced cases show that some supported-language rewrites can reverse C# named-argument bindings, emit declarations that target-language compilers reject, or silently remove Go variadic behavior. These issues must be addressed before merging.

Reviews (1) · Last reviewed commit: "feat: plan change-signature graph edits"

A keyword naming a keyword-only parameter is not part of the positional
mapping and is carried through exactly as written.
"""
positional, keyword = _split_call_arguments(args_node)

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.

P1 Preserve C# named arguments

For F(y: 2, x: 1), the changed mapping receives 2 and 1 as positional arguments after the C# argument wrappers discard y: and x:. Reordering the declaration from (x, y) to (y, x) then emits F(1, 2), which reverses the original bindings and changes program behavior. Preserve the C# argument names during mapping, or refuse to rewrite named C# call sites. This must be fixed before merging.

Knowledge Base Used: Multi-language parsing (codebase_rag/parsers)

Artifacts

Evidence from the check

  • Authored harness extracts and executes the changed splitter and mapper against the C# named-argument AST shape, showing the binding-changing rewrite.

Evidence from the check

  • Command wrapper runs the authored C# named-argument harness and captures the before and after evidence logs.

Command output from the check

  • The executed Git command confirms the newly added signature-call module is absent from the parent commit, establishing the pre-change baseline.

Command output from the check

  • The executed harness shows C# `F(y: 2, x: 1)` split as positional `2, 1` and rewritten to `F(1, 2)`, confirming changed bindings.

Command output from the check

  • The captured command output contains the exact authored harness and wrapper used to produce the observed result, making the reproduction traceable.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +180 to +195
def _render_param(spec: ParamSpec, language: cs.SupportedLanguage | None) -> str:
"""A brand-new parameter in the target grammar's spelling."""
annotation = spec.annotation
default = spec.default if spec.default is not None else spec.literal
if language == cs.SupportedLanguage.GO:
return f"{spec.name} {annotation}" if annotation else spec.name
if language == cs.SupportedLanguage.JAVA:
return f"{annotation} {spec.name}" if annotation else spec.name
if language == cs.SupportedLanguage.RUST:
return f"{spec.name}: {annotation}" if annotation else spec.name
text = spec.name
if annotation:
text += f": {annotation}"
if default is not None:
text += f" = {default}" if annotation else f"={default}"
return text

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.

P1 Render valid parameters

The renderer falls back to Python-style syntax for supported languages without dedicated handling, so a C# or C++ addition such as count:int becomes count: int. It also accepts typeless additions for Java, Go, and Rust, emitting only count. These generated definitions do not compile, so signature edits can leave affected source files invalid. Add language-specific rendering and reject additions whose required type information is absent. This must be fixed before merging.

Knowledge Base Used: Multi-language parsing (codebase_rag/parsers)

Artifacts

Evidence from the check

  • This authored script invokes the changed renderer for the claimed language/specification combinations and compiles its C++, Go, and Rust output, showing the invalid definitions.

Evidence from the check

  • This executable command records the working directory and runs the authored targeted harness, showing the invalid output.

Command output from the check

  • The executed harness rendered C# and C++ annotations with Python syntax and produced typeless Java, Go, and Rust additions; real C++, Go, and Rust compilers reject the rendered definitions, confirming the finding.

Evidence from the check

  • This executable command compiles valid C++, Go, and Rust parameter forms for side-by-side comparison with the rendered output.

Command output from the check

  • The executed baseline compiled `int count`, `count int`, and `count: i32` successfully, establishing that the compiler failures are caused by the renderer's generated spellings.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +176 to +178
old = _parameters(node, language)
if any(p.node.type in _VARIADIC_PARAM_TYPES for p in old):
raise SignatureRefused(cs.SIGNATURE_VARIADIC.format(qn=qn))

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.

P1 Retain Go variadic semantics

A Go parameter declared as args ...string is not recognized by the variadic refusal guard. Changing its annotation is planned as args int, silently converting a variadic API into a single-argument API while leaving syntactically valid Go code. Refuse Go variadic parameter edits or preserve the ... grammar explicitly. This must be fixed before merging.

Knowledge Base Used: Multi-language parsing (codebase_rag/parsers)

Artifacts

Evidence from the check

  • A temporary Python harness creates a Go variadic definition, invokes the changed planner with graph responses, and optionally enables the proposed guard, demonstrating the semantic-loss path.

Command output from the check

  • The executed current-code run plans the Go edit and rewrites `args ...string` to `args int` while the patch remains parseable and formatted, confirming variadic semantics are removed.

Command output from the check

  • The executed control run adds the Go variadic AST node to the refusal set and the same request is refused, showing the required guard prevents the loss.

View artifacts

T-Rex Ran code and verified through T-Rex

@greptile-apps

greptile-apps Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Comments Outside Diff

These findings sit on lines the diff does not cover, so they could not be posted inline. Each one leaves this list once its file changes.

  • P1 C named arguments are rewritten as positional values after a signature reorder ▶

    • Bug
      • For F(y: 2, x: 1), _split_call_arguments unwraps each C# argument wrapper to its final expression and returns positional values 2 and 1 with no keyword entries. _map_arguments then maps those values by source position while reordering (x, y) to (y, x), producing F(1, 2) rather than preserving/refusing the named call. The rewritten call binds y=1, x=2, unlike the original y=2, x=1.
    • Cause
      • codebase_rag/parsers/call_processor.py::_split_call_arguments unconditionally replaces a C# argument node with child.named_children[-1], discarding its name: component before named-argument classification. codebase_rag/editing/signature_calls.py::_map_arguments consequently treats these values as positional.
    • Fix
      • Preserve and parse the C# argument wrapper's optional name: component into the keyword mapping before unwrapping its value. For a reordered C# signature, either retain the original named syntax when safe or return SIGNATURE_NEEDS_KEYWORDS/an explicit unmapped result instead of emitting positional arguments.
  • P1 Signature additions emit invalid parameters for supported languages ▶

    • Bug
      • _render_param handles only Go, Java, and Rust specially; all other supported languages take the Python-style fallback. Thus a C# or C++ spec such as count:int becomes count: int, which is invalid in those languages. The special branches also return bare names when no annotation is supplied, so Java, Go, and Rust accept requests that produce definitions with required types omitted.
    • Cause
      • codebase_rag/editing/signature_params.py:184-195 neither limits signature rewriting to grammars with supported rendering rules nor rejects missing annotations where the target grammar requires a type.
    • Fix
      • Add explicit renderers and validation for every language accepted by change-signature, including C# and C++. Reject a new or rebuilt parameter without an annotation for Java, Go, and Rust (and other type-required languages) with SignatureRefused rather than emitting a bare identifier.
  • P1 Go variadic signature edits can remove ... semantics ▶

    • Bug
      • SignaturePlanner.plan() only refuses the Python splat node types. For a Go definition such as func Collect(args ...string), changing the carried parameter annotation rebuilds it as func Collect(args int), changing a variadic parameter into one scalar parameter. The output remains syntactically valid and gofmt-clean, so patch validation does not catch the semantic contract change.
    • Cause
      • codebase_rag/editing/signature_params.py defines _VARIADIC_PARAM_TYPES with only list_splat_pattern and dictionary_splat_pattern; it omits cs.TS_GO_VARIADIC_PARAMETER_DECLARATION, despite that Go node constant being defined in codebase_rag/constants/ast_go.py. The guard at signature_planner.py:177 therefore does not recognize a Go variadic_parameter_declaration.
    • Fix
      • Add cs.TS_GO_VARIADIC_PARAMETER_DECLARATION to _VARIADIC_PARAM_TYPES (or use a language-aware equivalent) and add a regression test that changing a Go args ...T signature is refused.

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 8 High severity · 4 Medium severity

Open (12)
What changed in this PR

Adds graph-backed planning for change-signature edits across definitions and callers.

Changes:

  • Adds signature metadata Cypher queries and evaluator support.
  • Introduces parameter parsing, type checks, definition rewriting, and call-site mapping.
  • Extends edit contracts and constants for signature-change reporting.
File Description
evals/​cgr_graph.py Updated as part of this pull request.
codebase_rag/​editing/​signature_types.py Updated as part of this pull request.
codebase_rag/​editing/​signature_rewrite.py Updated as part of this pull request.
codebase_rag/​editing/​signature_planner.py Updated as part of this pull request.
codebase_rag/​editing/​signature_params.py Updated as part of this pull request.
codebase_rag/​editing/​signature_literals.py Updated as part of this pull request.
codebase_rag/​editing/​signature_calls.py Updated as part of this pull request.
codebase_rag/​editing/​contract.py Updated as part of this pull request.
codebase_rag/​cypher_queries.py Updated as part of this pull request.
codebase_rag/​constants/​mcp.py Updated as part of this pull request.
codebase_rag/​constants/​graph.py Updated as part of this pull request.
codebase_rag/​constants/​cli.py Updated as part of this pull request.
codebase_rag/​constants/​ast_python.py Updated as part of this pull request.
codebase_rag/​constants/​ast_nodes.py Updated as part of this pull request.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +70 to +72
positional, keyword = _split_call_arguments(args_node)
if any(child.type in _SPLAT_TYPES for child in args_node.named_children):
return cs.SIGNATURE_SPLAT
Comment on lines +105 to +109
for child in params.named_children:
if child.type == cs.TS_PY_KEYWORD_SEPARATOR:
keyword_only = True
continue
if child.type in _COMMENT_TYPES or child.type in _SEPARATOR_TYPES:
Comment on lines +190 to +194
text = spec.name
if annotation:
text += f": {annotation}"
if default is not None:
text += f" = {default}" if annotation else f"={default}"
) -> list[ParamSpec]:
names = [p.name for p in old if not p.receiver and not p.keyword_only]
resolved: list[ParamSpec] = []
seen: set[str] = set()
Comment on lines +177 to +178
if any(p.node.type in _VARIADIC_PARAM_TYPES for p in old):
raise SignatureRefused(cs.SIGNATURE_VARIADIC.format(qn=qn))
Comment thread evals/cgr_graph.py
Comment on lines +428 to +429
for label, uid in targets:
props = self.nodes[(label, uid)]
TESTS_REACHING = "tests_reaching"
# Graph-driven edit operations (issue #1532).
RENAME = "rename"
CHANGE_SIGNATURE = "change_signature"
parser = self._parsers.get(language) if language is not None else None
if parser is None:
return language, None
return language, parser.parse(source).root_node
Comment on lines +128 to +146
for spec in specs:
if spec.literal is None:
continue
annotation = spec.annotation
if (
annotation is None
and spec.from_index is not None
and spec.from_index < len(declared)
):
annotation = declared[spec.from_index] or None
if annotation is None:
continue
kind = _literal_kind(spec.literal)
if kind is not None and not _compatible(kind, annotation):
raise SignatureRefused(
cs.SIGNATURE_LITERAL_TYPE.format(
literal=spec.literal, name=spec.name, annotation=annotation
)
)
Comment on lines +159 to +164
if (
isinstance(positional, list)
and positional
and positional[0] in _RECEIVERS
):
out = out[1:] if len(out) == len(positional) else out
@vitali87
vitali87 removed this pull request from stack #2055 September 22, 2026 22:08
@vitali87
vitali87 added this pull request to stack #2133 September 22, 2026 22:09
@vitali87

Copy link
Copy Markdown
Owner Author

Superseded: change_signature lands through the split of #1912, which replaces #1548, as the stack #2163 → #2161 → #2162 → #2166 → #2164 → #2169 → #2168 → #2165 → #2167 on main. Closing this split-pr1548 stack at the owner's direction.

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

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants