Skip to content

Application diff: derive the comparison scope from the change when --scope is omitted #875

Description

@pengfei-threemoonslab

User problem

diff --application compares one --scope, and it defaults to the repository root. Someone reviewing a PR in an unfamiliar repository does not know what to pass. Both obvious choices fail often on real PRs:

  • Repository root:
    • One unrelated symlink or gitlink anywhere refuses the comparison (being fixed separately).
    • One file anywhere that uses another framework (anthropic, LangChain, CrewAI, MCP server source) marks the whole result partial.
    • Discovery is bounded at 1000 Python files.
  • The directory of the changed files: often contains no agent at all. The PR edits a tool or service module, and the agent that binds it is constructed elsewhere.

Measurement (2026-09-25, main a430e81a)

First corpus: 134 open SDK/ADK PRs.

Second corpus: 50 real application PRs that edit an existing agent's wiring (merged or open, last 90 days, pinned refs).

  • Scope = common parent of the changed wiring files: 30 not_established, 18 partial, 2 compared.
  • Repository root (42 of 50 run): 11 not_established, 29 partial, 2 exit 2. Among these, 12 PRs carry a gap from a file that uses another framework.

Worked example: mezgoodle/Vesta#58 (base 96f08d60…, head 8626cba5…). The PR changes tool definitions under backend/app/services/; the agents live in backend/app/agents/.

--scope Result
backend/app/services (where the change is) not_established, no agent
backend/app 5 head agents found, 8.4 s
backend same agents, 12.2 s

A first-time user who passes the changed directory is told no application agent exists.

Proposal

When --scope is omitted, derive the comparison scope from the change instead of defaulting to the repository root.

  1. Start from the changed Python files, on both sides of the compared refs.
  2. Relate those files to SDK/ADK candidate files found by existing discovery. Follow imports in both directions (a changed module imported by an agent module, or importing one), with a bounded depth and file count. Use Google ADK: resolve repository-local imported functions and module-qualified tool bindings #864's resolver where available.
  3. Choose the smallest directory that contains each related group of changed files and agent constructions.
  4. Report the choice.
    • Print the selected scope(s) and the rule in the header, e.g. scope: backend/app (derived: changed backend/app/services/gemini_tools.py is imported by backend/app/services/adk_service.py, which builds the agents defined in backend/app/agents/).
    • JSON records scope_selection with mode (derived or explicit), the reason, and candidate paths.
    • An explicit --scope always wins.
  5. No relation: if the change touches no SDK/ADK agent or module related to a tool, say exactly that. This is not_established with a reason naming the changed files considered. It is a useful answer; it is not a failure.

This is a projection over existing discovery and the existing comparison. It adds no new verdict and no new command.

Acceptance

  • Vesta#58 with no --scope derives backend/app (or a documented equivalent), finds the five head agents, and prints why.
  • A change confined to a tool module whose importing agent lives in a sibling package derives the scope that contains both.
  • A monorepo PR touching two independent apps yields two comparisons, never root.
  • A README-only or non-agent Python change yields the explicit "touches no SDK/ADK agent" answer.
  • Bounded:
    • Import following has fixed depth and file limits.
    • Exceeding them is a named limit and an input to scope selection, never a silent fallback to root.
    • Runtime on the 50-PR corpus is published.
  • Rerun the pinned 50-PR corpus with no --scope. Publish how many PRs reach an established comparison, compared with the two fixed-scope baselines above.
  • Docs (docs/application-comparison.md) and the distribution-surface registry row are updated together with the parity test. CHANGELOG entry.

Part of #868. Related: #580 (independent base/head scopes, relocation), #867 (per-agent wiring without a deployment root), the separate symlink-refusal fix, #864 (import resolution used for relating files).

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions