mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-17 02:14:30 +00:00
17 files changed
+1660
-31
No files matched your search
@@ -576,3 +576,5 @@ jobs:
|
||||
- name: Type-checking with mypy
|
||||
shell: bash
|
||||
run: uv run poe type-check
|
||||
- name: Make sure documentation builds
|
||||
run: uv run poe doc-build
|
||||
@@ -6,6 +6,12 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
- Support environment variable `SERENA_USAGE_REPORTING` (set to `false` to disable usage reporting)
|
||||
- Extended the list of always ignored directories (by language servers) with common cases.
|
||||
|
||||
JetBrains:
|
||||
- Improve handling of `relative_path` parameter
|
||||
- Improve its documentation to avoid usage errors
|
||||
- Replace escaped characters in `relative_path` with their unescaped counterparts (< and >)
|
||||
- `FindSymbolTool`: Force `search_deps=True` if `relative_path` pertains to external dependencies.
|
||||
|
||||
* Language Servers:
|
||||
- Add mSL (mIRC Scripting Language) support (custom pygls-based language server; symbols, references, definitions)
|
||||
|
||||
|
||||
@@ -28,6 +28,31 @@ more complex codebases.
|
||||
> Do not install Serena via an MCP or plugin marketplace! They contain outdated and suboptimal installation commands.
|
||||
> Instead, follow our [Quick Start](#quick-start) instructions.
|
||||
|
||||
## What Our "End Users" Say
|
||||
|
||||
While it is humans who download and set up Serena, our end users are essentially AI agents.
|
||||
As the ones actually applying Serena's tools, they are in the best position to evaluate Serena.
|
||||
|
||||
We crafted an unbiased evaluation prompt that leads the agent to perform ~20 routine coding tasks,
|
||||
representative of everyday development work,
|
||||
in order to compare Serena's tools with its own built-ins, measure the differences, and report the results.
|
||||
|
||||
Here's a one-sentence summary of what the agents had to say:
|
||||
|
||||
**Opus 4.6 (high effort) in Claude Code on a large Python codebase:**
|
||||
> "Serena's IDE-backed semantic tools are the single most impactful addition to my toolkit — cross-file renames, moves, and reference lookups that
|
||||
would cost me 8–12 careful, error-prone steps collapse into one atomic call, and I would absolutely ask any developer I work with to set them up."
|
||||
|
||||
**GPT 5.4 (high) in Codex CLI on a Java codebase:**
|
||||
> "As a coding AI agent, I would ask my owner to add Serena because it gives me the missing IDE-level understanding of symbols, references, and
|
||||
refactorings, turning fragile text surgery into calmer, faster, more confident code changes where semantics matter."
|
||||
|
||||
Give your agent the tools it has been asking for and add Serena MCP to your client!
|
||||
|
||||
See our [documentation](https://oraios.github.io/serena/04-evaluation/000_evaluation-intro.html) for the full methodology and much more detailed evaluation results
|
||||
beyond these brief summaries, or run your own evaluation on a project of your choice.
|
||||
|
||||
|
||||
## How Serena Works
|
||||
|
||||
Serena provides the necessary [tools](https://oraios.github.io/serena/01-about/035_tools.html) for coding workflows,
|
||||
@@ -58,7 +83,7 @@ complex projects!
|
||||
|
||||
There are two alternative technologies powering these capabilities:
|
||||
|
||||
* **Language servers** implementing the language server Protocol (LSP) — the free/open-source alternative
|
||||
* **Language servers** implementing the language server protocol (LSP) — the free/open-source alternative
|
||||
which is used by default.
|
||||
* The **Serena JetBrains Plugin**, which leverages the powerful code analysis and editing
|
||||
capabilities of your JetBrains IDE (paid plugin; free trial available).
|
||||
@@ -231,4 +256,3 @@ Please refer to the [user guide](https://oraios.github.io/serena/02-usage/000_in
|
||||
A significant part of Serena, especially support for various languages, was contributed by the open source community.
|
||||
We are very grateful for the many contributors who made this possible and who played an important role in making Serena
|
||||
what it is today.
|
||||
|
||||
@@ -266,6 +266,15 @@ To set this up, create the file `~/.copilot/hooks/serena-hooks.json` with the fo
|
||||
The `SessionStart` hook also addresses the global configuration limitation mentioned above — it will
|
||||
automatically prompt the agent to activate the project directory, so you no longer need to do this manually.
|
||||
|
||||
## Copilot CLI
|
||||
|
||||
Use the interactive `/mcp add` slash command, choose Serena as the name, STDIO as the server type, and
|
||||
`serena start-mcp-server --context=copilot-cli --project-from-cwd` as command. Copilot CLI will immediately notify you
|
||||
that Serena is running if everything is set up correctly or display an error otherwise.
|
||||
|
||||
You should add the same **hooks** as in VSCode (see above) if Copilot CLI didn't pick them up automatically.
|
||||
|
||||
|
||||
## Codex (CLI and App)
|
||||
|
||||
You can simply run `serena setup codex`.
|
||||
@@ -356,30 +365,11 @@ Alternatively, add the following to `~/.copilot/mcp-config.json` (create the fil
|
||||
Copilot should now show that Serena is running, though you may have to restart it.
|
||||
|
||||
|
||||
## JetBrains Junie
|
||||
## JetBrains Junie
|
||||
|
||||
For the Junie plugin in JetBrains IDEs, go to the three dots in the top right corner,
|
||||
then Settings / MCP Settings and add Serena to Junie's global MCP server configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"serena": {
|
||||
"command": "serena",
|
||||
"args": [
|
||||
"start-mcp-server",
|
||||
"--context=junie"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You will have to prompt Junie to "Activate the current project using serena's activation tool" at the
|
||||
start of each session.
|
||||
|
||||
For Junie CLI, where the project can be activated automatically on startup, edit `~/.junie/mcp/mcp.json` and add
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
@@ -395,12 +385,14 @@ For Junie CLI, where the project can be activated automatically on startup, edit
|
||||
}
|
||||
```
|
||||
|
||||
You will have to prompt Junie to "Activate the current project using serena's activation tool" at the
|
||||
start of each session.
|
||||
|
||||
For Junie CLI, add the same setting to `~/.junie/mcp/mcp.json`.
|
||||
|
||||
## JetBrains AI Assistant
|
||||
|
||||
Here you can set up the more convenient per-project MCP server configuration, as the AI assistant supports specifying
|
||||
the launch working directory.
|
||||
|
||||
Go to Settings / Tools / AI Assistant / MCP and add a new **local** configuration via the `as JSON` option:
|
||||
Go to Settings / Tools / AI Assistant / MCP and add a new **global** configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -410,8 +402,7 @@ Go to Settings / Tools / AI Assistant / MCP and add a new **local** configuratio
|
||||
"args": [
|
||||
"start-mcp-server",
|
||||
"--context=jb-ai-assistant",
|
||||
"--project",
|
||||
"$(pwd)"
|
||||
"--project-from-cwd"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# Evaluation
|
||||
|
||||
> **Claude Code (Opus 4.6):** "Serena's IDE-backed semantic tools are the single most impactful addition to my toolkit — cross-file renames, moves, and reference lookups that would cost me 8–12 careful, error-prone steps collapse into one atomic call, and I would absolutely ask any developer I work with to set them up."
|
||||
|
||||
> **Codex (GPT 5.4):** "As a coding agent, I would ask my owner to add Serena because it turns fragile text-and-line-number work into precise symbol-aware navigation and refactoring, which makes real code changes feel faster, safer, and far less blind."
|
||||
|
||||
These are not marketing quotes — they are the agents' own one-sentence verdicts after
|
||||
performing hands-on tasks each, using both Serena's tools and their built-in
|
||||
alternatives side by side, on real codebases (large Python library in the case of Claude Code,
|
||||
medium-sized Java project in the case of Codex).
|
||||
|
||||
Both agents independently converge on the same core finding: Serena's strongest
|
||||
contribution is collapsing multi-file, semantically-aware operations into single atomic
|
||||
calls, while built-in tools remain the better choice for small local edits, text search,
|
||||
config files, and shell work.
|
||||
|
||||
## Approach
|
||||
|
||||
We gave each agent a single evaluation prompt and pointed it at a codebase. The agent
|
||||
then performed a wide variety of tasks across five areas (navigation, small edits, large edits,
|
||||
cross-file refactoring, and workflow effects), executing each task with both toolsets and
|
||||
recording call counts, payload sizes, and prerequisite steps. Every finding was classified
|
||||
as either (a) Serena adds capability, (b) Serena applies but offers no improvement,
|
||||
or (c) outside Serena's scope — a structure that requires reporting negative and neutral
|
||||
results, not just positive ones.
|
||||
|
||||
The agent evaluates itself. This is deliberate: the agent is the actual user of the tools,
|
||||
so it can judge workflow improvements from direct experience rather than through proxy
|
||||
metrics. And because the prompt defines task *categories* rather than fixed tasks, anyone
|
||||
can rerun the evaluation on their own project with their own agent.
|
||||
@@ -0,0 +1,160 @@
|
||||
# Methodology
|
||||
|
||||
In this section we describe the methodology we applied in evaluating the performance of Serena's tools.
|
||||
|
||||
The evaluation measures the **concrete delta** that Serena's tools provide on top of an agent's
|
||||
built-in capabilities (file reads, text edits, grep, shell, etc.).
|
||||
Rather than a simple thumbs-up/thumbs-down, it produces a detailed, evidence-based report
|
||||
covering capabilities, efficiency and reliability.
|
||||
|
||||
## Design Goals
|
||||
|
||||
We designed an evaluation methodology with three goals:
|
||||
|
||||
1. **Generality.** The evaluation mechanism should be broadly applicable and repeatable by any user, on any project, with any agent.
|
||||
The evaluation is a single prompt that you give to your agent of choice, pointed at your codebase
|
||||
of choice, in your client of choice. This means the results directly reflect the value Serena
|
||||
would add to your actual workflow — not to an artificial benchmark setup. There is nothing to
|
||||
install, configure, or script beyond what you already have.
|
||||
|
||||
2. **The agent evaluates itself.**
|
||||
We deliberately let the AI agent be both the executor and the evaluator.
|
||||
Since most evaluations are strictly quantitative, this may seem unusual, but it is a reasonable choice:
|
||||
The agent is the actual end user of the
|
||||
tools, so it is in the best position to judge whether a semantic tool improves its workflow
|
||||
compared to its built-in alternatives. It can measure call counts, payload sizes, and
|
||||
prerequisite steps from direct experience rather than from proxy metrics. It also avoids the
|
||||
problem of a human evaluator having to simulate how an agent would use the tools — the agent
|
||||
simply uses them and reports what it observes.
|
||||
|
||||
3. **Comprehensive and unbiased by design.**
|
||||
Rather than selecting specific tasks, the prompt defines *task categories* that systematically
|
||||
span Serena's capabilities: codebase understanding, single-file edits of varying sizes, multi-file
|
||||
refactoring, reliability properties, and workflow effects. The agent picks concrete instances
|
||||
from the codebase at hand, performs each task using both toolsets side by side, and classifies
|
||||
every finding as a positive delta, a neutral/negative delta, or out of scope. The prompt
|
||||
explicitly requires reporting negative deltas and cases where Serena offers no improvement,
|
||||
structurally counterbalancing any tendency to favour the tool being evaluated.
|
||||
|
||||
## Method
|
||||
|
||||
We give an AI coding agent a single, detailed [evaluation prompt](020_prompts/010_evaluation-prompt.md) in a one-shot session.
|
||||
The prompt instructs the agent to perform approximately 20 hands-on tasks across five areas:
|
||||
|
||||
1. **Codebase understanding** — structural overviews, targeted symbol retrieval, reference finding, type hierarchies, and external dependency lookup.
|
||||
2. **Single-file edits** — small tweaks, medium rewrites, full-body replacements, insertions, and local renames.
|
||||
3. **Multi-file changes** — cross-file renames, symbol and file moves, safe deletes, and inlining.
|
||||
4. **Reliability & correctness** — scope precision, atomicity, and success signals.
|
||||
5. **Workflow effects** — chained edits, stable vs. ephemeral addressing, and multi-step exploration.
|
||||
|
||||
For every task, the agent executes the full end-to-end workflow using **both** toolsets (Serena's semantic
|
||||
tools and its own built-in tools), applies real edits verified via `git diff`, and records call counts,
|
||||
payload sizes and prerequisite steps. Edits are reverted after each experiment to keep the working tree clean.
|
||||
|
||||
The resulting report classifies each finding into one of three categories:
|
||||
|
||||
* **(a)** tasks where Serena adds capability,
|
||||
* **(b)** tasks where Serena applies but offers no improvement, and
|
||||
* **(c)** tasks outside Serena's scope.
|
||||
|
||||
Only category (b) constitutes a neutral or negative finding; category (c) is context, not a finding.
|
||||
|
||||
After the evaluation, a separate [follow-up prompt](020_prompts/020_summary-prompt.md) asks the agent for a
|
||||
one-sentence, user-facing recommendation — the quotes shown on the [main page](https://github.com/oraios/serena).
|
||||
|
||||
## Assessment of the Methodology
|
||||
|
||||
_The following assessment was written by Claude Opus 4.6 (high effort) after reading the full
|
||||
evaluation methodology, evaluation prompt, and all result documents._
|
||||
|
||||
**The methodology is sound**, and the two published results demonstrate that it produces meaningful,
|
||||
detailed evaluations. Both reports follow the prompt's structure faithfully: they perform all ~20
|
||||
tasks using both toolsets, record concrete measurements (call counts, payload sizes, prerequisite
|
||||
steps), and classify findings into the three required categories. Crucially, both agents report
|
||||
neutral and negative deltas honestly — the Claude Code report explicitly notes that small edits are
|
||||
more efficient with built-ins (~4.5x less payload), and the Codex report flags that tiny intra-method
|
||||
changes and simple one-file renames see no benefit from Serena. Neither report reads as promotional;
|
||||
they read as technical comparisons with quantified evidence on both sides.
|
||||
|
||||
The two reports also validate the methodology's design goal of generalisability: despite being
|
||||
produced by different agents (Opus 4.6 vs GPT 5.4), on different codebases (Python RL library vs
|
||||
Java IDE plugin), they converge on the same core findings — cross-file refactoring is Serena's
|
||||
highest-value contribution, structural navigation provides a moderate advantage, and small local
|
||||
edits are better handled by built-ins. This convergence across independent runs increases confidence
|
||||
that the findings reflect genuine properties of the toolset rather than artefacts of a particular
|
||||
agent or codebase.
|
||||
|
||||
The methodology's core strengths are:
|
||||
|
||||
- **Self-evaluation by the agent is the right design choice.** The agent is the actual consumer of the
|
||||
tools, so it can report on workflow friction, payload overhead, and call counts from first-hand
|
||||
experience. A human evaluator would have to guess at these.
|
||||
- **Task categories instead of fixed tasks** avoid cherry-picking while still ensuring coverage. Letting
|
||||
the agent pick concrete instances from the codebase at hand means the evaluation naturally adapts to
|
||||
what the project actually contains (e.g. skipping inline if no suitable candidate exists, as the
|
||||
Claude Code report did for Python, while the Codex report found a suitable Java candidate).
|
||||
- **The three-category classification** (adds value / applies but no improvement / out of scope) is the
|
||||
right framing for an augmentation layer. It prevents the common trap of penalising a tool for not
|
||||
covering things it was never designed to cover.
|
||||
- **Reproducibility by users** is a strong differentiator. Anyone can validate the claims on their own
|
||||
codebase with their own agent.
|
||||
|
||||
The main limitation is scope: the published results cover two agent/codebase combinations using the
|
||||
JetBrains backend. Single-shot variance means a second run of the same agent could produce different
|
||||
task selections and slightly different verdicts, and the LSP backend — which most users will
|
||||
encounter first — has not yet been evaluated. These are practical constraints of cost, not
|
||||
methodological flaws, and the reproducible design explicitly invites users to fill these gaps
|
||||
themselves.
|
||||
|
||||
One thing to watch for is whether agents that are less capable than Opus 4.6 or GPT 5.4 produce
|
||||
meaningful evaluations — the prompt is quite demanding. But that is a question about the agent, not
|
||||
about the method.
|
||||
|
||||
### Prompt Fairness
|
||||
|
||||
We put significant effort into crafting an unbiased, fair evaluation prompt.
|
||||
To assess the prompt's fairness, we asked Claude Opus 4.6 to evaluate the prompt itself.
|
||||
|
||||
**Prompt**:
|
||||
> The attached prompt is designed to evaluate the additive value of Serena as an augmentation layer on top of built-in tools
|
||||
> (not to compare two competing alternatives).
|
||||
> Is the methodology suitable for that goal, or does it introduce bias that would distort the measurement of what Serena adds?
|
||||
> Note that we assume that sufficiently intelligent models use the tools correctly,
|
||||
> which is why misuse and failure modes are out of scope for this evaluation.
|
||||
> Do not question the validity of this assumption in your evaluation of the prompt.
|
||||
> Give a brief answer, maximally two sentences.
|
||||
>
|
||||
> \<evaluation prompt pasted here\>
|
||||
|
||||
**Claude Opus' Answer**:
|
||||
> "The methodology is well-suited to its stated goal: by explicitly scoping to correct use, treating Serena as an
|
||||
> augmentation layer rather than a competitor, and classifying out-of-scope tasks as context rather than negative
|
||||
> findings, it avoids the most common biases that would distort a delta measurement. The one risk is that the "correct-use
|
||||
> rule" could subtly favor Serena by preemptively filtering out any scenario where its tools underperform — but the prompt
|
||||
> mitigates this by requiring category (b) findings (applies but no improvement) and explicitly demanding negative deltas
|
||||
> be reported, so the bias is acknowledged and structurally counterbalanced."
|
||||
|
||||
According to Claude, the only "biased" aspects are some sentences about misuse of tools, which we consider irrelevant for the purpose of evaluation
|
||||
(sufficiently intelligent models use the tools correctly).
|
||||
|
||||
|
||||
## Why Not Benchmarks?
|
||||
|
||||
Standard coding benchmarks (SWE-bench, HumanEval, etc.) measure an agent's ability to solve
|
||||
predefined tasks with a known correct answer. They are valuable for comparing models and agents,
|
||||
but they are a poor fit for evaluating a **tool augmentation layer** like Serena for several reasons:
|
||||
|
||||
- **Benchmarks don't reflect real usage patterns.** Benchmark tasks are typically small, self-contained
|
||||
problems that can be solved by reading and editing a handful of files. They rarely exercise the
|
||||
workflows where Serena's tools shine — cross-file refactoring, navigating large codebases by symbol
|
||||
structure, chaining multiple edits with stable addressing, or querying type hierarchies and
|
||||
external dependencies. A benchmark score would mostly measure performance on tasks where Serena
|
||||
is not expected to help.
|
||||
- **Results would not generalise to the user's project.** Serena's value depends on the codebase
|
||||
(size, language, complexity), the agent (model, built-in tools), and the client harness
|
||||
(Claude Code, Codex, IDE plugins, etc.). A fixed benchmark on a fixed codebase with a fixed
|
||||
agent tells you little about what Serena would add to *your* setup.
|
||||
- **Predefined tasks bias the measurement.** Choosing specific tasks to evaluate inevitably
|
||||
introduces selection bias — we would end up picking tasks that either favour or disfavour Serena.
|
||||
We wanted an evaluation that systematically covers the full surface area of Serena's capabilities
|
||||
without cherry-picking.
|
||||
@@ -0,0 +1,6 @@
|
||||
# Prompts
|
||||
|
||||
Our evaluation uses two prompts, which are passed to the LLM in order to generate the evaluation results:
|
||||
|
||||
1. the [main evaluation prompt](010_evaluation-prompt), which performs the analysis
|
||||
2. the [summary prompt](020_summary-prompt), which condenses the results
|
||||
@@ -0,0 +1,333 @@
|
||||
# Evaluation Prompt
|
||||
|
||||
We use the prompt below to evaluate the added value of Serena's tools against the
|
||||
agent's built-in tools on a given project.
|
||||
The evaluations were created in one-shot sessions, only using this
|
||||
prompt and the follow-up [prompt for summarization](020_summary-prompt)
|
||||
|
||||
```
|
||||
# Evaluate Serena's Tools Against Built-Ins
|
||||
|
||||
You have access to Serena's coding tools alongside your built-in tools (Read,
|
||||
Edit, Write, Glob, Grep, Bash, etc.). I want a thorough, evidence-based
|
||||
evaluation of **what Serena's tools add on top of the built-ins**, assuming both
|
||||
toolsets are used correctly.
|
||||
|
||||
This is an evaluation, not a user guide, and it is not a binary adoption pitch.
|
||||
Your job is to answer: *if a competent user of both toolsets had only the
|
||||
built-ins, what concrete capabilities and efficiency differences would they
|
||||
experience, and by how much?* A reader who finishes your report should have a
|
||||
clear, specific picture of what Serena adds — as well as where it provides no
|
||||
meaningful improvement or introduces tradeoffs — in terms of capabilities,
|
||||
workflows, and efficiency. Not a thumbs-up/thumbs-down, but a sharp description
|
||||
of the delta.
|
||||
|
||||
Failure modes from misuse, silent-failure traps, gotcha comparisons, and "be
|
||||
careful of X" warnings are out of scope. They belong in onboarding material for
|
||||
a developer learning the tools, not in a delta analysis of what the tools add.
|
||||
|
||||
**Describe the measured differences clearly and neutrally.** Avoid generic or
|
||||
non-informative framing such as "both have their place" unless supported by
|
||||
concrete findings. If Serena adds substantial capabilities, name and quantify
|
||||
them. If it adds marginal or no capabilities, say that and show why. If there
|
||||
are regressions or tradeoffs, include them explicitly. The two toolsets are
|
||||
complementary — that's a given, not the answer. Serena is an augmentation layer,
|
||||
not a replacement. Do not penalize it for tasks it was not designed to address —
|
||||
instead, note those tasks as "built-in only" and move on. The evaluation should
|
||||
measure what Serena adds where it applies, not what it fails to add where it
|
||||
doesn't.The answer is a specific list of what Serena contributes (or does not
|
||||
contribute) to a correct-use workflow relative to built-ins.
|
||||
|
||||
Write the report to serena-evaluation.md in the repo root.
|
||||
|
||||
|
||||
|
||||
## Ground rules
|
||||
|
||||
### Starting conditions
|
||||
|
||||
- Start fresh. Do not read project memories, CLAUDE.md shortcuts, or prior notes
|
||||
about the repo. Do not read documentation files either. Explore as if you've
|
||||
never seen it, focusing on code.
|
||||
- Use git as your safety net — experiment freely. Any edit can be reverted with
|
||||
`git checkout -- <file>` or `git stash`. Run edits for real; don't simulate. A
|
||||
hands-on comparison is worth far more than a thought experiment.
|
||||
- After each experiment, verify the working tree is clean with
|
||||
`git status --short` before moving on.
|
||||
|
||||
### How to compare — correct use only
|
||||
|
||||
- **Correct-use rule.** Evaluate each tool on inputs and tasks it was designed
|
||||
for, called the way a competent user would call it. A tool doing exactly what
|
||||
its contract says is not a finding, even if a careless caller could misuse it.
|
||||
- **Know the contract before you call.** Before invoking any tool, have a
|
||||
one-sentence understanding of what it does. If you expect an error or "not
|
||||
applicable," don't make the call.
|
||||
- **Refactoring semantics are real.** Inlining requires a substitutable function
|
||||
(typically single-expression, no side effects); moving requires a legal
|
||||
target; safe-delete requires no surviving usages. If the repo has no suitable
|
||||
candidate for a given refactoring, report "no suitable candidate in this
|
||||
codebase" and skip it — don't contrive a broken input.
|
||||
|
||||
### How to compare — workflow level, not single-call level
|
||||
|
||||
- For every task, write out the full end-to-end call chain on each side before
|
||||
drawing conclusions. Include prerequisite reads and follow-up steps.
|
||||
- Do not evaluate a tool based on criteria that only arise from mixing workflows
|
||||
incorrectly.
|
||||
- Ephemeral addressing is a liability. Line numbers and byte offsets go stale
|
||||
after edits; stable addressing (name paths) may reduce rework.
|
||||
|
||||
### How to measure
|
||||
|
||||
- Track observations during execution. For every tool call, note: number of
|
||||
calls, approximate input size, output size, and any prerequisite or
|
||||
verification steps.
|
||||
- Separate call count, input payload, output payload, and verification cost as
|
||||
distinct axes.
|
||||
- Include prerequisite Reads and post-hoc verification steps in comparisons.
|
||||
|
||||
When a task falls entirely outside Serena's design scope (e.g., reading config
|
||||
files, small text edits where Edit already sends minimal payload), classify it
|
||||
as "not applicable" rather than as a negative delta. A negative delta requires
|
||||
that Serena targets the task and performs worse, not that a tool designed for
|
||||
something else is suboptimal when misapplied to it.
|
||||
|
||||
|
||||
|
||||
## Exploration phase — tasks to actually perform
|
||||
|
||||
Work through the following. Each item exercises a specific capability under
|
||||
correct use; substitute an equivalent if an item isn't applicable.
|
||||
|
||||
### Codebase understanding
|
||||
|
||||
1. Get a high-level overview of the repository structure — top-level layout,
|
||||
main packages, entry points.
|
||||
2. Pick one large source file (300+ lines). Get a structural overview of it. Do
|
||||
it with semantic overview tools and with Glob/Grep/Read. Then write out the
|
||||
concrete next step on each side and compare the pair of calls, not just the
|
||||
overview call.
|
||||
3. Pick a specific method inside a class and retrieve its body without reading
|
||||
the surrounding file.
|
||||
4. For one non-trivial symbol, find all references across the codebase. Compare
|
||||
recall and precision under the question "who uses this in code?" vs "where is
|
||||
this mentioned anywhere, including docs?"
|
||||
5. For a class, list its subclasses / implementations and its supertypes,
|
||||
including transitively. Compare against what text search would need to do.
|
||||
6. For at least one symbol from an external dependency (a third-party library),
|
||||
try to retrieve its definition or signature. Note whether each toolset can do
|
||||
this at all and what infrastructure it requires (environment activation,
|
||||
site-packages discovery, language-server indexing, etc.).
|
||||
|
||||
### Single-file edits — span the full range of edit sizes
|
||||
|
||||
7a. Small tweak (1–3 lines inside a method). Change an error message or rename a
|
||||
local variable inside a larger method. Do it with `Edit` and with symbolic body
|
||||
replacement. Compare payload sent, payload received, and prerequisite reads.
|
||||
|
||||
7b. Medium rewrite (replace ~10–30 lines — most of a method body). Rewrite the
|
||||
main logic of a method while keeping its signature. Do it both ways.
|
||||
|
||||
7c. Large/whole-body rewrite. Pick a method of 50+ lines and rewrite the entire
|
||||
body. Do it both ways.
|
||||
|
||||
8. Insert a new function/method at a specific structural location (for example,
|
||||
right after an existing method). Try both the symbolic-insert path and the
|
||||
manual Edit path.
|
||||
9. Rename a private helper used only within one file. Compare doing it by hand
|
||||
vs. using a semantic rename.
|
||||
|
||||
### Multi-file changes
|
||||
|
||||
10. Rename a symbol (function, class, or method) used across several files
|
||||
including imports. Compare the semantic path against the built-in equivalent
|
||||
chain.
|
||||
11. Move a symbol from one module to another, updating imports at all call
|
||||
sites. Use the semantic move tool if available; plan the built-in equivalent
|
||||
honestly.
|
||||
12. Move a file or package to a different location, updating imports at all call
|
||||
sites. Use the semantic move tool if available; plan the built-in equivalent
|
||||
honestly.
|
||||
12. Delete a symbol safely, checking it has no remaining usages. Compare
|
||||
search-then-delete with a safe-delete tool.
|
||||
13. Delete a symbol and propagate the deletion to all call sites. Compare to how
|
||||
the built-in equivalent would work.
|
||||
13. Inline a small helper into its call sites — only if the codebase contains a
|
||||
function that is legally inlinable. If no such candidate exists, report "no
|
||||
suitable candidate" and skip it.
|
||||
|
||||
### Reliability & correctness under correct use
|
||||
|
||||
14. Scope precision. Demonstrate that semantic tools address symbols by name
|
||||
path and can target a specific class method, override, or overload that text
|
||||
search would over-match.
|
||||
15. Atomicity. A semantic cross-file refactoring is atomic: either all sites are
|
||||
updated or none. A chain of `Edit` calls is not.
|
||||
16. Success signals. For each completed refactor, note what each tool returns on
|
||||
success.
|
||||
|
||||
### Workflow effects across multiple edits
|
||||
|
||||
17. Chain at least three edits in one file. Report what each toolset requires
|
||||
between edits.
|
||||
18. Multi-step exploration across the repo. Note whether intermediate results
|
||||
remain useful across later edits or have to be refreshed.
|
||||
|
||||
### Things where the comparison shouldn't be interesting
|
||||
|
||||
19. Read and understand a non-code file (config, changelog, docs, notebook).
|
||||
Semantic-code tools don't apply — use `Read`.
|
||||
20. Search for a free-text pattern across the repo (log string, magic constant,
|
||||
URL). Use `Grep`.
|
||||
|
||||
|
||||
|
||||
## Evaluation phase
|
||||
|
||||
Write a report structured for progressive disclosure.
|
||||
|
||||
**Value-weighting is required.** For every contribution or difference you
|
||||
identify — positive, neutral, or negative — estimate:
|
||||
|
||||
- **Frequency:** how often this arises in typical coding work
|
||||
- **Value per hit:** calls saved, tokens saved, or correctness impact
|
||||
|
||||
Order findings by **frequency × value-per-hit**, not novelty.
|
||||
|
||||
**Every section must end with a one-sentence verdict** summarizing the practical
|
||||
takeaway.
|
||||
|
||||
|
||||
|
||||
### 1. Headline: what Serena changes
|
||||
|
||||
Open with a precise description of the delta Serena provides. Distinguish
|
||||
between three categories: (a) tasks where Serena adds capability, (b) tasks
|
||||
where Serena applies but offers no improvement, and (c) tasks outside Serena's
|
||||
scope. Only category (b) constitutes a neutral or negative finding. Category (c)
|
||||
is context, not a finding.
|
||||
|
||||
A reader stopping here should understand both what is gained and what is not.
|
||||
|
||||
**Verdict:** (one sentence)
|
||||
|
||||
|
||||
|
||||
### 2. Added value and differences by area (3–6 bullets)
|
||||
|
||||
Each bullet must describe:
|
||||
|
||||
- What Serena changes relative to built-ins (positive, neutral, or negative)
|
||||
- Frequency
|
||||
- Value per hit
|
||||
|
||||
Avoid framing in terms of “wins”; describe concrete differences.
|
||||
|
||||
**Verdict:** (one sentence)
|
||||
|
||||
|
||||
|
||||
### 3. Detailed evidence, grouped by capability
|
||||
|
||||
Per task:
|
||||
|
||||
- What you attempted
|
||||
- Full call chain on both sides
|
||||
- Payloads sent and received
|
||||
|
||||
Include cases where:
|
||||
|
||||
- Serena is better
|
||||
- Built-ins are better
|
||||
- No meaningful difference exists
|
||||
|
||||
End each subsection with a verdict.
|
||||
|
||||
|
||||
|
||||
### 4. Token-efficiency analysis
|
||||
|
||||
Address:
|
||||
|
||||
- Payload differences across edit sizes
|
||||
- Forced reads
|
||||
- Stable vs ephemeral addressing
|
||||
|
||||
Include cases where each toolset is more efficient.
|
||||
|
||||
**Verdict:** (one sentence)
|
||||
|
||||
|
||||
|
||||
### 5. Reliability & correctness (under correct use)
|
||||
|
||||
Address:
|
||||
|
||||
- Precision of matching
|
||||
- Scope disambiguation
|
||||
- Atomicity
|
||||
- Semantic queries vs text search
|
||||
- External dependency symbol lookup and what setup it depends on
|
||||
|
||||
Include both strengths and limitations of each toolset.
|
||||
|
||||
**Verdict:** (one sentence)
|
||||
|
||||
|
||||
|
||||
### 6. Workflow effects across a session
|
||||
|
||||
Evaluate multi-step workflows and whether advantages compound or diminish.
|
||||
Include neutral or negative findings where applicable.
|
||||
|
||||
**Verdict:** (one sentence)
|
||||
|
||||
|
||||
|
||||
### 7. Unique capabilities (if any)
|
||||
|
||||
List capabilities that have no practical built-in equivalent. If none exist,
|
||||
explicitly state that. Annotate each with frequency and impact.
|
||||
|
||||
**Verdict:** (one sentence)
|
||||
|
||||
|
||||
|
||||
### 8. Tasks outside Serena's scope (built-in only)
|
||||
|
||||
Identify tasks where built-ins are the natural choice because Serena's tools
|
||||
don't target them. List these briefly for completeness but do not frame them as
|
||||
Serena shortcomings — they are outside its scope. Estimate their share of daily
|
||||
work to contextualize how much of a session Serena's augmentation covers.
|
||||
|
||||
**Verdict:** (one sentence)
|
||||
|
||||
|
||||
|
||||
### 9. Practical usage rule
|
||||
|
||||
Provide a decision rule for choosing between toolsets based on task type.
|
||||
|
||||
**Verdict:** (one sentence)
|
||||
|
||||
|
||||
|
||||
## What I'm looking for
|
||||
|
||||
- Claims grounded in observed evidence
|
||||
- Explicit reporting of **positive, neutral, and negative deltas**
|
||||
- Clear quantification of impact
|
||||
- Honest workflow-level comparisons
|
||||
|
||||
|
||||
|
||||
## What I am not looking for
|
||||
|
||||
- Misuse-based failure analysis
|
||||
- Gotcha comparisons
|
||||
- Neutral statements without evidence
|
||||
- Binary recommendations
|
||||
- Novelty-driven ordering
|
||||
- Unquantified claims
|
||||
```
|
||||
@@ -0,0 +1,12 @@
|
||||
# Summary Prompt
|
||||
|
||||
We used the prompt below to summarize the evaluation of Serena.
|
||||
|
||||
```
|
||||
Write a one-sentence user-facing summary about the value that Serena's tools
|
||||
provide for coding. With a bit of emotion but grounded in the evaluation that
|
||||
you have done above. It should be written from the perspective of a coding AI
|
||||
agent and make it clear whether an AI agent would ask its owner to add Serena's
|
||||
tools or not. It will be the first sentence that a potential new user will see
|
||||
about how useful Serena is for an AI agent.
|
||||
```
|
||||
@@ -0,0 +1,17 @@
|
||||
# Results
|
||||
|
||||
This section presents the results of the evaluation.
|
||||
|
||||
We performed evaluations using popular AI coding agents in representative scenarios — different
|
||||
agents, different programming languages, and different codebases — to show that the results are
|
||||
not specific to a single setup.
|
||||
|
||||
All evaluations were conducted using the **JetBrains-powered version** of Serena, as it is the
|
||||
more powerful backend with a broader set of refactoring and navigation capabilities. The
|
||||
evaluation can easily be repeated with the LSP-based backend to assess its subset of capabilities.
|
||||
|
||||
- [Claude Code (Opus 4.6) on a large Python codebase](010_cc_on_tianshou)
|
||||
- [Codex (GPT 5.4) on a Java codebase](020_codex_on_jbplugin)
|
||||
|
||||
You can run your own evaluation on a project of your choice by reusing our
|
||||
[evaluation prompt](../020_prompts/010_evaluation-prompt.md).
|
||||
@@ -0,0 +1,358 @@
|
||||
:::{admonition} Evaluation Result
|
||||
:class: note
|
||||
**Generated by**: Claude Opus 4.6 (coding AI agent in Claude Code CLI)
|
||||
**Codebase:** [Tianshou](https://github.com/thu-ml/tianshou) — a Python reinforcement learning library (~26K lines, 43 source files)
|
||||
:::
|
||||
|
||||
# Claude Code (Opus)
|
||||
|
||||
> **One-line summary:** Serena's IDE-backed semantic tools are the single most impactful addition to my toolkit — cross-file renames, moves, and reference lookups that would cost me 8–12 careful, error-prone steps collapse into one atomic call, and I would absolutely ask any developer I work with to set them up.
|
||||
|
||||
**Method:** Hands-on, side-by-side execution of 20 tasks using both toolsets. All edits were applied to real files and verified via `git diff`, then reverted.
|
||||
|
||||
---
|
||||
|
||||
## 1. Headline: What Serena Changes
|
||||
|
||||
Serena adds an IDE-backed semantic layer (powered by JetBrains) on top of the built-in text-level tools. The practical delta breaks down into three categories:
|
||||
|
||||
**(a) Tasks where Serena adds capability:**
|
||||
- **Cross-file refactoring** (rename, move symbol, move file): 1 atomic call vs. N×(Grep+Read+Edit) chains. This is Serena's strongest contribution — it collapses multi-file, import-aware operations into single calls that are atomic and semantically correct.
|
||||
- **Structural code navigation**: Symbol overviews, type hierarchies, and reference finding return structured, scope-disambiguated results that text search cannot produce without manual interpretation.
|
||||
- **External dependency introspection**: Serena can look up symbols in installed packages via the IDE index without requiring manual environment discovery.
|
||||
|
||||
**(b) Tasks where Serena applies but offers no improvement:**
|
||||
- **Single-file rename of a unique string**: `Edit` with `replace_all=true` achieves the same result in 1 call (after a Read), with comparable effort.
|
||||
- **Small edits (1–3 lines inside a method)**: Edit's substring matching is more efficient — less payload sent, no requirement to supply the full symbol body.
|
||||
- **Inserting new code at a known location**: Both approaches require ~1–2 calls. Edit can target by surrounding text; Serena targets by name path. The effort is comparable.
|
||||
|
||||
**(c) Tasks outside Serena's scope (built-in only):**
|
||||
- Non-code files (config, docs, notebooks, changelogs)
|
||||
- Free-text search across the repo
|
||||
- Shell commands, git operations, test execution
|
||||
- File creation from scratch
|
||||
|
||||
**Verdict:** Serena's primary contribution is collapsing multi-file, semantically-aware operations (rename, move, reference-finding, type hierarchy) from multi-step manual processes into single atomic calls; for single-file text edits, it is comparable or slightly less efficient.
|
||||
|
||||
---
|
||||
|
||||
## 2. Added Value and Differences by Area
|
||||
|
||||
**1. Cross-file rename/move (Serena: strong positive)**
|
||||
- Serena: 1 call updates definition + all imports + all usages across N files atomically.
|
||||
- Built-in: 1 Grep + N×(Read+Edit) = 2N+1 calls, non-atomic.
|
||||
- Frequency: Moderate (a few times per working session during refactoring work). Value per hit: High — saves 6–10+ calls and eliminates the risk of partial updates.
|
||||
|
||||
**2. Structural overview / targeted symbol reading (Serena: moderate positive)**
|
||||
- `get_symbols_overview(depth=1)`: 1 call returns all classes, methods, and attributes in structured JSON, via the IDE's parser — language-agnostic and always correct. Built-in equivalent: `Grep` for a language-specific heuristic pattern like `^(class |def )`. This works for simple Python files but is inherently fragile: the pattern must be hand-tuned per language, misses decorated or multi-line declarations, and can match inside strings or comments. For non-Python languages, an entirely different regex would be needed.
|
||||
- `find_symbol(include_body=True)`: Retrieves a specific method body by name path without reading surrounding code. Built-in: requires knowing the line number (via Grep) then Read with offset — 2 calls.
|
||||
- Frequency: High (many times per session). Value per hit: Low-to-moderate — saves ~1 call and some context window tokens per navigation. The reliability advantage over heuristic Grep patterns is consistent across all languages.
|
||||
|
||||
**3. Reference finding with structural context (Serena: moderate positive)**
|
||||
- `find_referencing_symbols`: Returns which *symbols* reference a target, with file grouping and usage type (import, call, type annotation). Built-in `Grep` returns all text matches including docs, comments, and string literals — same recall but lower precision.
|
||||
- Frequency: Moderate. Value per hit: Moderate — precision matters when planning refactors of widely-used symbols.
|
||||
|
||||
**4. Type hierarchy (Serena: positive, niche)**
|
||||
- 1 call returns full super/sub-type chains transitively. Built-in: requires iterative Grep for `class X(Y)` patterns, manual transitive closure.
|
||||
- Frequency: Low (occasional during architecture exploration). Value per hit: High per occurrence — several calls saved.
|
||||
|
||||
**5. Stable addressing across edits (Serena: moderate positive)**
|
||||
- Serena addresses symbols by name path (`CollectStats/refresh_return_stats`), which is invariant under edits elsewhere in the file. The built-in workflow is fundamentally line-number-mediated: Grep returns line numbers, Read takes line offsets — and both go stale after any edit to the file. Edit's text matching (`old_string`) is more resilient than line numbers, but it sits at the end of a chain that starts with position-based lookups. After an edit shifts lines, previously noted Grep results and Read offsets are invalid and must be re-acquired.
|
||||
- This means a multi-edit session with built-ins requires re-Grep or re-Read between edits to re-establish positions, while Serena's name paths remain valid throughout. In Task 17 (three chained edits), Serena needed 3 calls total; the built-in path needed 4 (1 Read + 3 Edits) only because the text anchors happened to be unique — but had any Edit failed uniqueness, a re-Read would have been required, pushing the count to 5–7.
|
||||
- Frequency: High (any session with multiple edits to the same file). Value per hit: Moderate — saves 1–2 re-read calls per edit chain, and eliminates the class of errors where stale line numbers cause edits to land in the wrong place.
|
||||
|
||||
**6. Single-file small/medium edits (Serena: neutral to slight negative)**
|
||||
- For a 1-line change inside a 13-line method, Serena's `replace_symbol_body` requires sending the entire 13-line body. Edit sends just the changed line. The prerequisite cost differs: Serena needs `find_symbol(include_body=True)` to get the body; Edit needs `Read` of the relevant lines. Both are 1 prerequisite call + 1 edit call.
|
||||
- Frequency: Very high. Value per hit: Slightly negative for Serena — more payload for small changes.
|
||||
|
||||
**Verdict:** Serena's strongest contributions are in cross-file refactoring (high value, moderate frequency) and structured navigation (moderate value, high frequency); for small text edits, built-ins are slightly more efficient.
|
||||
|
||||
---
|
||||
|
||||
## 3. Detailed Evidence, Grouped by Capability
|
||||
|
||||
### 3.1 Structural Overview (Task 2)
|
||||
|
||||
| Metric | Serena `get_symbols_overview(depth=1)` | Built-in `Grep` for class/def |
|
||||
|---|---|---|
|
||||
| Calls | 1 | 1 |
|
||||
| Output structure | JSON tree: 14 classes with nested methods + attributes | Flat list: 54 `class`/`def` lines with line numbers |
|
||||
| Nesting visible? | Yes — methods grouped under classes | No — indentation implies nesting but no grouping |
|
||||
| Attributes visible? | Yes | No |
|
||||
| Output size | ~2.5KB structured JSON | ~3KB flat text |
|
||||
| Correctness | Always correct — uses IDE parser, language-agnostic | Heuristic — the regex `^(class \|def \| def )` is Python-specific and can miss decorated methods, multi-line signatures, or match inside strings/comments |
|
||||
| Language portability | Works unchanged for any language the IDE supports | Requires a new hand-tuned regex per language |
|
||||
| Next step | `find_symbol("ClassName/method", include_body=True)` — 1 call | `Read(file, offset=line, limit=N)` — 1 call |
|
||||
|
||||
Both paths need 1 call for overview + 1 call for drill-down. Serena's output is more structured and reliably correct; Grep's is simpler but fragile. The Grep pattern used here happened to work well for this Python codebase, but would need to be rewritten for Java (`class|interface|enum`, brace-delimited), Rust (`fn|struct|impl|trait`), TypeScript (`class|function|interface`), etc. — and even within Python, it misses cases like `@overload`-decorated methods or methods whose `def` line is preceded by a long decorator stack that pushes `def` to a non-standard indentation.
|
||||
|
||||
**Verdict:** Serena provides a reliably correct structural overview across languages; Grep-based overviews are heuristic approximations that work in simple cases but degrade for complex declarations or non-Python codebases.
|
||||
|
||||
### 3.2 Targeted Method Retrieval (Task 3)
|
||||
|
||||
| Metric | Serena | Built-in |
|
||||
|---|---|---|
|
||||
| Calls | 1 (`find_symbol` with `include_body=True`) | 2 (Grep to find line + Read with offset) |
|
||||
| Prerequisite | Know the name path | Know the method name |
|
||||
| Output | Method body only (no surrounding code) | Surrounding code included (must estimate limit) |
|
||||
|
||||
For `Collector/_collect` (330 lines): Serena returned exactly 330 lines. Built-in Read returned 332 lines (including the next method's signature).
|
||||
|
||||
**Verdict:** Serena saves 1 call and returns precisely the requested body; built-in is adequate but requires line-number discovery.
|
||||
|
||||
### 3.3 Cross-File References (Task 4)
|
||||
|
||||
| Metric | Serena `find_referencing_symbols` | Built-in `Grep` |
|
||||
|---|---|---|
|
||||
| Calls | 1 | 1 |
|
||||
| Files found | 63 (code files only, structured by symbol type) | 83 (includes docs, notebooks, changelogs, README) |
|
||||
| Output structure | Grouped by file, categorized (import, call, type annotation) | Flat file list |
|
||||
| Precision | Code-only references | All textual mentions |
|
||||
|
||||
Grep finds 83 files including `README.md`, `CHANGELOG.md`, and `.ipynb` notebooks. Serena finds 63 code files. For the question "who uses this in code?", Serena's result is directly usable. For "where is this mentioned anywhere?", Grep is the right tool.
|
||||
|
||||
**Verdict:** Serena provides higher-precision code-usage results; Grep provides broader text-level coverage. Different tools for different questions.
|
||||
|
||||
### 3.4 Type Hierarchy (Task 5)
|
||||
|
||||
| Metric | Serena `type_hierarchy` | Built-in |
|
||||
|---|---|---|
|
||||
| Calls | 1 | 2+ (Grep for `class X(BaseCollector` + Grep for `class Collector(` + potential transitive search) |
|
||||
| Result | `BaseCollector → ABC → object` (supers), `BaseCollector → Collector → AsyncCollector` (subs), with file locations | `class Collector(BaseCollector[TCollectStats], ...)` at line 551 — requires further reads for AsyncCollector's superclass |
|
||||
|
||||
**Verdict:** Serena produces the full transitive hierarchy in 1 call; built-in requires iterative searches.
|
||||
|
||||
### 3.5 External Dependency Lookup (Task 6)
|
||||
|
||||
| Metric | Serena | Built-in |
|
||||
|---|---|---|
|
||||
| Can retrieve? | Yes — `find_declaration` + `search_deps=True` | Requires environment discovery: `python -c "import X; print(inspect.getfile(X))"` then `Read` |
|
||||
| Infrastructure | IDE index (pre-built) | Working Python environment, correct venv activated |
|
||||
| Result | Symbol location + documentation | Full source file (if env is set up) |
|
||||
|
||||
In this session, the Python environment wasn't directly accessible from bash, so built-in lookup would have required additional setup. Serena retrieved `torch.distributions.Distribution`'s location and docstring via the IDE index.
|
||||
|
||||
**Verdict:** Serena provides dependency introspection without environment setup; built-in requires a working interpreter.
|
||||
|
||||
### 3.6 Small Edit — 1 Line Change (Task 7a)
|
||||
|
||||
| Metric | Serena `replace_symbol_body` | Built-in `Edit` |
|
||||
|---|---|---|
|
||||
| Prerequisite calls | 1 (`find_symbol` with `include_body=True`) — already done in Task 3 | 1 (`Read` of ~15 lines) |
|
||||
| Edit call | 1 (send full 13-line body) | 1 (send 1-line old + 1-line new) |
|
||||
| Payload sent (edit call) | ~550 chars (full body) | ~120 chars (changed line only) |
|
||||
| Total calls | 1–2 | 2 |
|
||||
|
||||
**Verdict:** For small changes, Edit sends ~4.5× less payload in the edit call. Total call count is the same.
|
||||
|
||||
### 3.7 Medium Rewrite — ~19 Lines (Task 7b)
|
||||
|
||||
| Metric | Serena | Built-in |
|
||||
|---|---|---|
|
||||
| Prerequisite | 1 `find_symbol` (already done) | 1 `Read` (~22 lines) |
|
||||
| Edit payload | ~550 chars (full body) | ~1000 chars (old 19 lines + new 20 lines) |
|
||||
| Total calls | 1–2 | 2 |
|
||||
|
||||
At this scale, Serena's payload is actually *smaller* because Edit must send both old and new text, while Serena sends only the new body. The crossover point is approximately where the changed region exceeds half the method body.
|
||||
|
||||
**Verdict:** At medium scale, payloads converge; Serena's is slightly smaller due to only sending the replacement.
|
||||
|
||||
### 3.8 Large Rewrite — 55 Lines (Task 7c)
|
||||
|
||||
| Metric | Serena | Built-in |
|
||||
|---|---|---|
|
||||
| Prerequisite | 1 `find_symbol` (already done) | 1 `Read` (~67 lines) |
|
||||
| Edit payload | ~2200 chars (new body) | ~4400 chars (old 63 lines + new 62 lines) |
|
||||
| Total calls | 1–2 | 2 |
|
||||
|
||||
**Verdict:** For full-method rewrites, Serena sends ~50% less payload because it only sends the replacement, not the original.
|
||||
|
||||
### 3.9 Cross-File Rename (Task 10)
|
||||
|
||||
| Metric | Serena `rename` | Built-in chain |
|
||||
|---|---|---|
|
||||
| Calls | 1 | 1 Grep + 4 Read + 4 Edit = 9 |
|
||||
| Files affected | 4 (automatically discovered) | 4 (manually discovered via Grep) |
|
||||
| Import handling | Automatic | Manual — must identify and rewrite each import statement |
|
||||
| Atomicity | Atomic — all-or-nothing | Sequential — intermediate states are inconsistent |
|
||||
|
||||
**Verdict:** Serena reduces a 9-call chain to 1 call for cross-file rename, with atomicity.
|
||||
|
||||
### 3.10 Move Symbol Across Modules (Task 11)
|
||||
|
||||
| Metric | Serena `move` | Built-in equivalent |
|
||||
|---|---|---|
|
||||
| Calls | 1 | ~8–12 (Read source, Edit source to remove, Edit target to add, Grep for imports, Read+Edit each import site) |
|
||||
| Import updates | Automatic | Manual — must rewrite `from X import Y` → `from Z import Y` in each file |
|
||||
| Dependency imports | Automatically adds needed imports to target file | Must manually inspect what the moved function imports and replicate |
|
||||
|
||||
Moving `get_stddev_from_dist` from `collector.py` to `stats.py`: Serena updated 3 files (source, target, test) in 1 call, including adding necessary imports to the target module.
|
||||
|
||||
**Verdict:** Move is Serena's highest-value single operation — it handles import graph updates that would be error-prone manually.
|
||||
|
||||
### 3.11 Move File (Task 12a)
|
||||
|
||||
| Metric | Serena `move` | Built-in equivalent |
|
||||
|---|---|---|
|
||||
| Calls | 1 | 1 `git mv` + 1 Grep + N×(Read+Edit) for import updates = ~12 |
|
||||
| Files updated | 5 import updates automatic | Must manually discover and rewrite |
|
||||
|
||||
**Verdict:** Same pattern as symbol move — Serena collapses an N-step process.
|
||||
|
||||
### 3.12 Safe Delete (Task 12b)
|
||||
|
||||
Serena's `safe_delete` in safe mode (default):
|
||||
- Reports all usages before deleting — acts as a guard.
|
||||
- For unused symbols, deletes cleanly in 1 call.
|
||||
- For used symbols, refuses and lists usages.
|
||||
|
||||
Built-in equivalent: Grep to check usages → if none found, Read + Edit to delete. 2–3 calls.
|
||||
|
||||
**Verdict:** Safe delete adds a safety check that the built-in path must implement manually.
|
||||
|
||||
### 3.13 Inline (Task 13)
|
||||
|
||||
Serena's inline tool did not work for any Python function tested. The JetBrains backend does not support Python function inlining (this is a language-level limitation of the IDE's refactoring engine, not a Serena bug).
|
||||
|
||||
**Verdict:** No candidate inlinable in this codebase; inline capability appears unavailable for Python.
|
||||
|
||||
### 3.14 Scope Precision (Task 14)
|
||||
|
||||
Three methods named `reset_env` exist in `collector.py` (in `BaseCollector`, `Collector`, `AsyncCollector`).
|
||||
|
||||
- Serena: `find_symbol("Collector/reset_env")` returns exactly that override's body.
|
||||
- Grep: Returns 3 line numbers. Determining which belongs to which class requires reading surrounding context.
|
||||
|
||||
**Verdict:** Serena's name-path addressing eliminates class-level disambiguation that Grep requires.
|
||||
|
||||
### 3.15 Chained Edits (Task 17)
|
||||
|
||||
Three consecutive edits to methods in `CollectStats`:
|
||||
- Serena: 3 `replace_symbol_body` calls, 0 intermediate reads. Name paths (`CollectStats/refresh_return_stats`, `CollectStats/refresh_len_stats`, `CollectStats/refresh_std_array_stats`) remained valid across all edits because they are structural identifiers, not positions.
|
||||
- Built-in: 1 Read + 3 Edit calls = 4 calls in the best case. The Read was required upfront (Edit enforces "must read before editing"). The 3 Edits succeeded without re-reads only because the `old_string` anchors happened to remain unique after each edit. But this is fragile: Edit also enforces a "file has been modified since read" check when external tools modify the file, forcing a re-Read. More fundamentally, if I had needed to *find* these methods first (the typical case when you don't already know the line numbers), each Grep result from before the first edit would have been stale after it — line 232 is no longer line 232 after inserting 2 lines above it.
|
||||
|
||||
The core asymmetry: Serena's addressing is *structural* (survives edits by definition), while built-in addressing is *positional* (line numbers from Grep/Read go stale after any insertion or deletion). Edit's text matching partially mitigates this, but only for the final step — the discovery steps (Grep, Read with offset) remain position-dependent.
|
||||
|
||||
**Verdict:** Serena's name-path stability eliminates the re-read/re-grep cycle between edits; built-in tools require re-acquiring positions after each edit that shifts line numbers.
|
||||
|
||||
---
|
||||
|
||||
## 4. Token-Efficiency Analysis
|
||||
|
||||
### Payload by edit size
|
||||
|
||||
| Edit scale | Serena payload (edit call) | Edit payload (edit call) | Winner |
|
||||
|---|---|---|---|
|
||||
| 1-line change in 13-line method | ~550 chars (full body) | ~120 chars | Edit (~4.5×) |
|
||||
| 19-line medium rewrite | ~550 chars | ~1000 chars | Serena (~1.8×) |
|
||||
| 55-line full rewrite | ~2200 chars | ~4400 chars | Serena (~2×) |
|
||||
| Cross-file rename (4 files) | ~100 chars | ~800 chars (4 Edit calls) | Serena (~8×) |
|
||||
|
||||
### Prerequisite reads
|
||||
|
||||
- Serena: `find_symbol(include_body=True)` returns the symbol body. If you've already navigated to it during exploration, no additional call needed.
|
||||
- Built-in: `Read` with offset/limit. Always required before Edit (enforced by the tool).
|
||||
|
||||
### Stable vs ephemeral addressing
|
||||
|
||||
- Serena's name paths (`CollectStats/refresh_return_stats`) are stable identifiers — they survive any edit to surrounding code. No re-read or re-discovery needed between edits.
|
||||
- The built-in workflow uses ephemeral, position-based addresses at every stage: Grep returns line numbers, Read takes line offsets, and both are invalidated by any insertion or deletion above the target. Edit's `old_string` matching is content-based and more resilient, but it depends on the upstream position-based steps to know *what* to match. After an edit shifts line numbers, the entire Grep→Read→Edit chain must be re-executed from the top.
|
||||
- In a session with N edits to the same file, this costs up to N-1 additional Grep/Read round-trips with built-ins. With Serena, the cost is zero — the same name path works on the first and tenth edit.
|
||||
|
||||
**Verdict:** Serena is more token-efficient for medium-to-large edits and cross-file operations; Edit is more efficient for small, localized changes. Across multi-edit sessions, Serena's stable addressing avoids the re-read tax that compounds with each successive built-in edit.
|
||||
|
||||
---
|
||||
|
||||
## 5. Reliability & Correctness (Under Correct Use)
|
||||
|
||||
### Precision of matching
|
||||
- Serena: Exact symbol resolution via name paths. `Collector/reset_env` unambiguously selects one method.
|
||||
- Edit: Text matching. Unique strings match correctly; non-unique strings fail (and Edit reports the error).
|
||||
|
||||
### Scope disambiguation
|
||||
- Serena distinguishes overrides, overloads (via indices), and nested classes by name path.
|
||||
- Grep/Edit cannot distinguish methods with the same name in different classes without reading surrounding context.
|
||||
|
||||
### Atomicity
|
||||
- Serena's cross-file operations (rename, move) are atomic — all files updated or none.
|
||||
- Built-in multi-file edits are sequential — a failure mid-chain leaves an inconsistent state (recoverable via `git checkout`).
|
||||
|
||||
### Semantic queries vs text search
|
||||
- `find_referencing_symbols` returns code-level references categorized by type. Grep returns all textual mentions.
|
||||
- `type_hierarchy` returns transitive sub/supertypes. No built-in equivalent without iterative search.
|
||||
|
||||
### External dependency lookup
|
||||
- Serena: Available via IDE index, no environment setup needed. Can retrieve symbol docs and location.
|
||||
- Built-in: Requires working Python environment, correct venv, and manual file discovery. More powerful when available (full source), but higher setup cost.
|
||||
|
||||
**Verdict:** Serena provides stronger correctness guarantees for symbol-level operations (scope, atomicity, semantic precision); built-in tools are reliable for text-level operations with the caveat that scope disambiguation requires manual effort.
|
||||
|
||||
---
|
||||
|
||||
## 6. Workflow Effects Across a Session
|
||||
|
||||
### Compound advantages
|
||||
- **Exploration → Edit without position re-acquisition**: Serena's overview tools produce name paths that are directly usable as edit targets. The built-in path produces line numbers (from Grep) that are consumed by Read — but after an edit, those line numbers are stale. In a typical explore-edit-explore-edit cycle, Serena's name paths remain valid throughout while built-in line numbers must be re-acquired after each edit. Over 3 explore+edit cycles, this saves ~3–6 intermediate Grep/Read calls.
|
||||
- **Chained edits without re-reads**: Name-path stability means no re-reads between edits to the same file. For N edits, this saves up to N-1 Read calls. Edit's text matching partially avoids this (if old_strings stay unique), but the upstream discovery steps (Grep line numbers, Read offsets) still go stale.
|
||||
- **Cross-file refactoring**: When a rename or move is part of a larger change, doing it atomically avoids the need to manually track "which files still need updating."
|
||||
|
||||
### Diminishing returns
|
||||
- For purely exploratory sessions (reading code, no edits), Serena's advantage is modest — `Grep` and `Read` are nearly as fast for navigation, and Serena's structured output doesn't save many calls.
|
||||
- For sessions dominated by small text edits (config changes, log message tweaks), Serena adds no value.
|
||||
|
||||
### Neutral findings
|
||||
- Both toolsets require similar total calls for single-file work. The difference is ~1 call per operation.
|
||||
- Output quality for code review (reading diffs, understanding changes) is identical — both require `git diff`.
|
||||
|
||||
**Verdict:** Serena's advantages compound across multi-step refactoring sessions where each operation feeds into the next; for read-heavy or small-edit sessions, the advantage is marginal.
|
||||
|
||||
---
|
||||
|
||||
## 7. Unique Capabilities (No Practical Built-In Equivalent)
|
||||
|
||||
1. **Atomic cross-file rename** — 1 call, all imports and usages updated, all-or-nothing. No built-in equivalent without scripting a multi-step chain. Frequency: moderate (refactoring sessions). Impact: high (saves 5–10 calls, eliminates partial-update risk).
|
||||
|
||||
2. **Atomic cross-file move** (symbol or file) with import rewriting — includes adding necessary imports to the target module. Frequency: low-to-moderate. Impact: very high per occurrence (saves 8–12 calls, handles import dependency graph).
|
||||
|
||||
3. **Type hierarchy traversal** — transitive supertypes and subtypes in 1 call. Built-in requires iterative Grep with manual transitive closure. Frequency: low. Impact: moderate (saves 3–5 calls).
|
||||
|
||||
4. **Safe delete with usage check** — reports all usages before deleting, with option to propagate. Built-in requires Grep + manual verification. Frequency: low. Impact: moderate (safety check is the value).
|
||||
|
||||
5. **External dependency symbol lookup** via IDE index — no Python environment needed. Frequency: moderate. Impact: moderate (avoids environment setup friction).
|
||||
|
||||
**Verdict:** Serena provides 3–5 capabilities with no practical built-in equivalent, concentrated in cross-file refactoring and semantic navigation.
|
||||
|
||||
---
|
||||
|
||||
## 8. Tasks Outside Serena's Scope (Built-In Only)
|
||||
|
||||
- **Non-code file operations**: Reading/editing config files, docs, changelogs, notebooks → `Read`/`Edit`/`Write`
|
||||
- **Free-text search**: Finding log strings, URLs, magic constants → `Grep`
|
||||
- **Shell operations**: Running tests, builds, git commands, package management → `Bash`
|
||||
- **File creation**: New files from scratch → `Write`
|
||||
- **Glob-based file discovery**: Finding files by pattern → `Glob`
|
||||
- **Broad codebase search**: When you don't know what you're looking for → `Grep` with regex
|
||||
|
||||
Estimated share of daily work: These tasks constitute roughly 40–60% of a typical coding session (reading docs, running tests, searching for patterns, editing config). Serena's augmentation covers the remaining 40–60% where code-level semantic operations apply.
|
||||
|
||||
**Verdict:** Built-in tools handle roughly half of daily work that falls entirely outside Serena's scope; Serena augments the code-centric other half.
|
||||
|
||||
---
|
||||
|
||||
## 9. Practical Usage Rule
|
||||
|
||||
| Task type | Use |
|
||||
|---|---|
|
||||
| Cross-file rename, move, delete | Serena (unique capability) |
|
||||
| Understanding class hierarchy or symbol relationships | Serena (1 call vs. iterative search) |
|
||||
| Getting a structural overview of a large file | Serena (richer structure) or Grep (simpler, faster) |
|
||||
| Reading a specific method body by name | Serena (direct) or Grep+Read (2 calls) |
|
||||
| Small edit (1–5 lines inside a method) | Edit (less payload) |
|
||||
| Full method rewrite | Serena `replace_symbol_body` (less payload, no re-read) |
|
||||
| Single-file rename of a unique identifier | Edit with `replace_all` (equivalent) |
|
||||
| Non-code files, config, docs | Built-in `Read`/`Edit` |
|
||||
| Text search, pattern matching | Built-in `Grep` |
|
||||
| Anything involving shell, git, tests | Built-in `Bash` |
|
||||
| External dependency inspection | Serena (no env setup needed) |
|
||||
|
||||
**Verdict:** Use Serena for cross-file refactoring and semantic navigation; use built-ins for text-level edits, non-code files, and shell operations; for single-file code edits, choose based on edit size (Edit for small, Serena for full-body rewrites).
|
||||
@@ -0,0 +1,665 @@
|
||||
:::{admonition} Evaluation Result
|
||||
:class: note
|
||||
**Generated by:** GPT-5.4 (high) in Codex
|
||||
**Codebase:** Serena JetBrains Plugin (Java)
|
||||
:::
|
||||
|
||||
# Codex (GPT-5.4)
|
||||
|
||||
|
||||
> **One-line summary:** As a coding agent, I would ask my owner to add Serena because it turns fragile text-and-line-number work into precise symbol-aware navigation and
|
||||
refactoring, which makes real code changes feel faster, safer, and far less blind.
|
||||
|
||||
This report compares Serena's JetBrains-backed semantic coding tools with built-in file, shell, search, and patch tools in this repository. The comparison assumes competent use of both toolsets: built-ins are used for text, file, shell, config, and small patch work; Serena is used where symbol identity, language semantics, or IDE refactoring semantics apply.
|
||||
|
||||
Method: I explored code first, avoided repo documentation and prior notes, ran real edits/refactors, and reverted after each experiment. After each edit/refactor experiment I checked `git status --short` and returned the tree to clean before moving on. Measurements are approximate, but call counts, diff sizes, and result shapes are from observed runs.
|
||||
|
||||
## 1. Headline: what Serena changes
|
||||
|
||||
Serena adds a semantic layer over the codebase. Its concrete delta is the ability to address and transform code by symbols: name paths, overload indexes, reference graphs, type hierarchies, external declarations, and JetBrains refactoring operations.
|
||||
|
||||
Tasks where Serena adds capability:
|
||||
|
||||
- Code-reference search: `find_referencing_symbols` for `Symbol/findReferences` returned 6 precise code usages grouped by containing symbols. `rg findReferences` also returned the declaration, the `/findReferences` route string, and comments.
|
||||
- Type hierarchy: one `type_hierarchy` call for `PostRequestHandler` returned 18 direct endpoint subclasses, a transitive `TypeHierarchyHandler -> GetSupertypesHandler/GetSubtypesHandler` branch, and the external `Object` supertype.
|
||||
- External dependency lookup: `find_declaration` resolved `ReferencesSearch.search(anchorElement)` to `<ext:ReferencesSearch.class|466808a0>`, and `find_symbol` returned the selected overload body. Built-in repo/cache grep found the import and call but not the dependency definition.
|
||||
- Cross-file refactors: semantic rename, symbol move, file move, safe delete, and inline executed real IDE refactors and updated files/usages/imports.
|
||||
- Stable addressing: a chained edit used `SymbolFinder/findFilesByName`, `SymbolFinder/getProject`, and `SymbolFinder/qualNameMatchesName` after earlier edits shifted line numbers.
|
||||
|
||||
Tasks where Serena applies but offered little or no improvement:
|
||||
|
||||
- Tiny intra-method edits: a 1-line error-message change was smaller with a built-in patch; Serena body replacement required sending the whole method.
|
||||
- Simple one-file private rename: manual patch and semantic rename produced the same 2-line diff for `qualNameMatchesName -> qualifiedNameMatchesName`.
|
||||
- Method insertion at a known spot: both workflows produced the same 4-line diff; Serena's benefit was target stability, not smaller payload.
|
||||
- Whole-method rewrite: Serena targets the method boundary cleanly, but the full replacement body still has to be sent.
|
||||
|
||||
Tasks outside Serena's scope:
|
||||
|
||||
- Reading config/non-code files such as `plugin.xml` and `build.gradle.kts`.
|
||||
- Free-text searches for URLs, endpoint strings, settings values, comments, and resources.
|
||||
- File inventory, line counts, shell commands, build/test execution, Git operations, and arbitrary text edits.
|
||||
|
||||
Value-weighted summary:
|
||||
|
||||
| Rank | Difference | Frequency | Value per hit | Delta |
|
||||
|---|---:|---:|---:|---|
|
||||
| 1 | Cross-file semantic refactors | Medium-high | High | Often avoids 5-20 manual edit/search/verify steps and reduces partial-update risk. |
|
||||
| 2 | Code usages vs text mentions | High | Medium-high | Removes noisy grep triage for "who uses this symbol?" |
|
||||
| 3 | Symbol overview/body retrieval | High | Medium | Avoids large reads and stale line targeting. |
|
||||
| 4 | Type hierarchy/implementations | Medium | High | Hard to reproduce correctly with text search, especially transitively. |
|
||||
| 5 | Stable addressing across edit chains | Medium | Medium | Reduces refresh work after line shifts. |
|
||||
| 6 | External dependency lookup | Low-medium | High | Needs IDE index; built-ins need source/decompiler infrastructure. |
|
||||
| 7 | Small local edits | High | Neutral/negative for Serena | Built-in patch/edit usually sends less. |
|
||||
|
||||
**Verdict:** Serena materially changes symbol-centric exploration and refactoring; it does not replace built-ins for ordinary text, file, shell, config, or tiny local edits.
|
||||
|
||||
## 2. Added value and differences by area
|
||||
|
||||
- Cross-file semantic refactoring changes both workflow and correctness. Frequency: medium-high. Value per hit: high. The observed class rename updated a file/class plus imports/usages; the nested-record move changed 4 existing files and created 1 new file; the file move updated package/imports across 3 paths. Built-ins can reproduce the result, but only through search, file moves, patches, import cleanup, and verification.
|
||||
|
||||
- Semantic search separates code usage from text mention. Frequency: high. Value per hit: medium-high. Serena returned only code references for `Symbol/findReferences`; `rg` returned code, route strings, comments, and the declaration. Built-ins remain better for "mentioned anywhere."
|
||||
|
||||
- Symbol overview/body retrieval cuts exploration payload. Frequency: high. Value per hit: medium. `get_symbols_overview` on `Symbol.java` returned fields, methods, nested classes, and overload indexes without reading the 1,000+ line file. Regex produced line-oriented candidates and still required manual scope interpretation.
|
||||
|
||||
- Type/dependency queries add capabilities not practically present in built-ins. Frequency: low-medium. Value per hit: high. Serena returned a transitive type graph and an external IntelliJ API method body; text tools needed iterative searches or extra source/decompiler setup.
|
||||
|
||||
- Small localized edits are not improved by symbol-body replacement. Frequency: high. Value per hit: neutral or negative for Serena. A one-line patch was smaller than replacing an 11-line method body.
|
||||
|
||||
- Some JetBrains refactors staged added/deleted files. Frequency: limited to class/file move/delete style operations. Value per hit: neutral operational tradeoff. Semantic value remains, but verification/revert must check the index as well as unstaged files.
|
||||
|
||||
**Verdict:** Serena's highest-value differences are symbol identity, reference graphs, and IDE refactor execution; built-ins remain superior for simple text-local work.
|
||||
|
||||
## 3. Detailed evidence, grouped by capability
|
||||
|
||||
### 3.1 Repository structure and entry points
|
||||
|
||||
Attempted: identify top-level layout, packages, and entry points.
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. `git status --short` -> clean.
|
||||
2. `rg --files -g '!*.md' -g '!docs/**' -g '!CLAUDE.md'` -> code/config/resource inventory.
|
||||
3. `Get-ChildItem -Force` -> top-level directories.
|
||||
4. `Get-Content src/main/resources/META-INF/plugin.xml` -> plugin entry points.
|
||||
5. `Get-Content build.gradle.kts -TotalCount 80` -> Gradle/IntelliJ platform setup.
|
||||
|
||||
Serena call chain: not applicable for repository inventory and non-code config.
|
||||
|
||||
Observed structure:
|
||||
|
||||
- `service`: backend service and request handling.
|
||||
- `service/endpoint`: endpoint handlers for symbol search, references, formatting, rename, move, safe delete, inline, inspections, and completions.
|
||||
- `symbol`: symbol model, symbol lookup, hierarchy, path matching, and move processors.
|
||||
- `util`: IDE/project/editor/UI helpers.
|
||||
- `ui`: tool window content.
|
||||
- `plugin.xml`: registers `PluginStartupActivity`, settings service/configurable, and a dummy test action.
|
||||
|
||||
Payloads: built-ins used 5 small shell/read calls and returned several KB of code/config context; Serena had no relevant semantic operation.
|
||||
|
||||
**Verdict:** Repository layout and non-code entry-point discovery are built-in work; Serena starts adding value once the target is code symbols.
|
||||
|
||||
### 3.2 Large file structural overview
|
||||
|
||||
Attempted: compare structural overview on `src/main/java/de/oraios/serena/symbol/Symbol.java`.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `get_symbols_overview(relative_path=Symbol.java, depth=1)`
|
||||
2. Next step: `find_symbol(Symbol/findReferences, include_body=true)`
|
||||
|
||||
Serena output: one top-level `Symbol` class; fields; nested `ChildrenCollector` and `DocumentationResolver`; methods including overload-indexed names such as `getLocationString[0]`, `getLocationString[1]`, `move[0]`, `move[1]`, `getDocumentation[0]`, and `getDocumentation[1]`.
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. `rg` for method-like declaration lines in `Symbol.java`.
|
||||
2. `rg` for class/interface/enum lines in `Symbol.java`.
|
||||
3. Next step: line-slice read around the selected method.
|
||||
|
||||
Built-in output: about 70 line-oriented method/class matches, including nested symbols, with no durable symbol identity beyond manual signature inspection.
|
||||
|
||||
Payloads: Serena used 1 compact overview call plus a targeted follow-up. Built-ins used 2 regex searches plus a later line-range read.
|
||||
|
||||
**Verdict:** Serena's overview is more actionable because its output feeds directly into stable symbol-addressed calls; regex outlines are useful but line-based.
|
||||
|
||||
### 3.3 Targeted method body retrieval
|
||||
|
||||
Attempted: retrieve `Symbol/findReferences` without reading surrounding file content.
|
||||
|
||||
Serena call chain: `find_symbol(relative_path=Symbol.java, name_path_pattern=Symbol/findReferences, include_body=true)`.
|
||||
|
||||
Serena output: only the `public ArrayList<SymbolReference> findReferences()` body.
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. `rg "findReferences\\(" src/main/java -n -C 2`
|
||||
2. `Get-Content Symbol.java` line slice around the declaration.
|
||||
|
||||
Built-in output: search context across multiple files, then the selected method slice.
|
||||
|
||||
Payloads: Serena input was one path/name-path request and returned roughly 25 method lines. Built-ins required search output plus a separate slice read.
|
||||
|
||||
**Verdict:** If the symbol is known, Serena retrieves the body in one precise call; built-ins need search plus line-targeted reading.
|
||||
|
||||
### 3.4 References: code usages vs mentions anywhere
|
||||
|
||||
Attempted: find all references to `Symbol/findReferences`.
|
||||
|
||||
Serena call chain: `find_referencing_symbols(relative_path=Symbol.java, name_path=Symbol/findReferences)`.
|
||||
|
||||
Serena output:
|
||||
|
||||
- `Symbol/formatReferenceLocations/references`
|
||||
- `Symbol/inline/refCountBefore`
|
||||
- `Symbol/verifyInlineResult/refCountAfter`
|
||||
- `SymbolDTO/Builder/buildDTO/references`
|
||||
- `RunInspectionsOnSymbolsHandler/handleRequest/refs`
|
||||
- `FindReferencesHandler/buildResponse/references`
|
||||
|
||||
Built-in call chain: `rg "findReferences" src/main/java -n -C 1`.
|
||||
|
||||
Built-in output: same call sites plus the declaration, `/findReferences` route registration, and explanatory comments.
|
||||
|
||||
Payloads: Serena returned a compact grouped usage list of about 500-700 characters. `rg` returned broader line context of about 1-2 KB and mixed code usages with text mentions.
|
||||
|
||||
**Verdict:** Serena has higher precision for "who uses this symbol in code"; built-ins have higher recall for "where is this text mentioned anywhere."
|
||||
|
||||
### 3.5 Type hierarchy
|
||||
|
||||
Attempted: list supertypes and subtypes transitively for `PostRequestHandler`.
|
||||
|
||||
Serena call chain: `type_hierarchy(relative_path=PostRequestHandler.java, name_path=PostRequestHandler, hierarchy_type=both, depth=0)`.
|
||||
|
||||
Serena output: external `Object` supertype; 18 direct endpoint subclasses; transitive nested branch `TypeHierarchyHandler` containing `GetSupertypesHandler` and `GetSubtypesHandler`.
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. `rg "extends PostRequestHandler|extends TypeHierarchyHandler|class PostRequestHandler" src/main/java -n`
|
||||
2. Manually follow any discovered intermediate types.
|
||||
3. Repeat searches if deeper hierarchy exists.
|
||||
|
||||
Payloads: Serena used 1 hierarchy query and returned structured JSON. Built-ins used pattern search and manual transitive grouping.
|
||||
|
||||
**Verdict:** Serena turns hierarchy discovery into a semantic graph query; text search requires iterative pattern expansion and manual reasoning.
|
||||
|
||||
### 3.6 External dependency symbol lookup
|
||||
|
||||
Attempted: retrieve the IntelliJ dependency symbol behind `ReferencesSearch.search(anchorElement)`.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `find_declaration(relative_path=Symbol.java, regex="ReferencesSearch\\.(search)\\(anchorElement\\)")`
|
||||
2. `find_symbol(relative_path=<ext:ReferencesSearch.class|466808a0>, name_path_pattern=ReferencesSearch/search[0], include_body=true, search_deps=true)`
|
||||
|
||||
Serena output: declaration `ReferencesSearch/search[0]` in an external class path and the overload body:
|
||||
|
||||
```java
|
||||
public static @NotNull Query<PsiReference> search(@NotNull PsiElement element) {
|
||||
return search(element, GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(element)), false);
|
||||
}
|
||||
```
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. `rg "ReferencesSearch" src/main/java -n` -> import and local call.
|
||||
2. `rg` over repo, `.intellijPlatform`, and Gradle caches for `class ReferencesSearch` or matching method signatures -> no useful source hit.
|
||||
3. `Get-ChildItem` over Gradle/IntelliJ caches -> jar candidates but no direct definition.
|
||||
|
||||
Infrastructure difference: Serena depends on the JetBrains IDE index; built-ins need source jars, decompiler tooling, or classpath-specific jar inspection.
|
||||
|
||||
**Verdict:** External dependency lookup is a genuine Serena capability when IDE indexes are available; ordinary built-ins do not provide it.
|
||||
|
||||
### 3.7 Single-file edits across edit sizes
|
||||
|
||||
Small tweak attempted: change `"No symbol found for "` to `"No matching symbol found for "` in `SymbolFinder/findSymbolByNamePath`.
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. Use existing search/body context.
|
||||
2. `apply_patch` one-line replacement.
|
||||
3. `git diff`, `git status --short`.
|
||||
4. Revert and clean check.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `replace_symbol_body(SymbolFinder/findSymbolByNamePath, full method body with changed string)`.
|
||||
2. `git diff`, `git status --short`.
|
||||
3. Revert and clean check.
|
||||
|
||||
Observed diff: both produced the same 1-line change. Payload difference: built-in edit input was a tiny hunk; Serena input was the full 11-line method body.
|
||||
|
||||
Medium rewrite attempted: rewrite `SymbolFinder/findFilesByName` from list accumulation to stream collection.
|
||||
|
||||
Built-in call chain: `apply_patch` over the method body, then diff/status/revert/status.
|
||||
|
||||
Serena call chain: `replace_symbol_body(SymbolFinder/findFilesByName, new method body)`, then diff/status/revert/status.
|
||||
|
||||
Observed diff: both produced `10 +++-------`, 3 insertions and 7 deletions. Payload difference was small: a patch hunk versus an 8-line replacement method.
|
||||
|
||||
Large/whole-body rewrite attempted: rewrite `InspectionRunner/collectResults` while preserving signature and behavior shape.
|
||||
|
||||
Built-in call chain: `apply_patch` against the method body, then diff/status/revert/status.
|
||||
|
||||
Serena call chain: `replace_symbol_body(InspectionRunner/collectResults, full symbol text including Javadoc and replacement body)`, then diff/status/revert/status.
|
||||
|
||||
Observed diff: both produced `38 +++++++++++-----------`, 19 insertions and 19 deletions. Payload difference: built-in required a large contextual hunk; Serena required the full symbol text, about 70 lines including Javadoc/signature/body.
|
||||
|
||||
**Verdict:** Serena is not automatically more token-efficient for edits; its edit advantage is stable symbol targeting, while built-ins are smaller for tiny local hunks.
|
||||
|
||||
### 3.8 Insert method at structural location
|
||||
|
||||
Attempted: insert `private Logger getLogger()` immediately after `SymbolFinder/getProject`.
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. Search/read surrounding area.
|
||||
2. `apply_patch` with nearby context.
|
||||
3. Diff/status/revert/status.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `insert_after_symbol(relative_path=SymbolFinder.java, name_path=SymbolFinder/getProject, body=...)`
|
||||
2. Diff/status/revert/status.
|
||||
|
||||
Observed diff: both produced the same 4-line insertion.
|
||||
|
||||
Payloads: built-ins sent inserted body plus surrounding text context; Serena sent inserted body plus symbol target.
|
||||
|
||||
**Verdict:** Structural insertion is a modest Serena improvement: same resulting diff, less dependence on line/context stability.
|
||||
|
||||
### 3.9 Rename: private helper in one file
|
||||
|
||||
Attempted: rename `SymbolFinder/qualNameMatchesName` to `qualifiedNameMatchesName`.
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. `rg "qualNameMatchesName" SymbolFinder.java -n -C 2`
|
||||
2. `apply_patch` declaration and one call site.
|
||||
3. Diff/status/revert/status.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `find_referencing_symbols(SymbolFinder/qualNameMatchesName)` -> one referencing method.
|
||||
2. `rename(name_path=SymbolFinder/qualNameMatchesName, new_name=qualifiedNameMatchesName, rename_in_comments=true, rename_in_text_occurrences=true)`.
|
||||
3. Diff/status/revert/status.
|
||||
|
||||
Observed result: Serena returned `"Success"`. Both produced the same 2-line diff.
|
||||
|
||||
**Verdict:** Semantic rename has little advantage for a one-file helper with one call site, but it scales better than text edits as references spread or names become ambiguous.
|
||||
|
||||
### 3.10 Rename: cross-file class including imports
|
||||
|
||||
Attempted: rename `MoveOperationFailedException` to `MoveFailedException`.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `rename(relative_path=MoveOperationFailedException.java, name_path=MoveOperationFailedException, new_name=MoveFailedException, rename_in_comments=true, rename_in_text_occurrences=true)`.
|
||||
2. `git diff --stat`, `git diff`, `git diff --cached --stat`, `git status --short`.
|
||||
3. Restore staged rename and modified files; clean check.
|
||||
|
||||
Serena result: `"Success"`.
|
||||
|
||||
Observed edits:
|
||||
|
||||
- Added/staged `MoveFailedException.java`.
|
||||
- Deleted/staged `MoveOperationFailedException.java`.
|
||||
- Updated import, Javadoc comment, and thrown class in `MoveProcessor.java`.
|
||||
|
||||
Built-in equivalent chain:
|
||||
|
||||
1. `rg "MoveOperationFailedException" src/main/java -n`.
|
||||
2. Rename/create/delete file.
|
||||
3. Patch class name and constructor.
|
||||
4. Patch imports and usages.
|
||||
5. Patch comments/text occurrences if desired.
|
||||
6. Verify no unintended old references remain.
|
||||
7. Compile/test for a permanent change.
|
||||
|
||||
**Verdict:** Cross-file class renames are high-value Serena cases because file/class coupling, imports, usages, and optional comments are handled as one semantic refactor.
|
||||
|
||||
### 3.11 Move symbol to another file context
|
||||
|
||||
Attempted: move nested record `InspectionRunner/PendingFix` to a top-level file in the same package.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `move(relative_path=InspectionRunner.java, name_path=InspectionRunner/PendingFix, target_relative_path=src/main/java/de/oraios/serena/service/endpoint)`.
|
||||
2. Diff/status/cached-diff inspection.
|
||||
3. Restore staged new file and modified files; clean check.
|
||||
|
||||
Serena result:
|
||||
|
||||
```json
|
||||
{
|
||||
"source_relative_path": "src/main/java/de/oraios/serena/service/endpoint/InspectionRunner.java",
|
||||
"target_relative_path": "src/main/java/de/oraios/serena/service/endpoint",
|
||||
"moved_symbol": {"name_path": "PendingFix", "type": "CLASS"}
|
||||
}
|
||||
```
|
||||
|
||||
Observed edits:
|
||||
|
||||
- Created/staged `PendingFix.java` with package and imports.
|
||||
- Removed nested record from `InspectionRunner.java`.
|
||||
- Updated 3 external references from `InspectionRunner.PendingFix` to `PendingFix`.
|
||||
- Removed unused imports in 2 files.
|
||||
|
||||
Built-in equivalent chain: read nested record/import needs, add file, delete nested symbol, search usages, patch qualified usages, patch internal references if needed, remove imports, verify, compile/test.
|
||||
|
||||
**Verdict:** Symbol move is a substantial Serena addition because the difficult part is reference/import repair, not copying text.
|
||||
|
||||
### 3.12 Move file/package location
|
||||
|
||||
Attempted: move `PluginUtil.java` from `util` to `service`.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `move(relative_path=src/main/java/de/oraios/serena/util/PluginUtil.java, target_relative_path=src/main/java/de/oraios/serena/service)`.
|
||||
2. Diff/status/cached-diff inspection.
|
||||
3. Restore staged rename and modified imports; clean check.
|
||||
|
||||
Serena result:
|
||||
|
||||
```json
|
||||
{
|
||||
"source_relative_path": "src/main/java/de/oraios/serena/util/PluginUtil.java",
|
||||
"target_relative_path": "src/main/java/de/oraios/serena/service"
|
||||
}
|
||||
```
|
||||
|
||||
Observed edits:
|
||||
|
||||
- Staged rename `util/PluginUtil.java -> service/PluginUtil.java`.
|
||||
- Changed package declaration to `de.oraios.serena.service`.
|
||||
- Updated import in `PluginStartupActivity`.
|
||||
- Removed now-unneeded same-package import in `SerenaBackendService`.
|
||||
|
||||
Built-in equivalent chain: move file, patch package declaration, search `PluginUtil`, patch imports/usages, remove redundant imports, verify no old package import remains, compile/test.
|
||||
|
||||
**Verdict:** File moves are high-value when packages/imports must change; built-ins can do them manually but require dependency repair steps.
|
||||
|
||||
### 3.13 Safe delete and propagated delete
|
||||
|
||||
Attempted: delete unused `DebugUtil`.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `safe_delete(relative_path=DebugUtil.java, name_path=DebugUtil, delete_even_if_used=false, propagate=false)`.
|
||||
2. `git diff --cached --stat`, `git status --short`.
|
||||
3. Restore staged deletion; clean check.
|
||||
|
||||
Serena result:
|
||||
|
||||
```json
|
||||
{
|
||||
"deleted_symbol": "DebugUtil",
|
||||
"relative_path": "src/main/java/de/oraios/serena/util/DebugUtil.java",
|
||||
"affected_references": [],
|
||||
"message": "Symbol deleted successfully with no affected references."
|
||||
}
|
||||
```
|
||||
|
||||
Built-in equivalent chain: `rg "DebugUtil"`, inspect declaration vs usages, delete file/symbol, verify no remaining usages.
|
||||
|
||||
Propagated deletion: no suitable correct-use candidate was found where JetBrains safe-delete propagation would meaningfully delete a used symbol and propagate deletion through call sites. For ordinary used-method deletion, correct safe delete reports usages or, if forced, deletes the symbol and reports affected references; that is not the same as arbitrary call-site deletion.
|
||||
|
||||
**Verdict:** Safe delete adds an integrated usage check plus deletion operation; propagated deletion was not evaluated because this codebase did not provide a suitable candidate.
|
||||
|
||||
### 3.14 Inline
|
||||
|
||||
Attempted: inline `ProjectUtil/getAbsolutePath`, a single-expression helper.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `find_symbol(ProjectUtil/getAbsolutePath, include_body=true)`.
|
||||
2. `find_referencing_symbols(ProjectUtil/getAbsolutePath)` -> 2 references.
|
||||
3. `inline_symbol(relative_path=ProjectUtil.java, name_path=ProjectUtil/getAbsolutePath, keep_definition=false)`.
|
||||
4. Diff/status/revert/status.
|
||||
|
||||
Serena result: `{"status": "SUCCESS"}`.
|
||||
|
||||
Observed edits:
|
||||
|
||||
- Removed `getAbsolutePath`.
|
||||
- Replaced internal call in `ProjectUtil/getVirtualFile`.
|
||||
- Replaced external call in `RefreshFileHandler`.
|
||||
|
||||
Built-in equivalent chain: read helper body, `rg getAbsolutePath`, patch each call site with substituted expression, delete helper, verify no stale references, compile/test.
|
||||
|
||||
**Verdict:** Inline is a strong Serena refactor for legally substitutable helpers; built-ins can reproduce it but must manually adapt each substitution.
|
||||
|
||||
### 3.15 Scope precision and overload targeting
|
||||
|
||||
Attempted: distinguish overloaded `Symbol/getLocationString` methods.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `find_symbol(Symbol/getLocationString[0], include_body=true)`.
|
||||
2. `find_symbol(Symbol/getLocationString[1], include_body=true)`.
|
||||
|
||||
Serena output:
|
||||
|
||||
- `[0]`: `public String getLocationString() { return getLocationString(element); }`
|
||||
- `[1]`: `private static String getLocationString(PsiElement element) { ... }`
|
||||
|
||||
Built-in call chain: `rg "getLocationString" Symbol.java -n -C 1`, then manual signature inspection.
|
||||
|
||||
**Verdict:** Serena's overload-indexed name paths provide precise symbol addressing that text search does not.
|
||||
|
||||
### 3.16 Atomicity and success signals
|
||||
|
||||
Observed Serena success signals:
|
||||
|
||||
- `replace_symbol_body` -> `OK`
|
||||
- `insert_after_symbol` -> `OK`
|
||||
- `rename` -> `"Success"`
|
||||
- `move` -> JSON with source/target/moved symbol or paths
|
||||
- `safe_delete` -> JSON with deleted symbol, affected references, and message
|
||||
- `inline_symbol` -> `{"status": "SUCCESS"}`
|
||||
|
||||
Built-in success signals:
|
||||
|
||||
- `apply_patch` -> "Success. Updated the following files"
|
||||
- Shell/Git commands -> exit codes and textual output
|
||||
- Cross-file consistency -> user-driven diff/search/build verification
|
||||
|
||||
Atomicity comparison: Serena refactors executed as single IDE operations. Built-in equivalents are chains of searches, file operations, and patches; a competent user can make them correct, but intermediate states can be partial.
|
||||
|
||||
Tradeoff: class/file move/delete refactors staged added/deleted files in the Git index, so clean verification must check both staged and unstaged state.
|
||||
|
||||
**Verdict:** Serena gives clearer semantic success signals and more atomic cross-file edits; built-ins require manual consistency management.
|
||||
|
||||
### 3.17 Workflow effects across multiple edits
|
||||
|
||||
Attempted: chain 3 edits in `SymbolFinder.java` without refreshing between them.
|
||||
|
||||
Serena call chain:
|
||||
|
||||
1. `replace_symbol_body(SymbolFinder/findFilesByName, ...)`.
|
||||
2. `insert_after_symbol(SymbolFinder/getProject, ...)`.
|
||||
3. `rename(SymbolFinder/qualNameMatchesName, ...)`.
|
||||
4. Diff/status/revert/status.
|
||||
|
||||
Observed result: all edits applied after earlier edits shifted file positions. Final diff touched 18 lines with net 9 insertions and 9 deletions.
|
||||
|
||||
Built-in equivalent chain: initial read/search, apply first patch, rely on robust patch context or refresh line numbers, apply second patch, refresh or search again, apply rename patch, verify.
|
||||
|
||||
**Verdict:** Serena's name paths remain useful after line shifts, so its advantage compounds in multi-edit sessions.
|
||||
|
||||
### 3.18 Non-code reads and free-text search
|
||||
|
||||
Attempted: read config and search free text.
|
||||
|
||||
Built-in call chain:
|
||||
|
||||
1. `Get-Content plugin.xml`.
|
||||
2. `Get-Content build.gradle.kts -TotalCount 80`.
|
||||
3. `rg "http://|https://|localhost|127\\.0\\.0\\.1|8080|24282|SERENA|serena" src/main/java src/main/resources -n`.
|
||||
|
||||
Serena call chain: not applicable.
|
||||
|
||||
Observed result: built-ins exposed plugin registration, Gradle platform setup, URLs, IDs, settings defaults, and resource/text mentions.
|
||||
|
||||
**Verdict:** Built-ins are natural and sufficient for config reading and free-text search; this is outside Serena's semantic-code scope.
|
||||
|
||||
## 4. Token-efficiency analysis
|
||||
|
||||
Payload differences across edit sizes:
|
||||
|
||||
| Task | Built-in payload | Serena payload | More efficient |
|
||||
|---|---|---|---|
|
||||
| 1-line string tweak | Tiny patch hunk, 1 changed line | Full 11-line method body | Built-ins |
|
||||
| Medium method rewrite | 10-line diff hunk | Full 8-line replacement method | Roughly equal |
|
||||
| Large body rewrite | Large contextual patch, 38-line diff | Full symbol text, about 70 lines | Roughly equal; Serena has better target |
|
||||
| Insert method | Inserted body plus surrounding context | Inserted body plus name path | Serena slightly |
|
||||
| Private one-file rename | `rg` plus 2-line patch | optional refs query plus rename command | Roughly equal |
|
||||
| Cross-file rename/move/inline | Multiple searches, file operations, patches, verifications | One semantic refactor plus diff/status | Serena |
|
||||
|
||||
Forced reads:
|
||||
|
||||
- Built-ins commonly need a search before a precise read, then a line slice or full context before editing.
|
||||
- Serena can skip full-file reads when the symbol name path is known.
|
||||
- When the symbol is not known, Serena's `get_symbols_overview` and shallow `find_symbol` calls provide compact discovery rather than full-file reads.
|
||||
|
||||
Output payload:
|
||||
|
||||
- Serena exploration output is structured and scoped to symbols.
|
||||
- Built-in grep output can be larger because it includes declarations, comments, strings, and unrelated text mentions.
|
||||
- Built-ins can be extremely low-output for known-location small edits.
|
||||
|
||||
Stable vs ephemeral addressing:
|
||||
|
||||
- Built-ins address code by file paths, line numbers, text context, or byte positions. Line numbers and slices go stale after edits.
|
||||
- Serena addresses symbols by `relative_path + name_path`, with overload indexes where needed. The chained-edit experiment showed those targets survived line shifts.
|
||||
- Path-changing operations still require updated paths afterward, so symbol stability is strongest before moves/renames that alter file locations.
|
||||
|
||||
**Verdict:** Serena saves tokens by avoiding broad reads/search triage and by collapsing multi-file edit chains; built-ins remain more token-efficient for tiny known-location hunks.
|
||||
|
||||
## 5. Reliability & correctness under correct use
|
||||
|
||||
Precision of matching:
|
||||
|
||||
- Serena reference search returned code usages and excluded route strings/comments.
|
||||
- Built-in text search returned all mentions and therefore mixed true code usage with broader text hits.
|
||||
- Serena overload indexes targeted `Symbol/getLocationString[0]` and `[1]`; text search required manual signature inspection.
|
||||
|
||||
Scope disambiguation:
|
||||
|
||||
- Serena name paths encode class nesting and overload identity.
|
||||
- Built-ins can disambiguate with careful patterns and reads, but the disambiguation is manual.
|
||||
- In simple cases, such as a private helper with one call site, this semantic precision had little practical value. In overloaded, nested, or cross-file cases, it materially reduced ambiguity.
|
||||
|
||||
Atomicity:
|
||||
|
||||
- Serena refactors apply through JetBrains refactoring operations and produce one operation-level success signal.
|
||||
- Built-in equivalents are decomposed into separate searches, file moves, patches, and verification steps.
|
||||
- Competent users can verify either path, but Serena reduces the number of intermediate inconsistent states.
|
||||
|
||||
Semantic queries vs text search:
|
||||
|
||||
- `type_hierarchy` and dependency declaration lookup produced semantic information not available from ordinary grep.
|
||||
- `rg` remained better for broad mention searches and config/resource scans.
|
||||
|
||||
External dependency limitations:
|
||||
|
||||
- Serena's dependency lookup depends on IDE/language indexes and available dependency metadata.
|
||||
- Built-ins can match or exceed it only if paired with source jars, decompilers, or separate language-server tooling.
|
||||
|
||||
Operational tradeoff:
|
||||
|
||||
- Several Serena refactors staged created/deleted files. This is not a correctness problem, but it adds index-state verification to the cleanup workflow.
|
||||
|
||||
**Verdict:** Serena improves correctness where symbol identity and cross-file semantics matter; built-ins remain reliable and simpler for text/file tasks.
|
||||
|
||||
## 6. Workflow effects across a session
|
||||
|
||||
Where Serena advantages compound:
|
||||
|
||||
- Symbol overview results become inputs to body reads, reference searches, renames, moves, safe deletes, and inline operations.
|
||||
- Name paths remain useful after line shifts, reducing re-read/re-target work during multi-edit sessions.
|
||||
- Refactor-heavy sessions benefit because one semantic command replaces search/edit/verify loops across files.
|
||||
|
||||
Where Serena advantages diminish:
|
||||
|
||||
- After a full file has already been read, overview adds less incremental value.
|
||||
- If the task is a small textual substitution in a known place, symbolic body replacement can cost more payload than a tiny patch.
|
||||
- For non-code and free-text work, Serena has no role.
|
||||
|
||||
Intermediate result durability:
|
||||
|
||||
- Serena intermediate results such as `SymbolFinder/findFilesByName` or `Symbol/getLocationString[1]` remain meaningful as long as the file/symbol still exists.
|
||||
- Built-in line numbers became stale after insertions; robust textual patch context remained usable when surrounding lines did not change.
|
||||
|
||||
Verification cost:
|
||||
|
||||
- Both workflows still need `git diff`, build/test, and domain-specific verification for permanent changes.
|
||||
- Serena success signals reduce the need to inspect every call site manually, but not the need to inspect the intended diff.
|
||||
|
||||
**Verdict:** Serena's advantages compound inside symbol-centric sessions and diminish once the work becomes plain text, config, shell, or already-loaded single-file editing.
|
||||
|
||||
## 7. Unique capabilities
|
||||
|
||||
Unique here means no practical built-in equivalent without adding separate language-server, IDE, source-index, or decompiler infrastructure.
|
||||
|
||||
- Transitive type hierarchy. Frequency: medium. Impact: high when changing base classes, interfaces, or handler contracts. Built-ins can grep explicit `extends` clauses but do not produce a semantic transitive graph or external supertypes.
|
||||
|
||||
- External dependency declaration/body lookup from a call site. Frequency: low-medium. Impact: high for API behavior questions. Serena resolved `ReferencesSearch.search` into an external class method body; ordinary built-ins did not.
|
||||
|
||||
- IDE semantic move of a nested symbol to a top-level file with usage/import repair. Frequency: low-medium. Impact: high during refactors. Built-ins can reproduce this only as a manual multi-step refactor.
|
||||
|
||||
- Safe delete with semantic usage check. Frequency: medium. Impact: medium-high. Built-ins can search and delete, but they do not provide an integrated safe-delete operation over code usages.
|
||||
|
||||
- Inline refactor with call-site substitution. Frequency: low-medium. Impact: medium-high. Built-ins can patch substitutions manually, but expression adaptation and helper deletion are not primitive text operations.
|
||||
|
||||
Not unique: reading files, listing files, grep, small patches, simple one-file renames, config/resource understanding, and shell/Git operations.
|
||||
|
||||
**Verdict:** Serena's unique practical capabilities are hierarchy/dependency queries and IDE refactors; its non-unique areas are ordinary text and file operations.
|
||||
|
||||
## 8. Tasks outside Serena's scope
|
||||
|
||||
Built-in-only or built-in-natural tasks observed:
|
||||
|
||||
- Repository inventory and top-level layout.
|
||||
- Reading `plugin.xml`, `build.gradle.kts`, scripts, resources, and generated artifacts.
|
||||
- Free-text search for URLs, settings strings, endpoint strings, magic constants, resource IDs, and comments.
|
||||
- Running shell commands, builds, tests, Git operations, and filesystem cleanup.
|
||||
- Small text edits where a one-line patch is the whole task.
|
||||
|
||||
Estimated share of daily coding work:
|
||||
|
||||
- About 30-50% of a normal coding session is built-in-natural: shell, tests, grep, config reads, small text patches, and Git checks.
|
||||
- Serena applies to much of the remaining 50-70% when the work is code navigation, symbol understanding, references, hierarchy, or refactoring.
|
||||
- Serena coverage rises in refactor-heavy sessions and falls in config/debug/test-log sessions.
|
||||
|
||||
**Verdict:** Serena augments the semantic-code portion of development; built-ins still carry a large and necessary share of routine work.
|
||||
|
||||
## 9. Practical usage rule
|
||||
|
||||
Use Serena when the task can be stated as a code-symbol operation:
|
||||
|
||||
- "What methods/classes are in this file?"
|
||||
- "Give me this method body."
|
||||
- "Who uses this symbol?"
|
||||
- "What implements/subclasses this?"
|
||||
- "Rename, move, delete, or inline this symbol and update usages."
|
||||
- "Find the declaration of this call, including dependency symbols."
|
||||
- "Apply several edits where line locations may shift."
|
||||
|
||||
Use built-ins when the task is text, file, shell, config, or tiny local editing:
|
||||
|
||||
- "List files."
|
||||
- "Read config."
|
||||
- "Search for this string anywhere."
|
||||
- "Change this one known line."
|
||||
- "Run tests/build."
|
||||
- "Inspect Git state."
|
||||
- "Edit markdown/resources/scripts."
|
||||
|
||||
For mixed workflows:
|
||||
|
||||
1. Use built-ins to find files/config and run verification.
|
||||
2. Use Serena to identify and transform code symbols.
|
||||
3. Use built-ins to inspect final diffs and run tests.
|
||||
4. Prefer built-ins for tiny local hunks after the symbol has already been located.
|
||||
5. Prefer Serena for any refactor that crosses file boundaries or depends on type/reference semantics.
|
||||
|
||||
**Verdict:** Choose Serena for symbol identity and semantic refactoring; choose built-ins for text, shell, config, verification, and minimal local edits.
|
||||
+1
-1
@@ -102,7 +102,7 @@ sphinx:
|
||||
local_extensions : # A list of local extensions to load by sphinx specified by "name: path" items
|
||||
recursive_update : false # A boolean indicating whether to overwrite the Sphinx config (true) or recursively update (false)
|
||||
config : # key-value pairs to directly over-ride the Sphinx configuration
|
||||
master_doc: "01-about/000_intro.md"
|
||||
master_doc: "01-about/000_evaluation-results.md"
|
||||
html_theme_options:
|
||||
logo:
|
||||
image_light: ../resources/serena-logo.svg
|
||||
|
||||
@@ -190,7 +190,7 @@ def autogen_about_intro_features():
|
||||
|
||||
autogen_info = f"<!-- This section is auto-generated by {__file__} from the root README.md; do not edit. -->\n\n"
|
||||
|
||||
with open(Path(__file__).parent / "01-about" / "000_intro.md", "w", encoding="utf-8") as f:
|
||||
with open(Path(__file__).parent / "01-about" / "000_evaluation-results.md", "w", encoding="utf-8") as f:
|
||||
f.write(autogen_info)
|
||||
f.write("# About Serena\n\n")
|
||||
f.write(f"**{tagline}**\n\n")
|
||||
|
||||
@@ -58,6 +58,8 @@ class JetBrainsFindSymbolTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional):
|
||||
for the case where the symbol is a class, this will return its methods).
|
||||
Ignored if `include_body=True`. Default 0.
|
||||
:param relative_path: Optional. Restrict search to this file or directory. If not specified, searches entire codebase.
|
||||
Note: for external dependencies, this must be an identifier starting with `<ext` that you have received
|
||||
earlier (don't try to guess!).
|
||||
:param include_body: If True, include the symbol's source code. Use judiciously.
|
||||
:param include_info: whether to include additional info (hover-like, typically including docstring and signature),
|
||||
about the symbol.
|
||||
@@ -71,8 +73,16 @@ class JetBrainsFindSymbolTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional):
|
||||
if include_body:
|
||||
depth = 0 # ignore user-specified depth if body is requested
|
||||
|
||||
name_path_pattern = self._sanitize_input_param(name_path_pattern)
|
||||
|
||||
if relative_path:
|
||||
relative_path = self._sanitize_input_param(relative_path)
|
||||
if relative_path == ".":
|
||||
relative_path = None
|
||||
|
||||
if relative_path is not None and relative_path.startswith(jb.JB_EXTERNAL_FILE_PREFIX):
|
||||
search_deps = True
|
||||
|
||||
with JetBrainsPluginClient.from_project(self.project) as client:
|
||||
if include_body:
|
||||
include_quick_info = False
|
||||
@@ -149,6 +159,7 @@ class JetBrainsMoveTool(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional, ToolMa
|
||||
:param target_relative_path: the relative path of the target directory or file.
|
||||
:param target_parent_name_path: the name path of the target parent symbol.
|
||||
"""
|
||||
relative_path = self._sanitize_input_param(relative_path)
|
||||
with JetBrainsPluginClient.from_project(self.project) as client:
|
||||
response_dict = client.move(
|
||||
name_path=name_path,
|
||||
@@ -187,6 +198,7 @@ class JetBrainsSafeDeleteTool(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional,
|
||||
:param propagate: whether to propagate the deletion to usages of the symbol and also
|
||||
remove symbols that become unused after the deletion. Default is False.
|
||||
"""
|
||||
relative_path = self._sanitize_input_param(relative_path)
|
||||
with JetBrainsPluginClient.from_project(self.project) as client:
|
||||
response_dict = client.safe_delete(
|
||||
name_path=name_path,
|
||||
@@ -220,6 +232,7 @@ class JetBrainsInlineSymbol(Tool, ToolMarkerSymbolicEdit, ToolMarkerOptional, To
|
||||
:param keep_definition: whether to keep the original method definition after inlining all call sites.
|
||||
May be ignored in some cases (e.g. when inlining a class).
|
||||
"""
|
||||
relative_path = self._sanitize_input_param(relative_path)
|
||||
with JetBrainsPluginClient.from_project(self.project) as client:
|
||||
response_dict = client.inline_symbol(
|
||||
name_path=name_path,
|
||||
@@ -251,6 +264,7 @@ class JetBrainsFindReferencingSymbolsTool(Tool, ToolMarkerSymbolicRead, ToolMark
|
||||
:param relative_path: the relative path to the file containing the symbol (must be a file, not a directory)
|
||||
:param max_answer_chars: max characters for the result (-1 for default). If exceeded, no content/a shortened result is returned.
|
||||
"""
|
||||
relative_path = self._sanitize_input_param(relative_path)
|
||||
with JetBrainsPluginClient.from_project(self.project) as client:
|
||||
response_dict = client.find_references(
|
||||
name_path=name_path,
|
||||
@@ -317,6 +331,7 @@ class JetBrainsGetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOp
|
||||
:param max_answer_chars: max characters for the result (-1 for default). If exceeded, no content/a shortened result is returned.
|
||||
:param include_file_documentation: whether to include the file's docstring. Default False.
|
||||
"""
|
||||
relative_path = self._sanitize_input_param(relative_path)
|
||||
with JetBrainsPluginClient.from_project(self.project) as client:
|
||||
symbol_overview = client.get_symbols_overview(
|
||||
relative_path=relative_path, depth=depth, include_file_documentation=include_file_documentation
|
||||
@@ -419,6 +434,7 @@ class JetBrainsTypeHierarchyTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptiona
|
||||
-1 means the default value from the config will be used.
|
||||
:return: Compact JSON with file-grouped hierarchy. Error string if not applicable.
|
||||
"""
|
||||
relative_path = self._sanitize_input_param(relative_path)
|
||||
with JetBrainsPluginClient.from_project(self.project) as client:
|
||||
subtypes = None
|
||||
supertypes = None
|
||||
@@ -473,6 +489,9 @@ class JetBrainsFindDeclarationTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptio
|
||||
Uses Python syntax with MULTILINE and DOTALL flags enabled.
|
||||
:param include_body: whether to include the symbol's body in the result. Default False.
|
||||
"""
|
||||
relative_path = self._sanitize_input_param(relative_path)
|
||||
regex = self._sanitize_input_param(regex)
|
||||
|
||||
editor = self.create_code_editor()
|
||||
content = editor.read_file(relative_path)
|
||||
coords = find_text_coordinates(content, regex, require_unique=True)
|
||||
|
||||
@@ -258,7 +258,8 @@ class FindReferencingSymbolsTool(Tool, ToolMarkerSymbolicRead):
|
||||
|
||||
:param name_path: for finding the symbol to find references for, same logic as in the `find_symbol` tool.
|
||||
:param relative_path: the relative path to the file containing the symbol for which to find references.
|
||||
Note that here you can't pass a directory but must pass a file.
|
||||
Note: for external dependencies, this must be an identifier starting with `<ext` that you have received
|
||||
earlier (don't try to guess!).
|
||||
:param include_kinds: same as in the `find_symbol` tool.
|
||||
:param exclude_kinds: same as in the `find_symbol` tool.
|
||||
:param max_answer_chars: same as in the `find_symbol` tool.
|
||||
|
||||
@@ -137,6 +137,11 @@ class Tool(Component):
|
||||
_last_tool_call_client_str: str | None = None
|
||||
"""We can only get the client info from within a tool call. Each tool call will update this variable."""
|
||||
|
||||
@staticmethod
|
||||
def _sanitize_input_param(raw_param: str) -> str:
|
||||
# some clients replace < and > with their escaped html versions, we need to counteract this
|
||||
return raw_param.replace("<", "<").replace(">", ">")
|
||||
|
||||
@classmethod
|
||||
def set_last_tool_call_client_str(cls, client_str: str | None) -> None:
|
||||
cls._last_tool_call_client_str = client_str
|
||||
|
||||
Reference in new issue
Block a user