Activated Cloud
← App Store

Make a Surgical Change

Activated Cloud✓ Officialactivated/make-surgical-change

No ratings yet12 installsv1.0.0Updated Oct 6, 2026● Unknown

Free · MIT

About

Makes a small, targeted code or config change (a fix, a rename, a default, a copy change, one function) with the smallest correct diff: locate the exact site, read it first, find every caller before touching an interface, match the file's style, edit with patch, validate the syntax, run the relevant checks and show the diff. Use when the change fits in one or a few files and needs no plan. Not for multi-step features (use implement-feature-end-to-end) or behaviour-preserving restructuring (use refactor-safely).

Software Development

Documentation

From SKILL.md · v1.0.0 · what the agent reads when it loads this skill2 files: SKILL.md, references/edit-gotchas.md

Make a Surgical Change

Most real edits are small, and small edits are where careless habits do the most damage: the wrong one of two similar functions gets patched, a caller is missed, a whole file is reformatted, a YAML file stops parsing. A surgical change touches exactly what it must, looks like the code around it, and is proven by a check you ran.

When to use

  • "Change the timeout to 30 seconds", "rename this field", "fix the typo on the pricing page", "make this function return None instead of raising".
  • A one-line bug fix whose cause is already known.
  • Config, dependency pin, environment or CI tweaks.

Check the size before you start, and again if the change grows:

Signal Still surgical?
One to three files, internal code only Yes
A default, constant or signature others call Yes, after the caller search in step 3
Touches a public API, schema, migration or another team's code No: plan it as a feature
Needs new tests across several modules, or more than about 100 changed lines No: plan it as a feature
The cause of the bug is not yet known No: find the root cause first

What you need

  • The exact request. If "the timeout" could mean three timeouts, ask which with clarify (name the candidates and their locations).
  • Write access to the repo (GitHub or GitLab connected app, or a git credential on your computer), or an uploaded copy if the owner wants a patch back.
  • The command that checks the area you are changing: a specific test, the linter, a config validator.

Method

  1. Locate the exact site. search_files for the literal string, symbol or error text. If there are several hits, open each with read_file and decide which one the request means. Similar code in two places (a copy-pasted validator, a duplicated constant) often needs the change in both: check, and say what you did.

  2. Read before you edit. read_file the whole function or block you will change, plus enough above and below to see imports, types and how the result is used. Note the file's style: indentation, quotes, naming, error handling, type hints, import order, line length. If you or anything else may have changed the file since you read it, read it again.

  3. Check the blast radius. If you change anything others depend on (a function signature, return type, default value, exported name, constant, config key, environment variable, CLI flag, route, DB column, event name, CSS class used by tests), search for every reference:

    • search_files with \bname\b across the repo, excluding vendored and build folders;
    • string and dynamic uses ("name", getattr(obj, "name"), data["name"], templates, YAML, SQL, docs, tests);
    • other services or repos that consume it, if it crosses a boundary. Update every reference, or keep the old form working (a default argument, an alias) and say so in your summary.
  4. Edit with patch, smallest unique match. Pick an old_string that occurs once and includes a line or two of context. Read the unified diff that patch returns: it uses fuzzy matching, so confirm the change landed where you meant and nowhere else. Use replace_all only when you have counted the occurrences and want all of them. Do not rewrite a whole existing file with write_file for a small change: it churns formatting and silently drops anything that changed since you read it.

  5. Keep the diff clean.

    • No drive-by reformatting, renaming or reordering of lines you were not asked to touch.
    • Keep the file's line endings, indentation and trailing newline.
    • Generated files (*.pb.go, dist/, lockfiles, compiled CSS): change the source and regenerate with the project's command; never hand-edit the output.
    • Lockfiles change only through the package manager (npm install pkg@x, uv add, go get, cargo update -p).
    • Known language traps are listed in references/edit-gotchas.md. Check the ones for your file type.
  6. Validate syntax for config and data files.

    python -c "import sys, yaml; yaml.safe_load(open(sys.argv[1]))" path.yml && echo ok
    python -m json.tool path.json > /dev/null && echo ok
    python -c "import sys, tomllib; tomllib.load(open(sys.argv[1], 'rb'))" path.toml && echo ok
    docker compose config -q && echo ok
    

    Use the tool's own validator when there is one (nginx -t, terraform validate, actionlint, promtool check config).

  7. Run the narrowest meaningful check, then one wider. The test covering the code you changed, then that test file or package; the linter and type checker on the touched files. Check the exit code of each. If no test covers the behaviour you changed and it is logic (not copy or config), add one, or say plainly that it is untested.

  8. Show the diff. git diff (or git diff --stat plus the relevant hunks). Read it once more as a reviewer: is every changed line necessary?

  9. Commit if the workflow calls for it. Stage the exact paths, write a message that says why (fix(api): raise upload timeout to 30 s for large CSVs), and leave pushing to the owner's rules.

Output

A short message with: what changed and where (file:line), why that site and not the similar one, callers updated (or "none, internal only"), the checks you ran with their results, and the diff (or its key hunk) in a code block. For example:

Raised the CSV upload timeout from 10 s to 30 s in `api/uploads.py:42` (`UPLOAD_TIMEOUT_S`).
The other timeout in `api/client.py:17` is for outbound calls, so I left it alone.
Callers: the constant is used only in `api/uploads.py` (searched the repo and config files).
Checks: `pytest tests/test_uploads.py -q` passed (7 tests); `ruff check api/uploads.py` exit 0.

```diff
-UPLOAD_TIMEOUT_S = 10
+UPLOAD_TIMEOUT_S = 30  # large CSV imports exceed 10 s on the free plan
```

Checks before you finish

  • You read the file right before editing it, and the returned diff shows only the intended change.
  • Every reference to anything you renamed or re-typed was found and handled.
  • Config and data files parse.
  • The relevant test, linter and type check were run after the edit, with exit codes noted.
  • No unrelated lines changed (git diff --stat shows only the files you meant).

Pitfalls

  • Patching the wrong twin. Two functions with the same name in different modules, or a test fixture that mirrors production code. Confirm the call path before editing.
  • Changing a default and breaking a caller that relied on it. A default is an interface. Search for calls that omit the argument.
  • Fuzzy-match surprises. patch will find the closest match. A short old_string like return None may hit the first of five. Include context and read the diff.
  • YAML traps. Tabs are illegal; on, yes, no and off may parse as booleans; 010 may parse as octal in older parsers; indentation changes meaning. Quote strings that look like other types.
  • Whole-file rewrites. They hide the real change inside formatting noise and can erase a teammate's edit.
  • "It's only a string change." Strings are matched in tests, translations, analytics events and API clients. Search before changing them.
  • No check at all. Even a copy change deserves a look in the browser or a grep of the rendered template.

Versions

v1.0.0currentOct 6, 2026

Listed from the source repository.

Reviews

No reviews yet. Be the first.

Write a review