Task Statement 2.5·Domain 2 — 18% of exam
Built-in Tools
Select and apply built-in tools (Read, Write, Edit, Bash, Grep, Glob) effectively
Official Exam Guide Objectives
Task 2.5: Select and apply built-in tools (Read, Write, Edit, Bash, Grep, Glob) effectively.
Knowledge of
- Grep for content search (searching file contents for patterns like function names, error messages, or import statements)
- Glob for file path pattern matching (finding files by name or extension patterns)
- Read/Write for full file operations; Edit for targeted modifications using unique text matching
- When Edit fails due to non-unique text matches, using Read + Write as a fallback for reliable file modifications
Skills in
- Selecting Grep for searching code content across a codebase (e.g., finding all callers of a function, locating error messages)
- Selecting Glob for finding files matching naming patterns (e.g., **/*.test.tsx)
- Using Read to load full file contents followed by Write when Edit cannot find unique anchor text
- Building codebase understanding incrementally: starting with Grep to find entry points, then using Read to follow imports and trace flows, rather than reading all files upfront
- Tracing function usage across wrapper modules by first identifying all exported names, then searching for each name across the codebase
What You Need to Know
Six built-in tools cover working with a codebase: Read, Write, Edit, Bash, Grep, and Glob. Each is built for a particular job, and reaching for the wrong one costs time, context, or both. Exam items are constructed around exactly those confusions.
Grep vs Glob: The Core Distinction
Nothing else in this task statement is tested as often. Get it wrong and you'll lose marks.
Grep searches file CONTENTS for patterns. Reach for it whenever the question is about what is written inside files — who calls a function, where an error string is raised, which modules import something, where a variable is assigned.
// Every call site of processLegacyOrder()
Grep: "processLegacyOrder"
// Anywhere a timeout is reported to the user
Grep: "timeout"
// Whoever imports the auth helpers
Grep: "import.*from 'utils/auth'"Glob matches file PATHS by naming patterns. Reach for it whenever the question is about which files exist — tests, configuration, everything of one extension beneath a directory.
// Every test file, wherever it sits
Glob: "**/*.test.tsx"
// Config, whatever extension it uses
Glob: "**/config.*"
// The MDX under the domains tree
Glob: "content/domains/**/*.mdx"The distinction in one sentence: Grep finds what is INSIDE files. Glob finds files by their NAMES.
Items are built on the substitution. Sent after function callers, Glob returns nothing useful, because a path never contains a call. Sent after test files, Grep can stumble into a partial answer by matching the word in content — which is worse than failing outright, since a partial answer looks like a working one.
Read, Write, and Edit
Three tools for touching files, each suited to a different situation.
Edit changes one thing, located by matching text you supply exactly. It is quick and it is precise, because nothing outside the matched region is loaded or rewritten.
Edit:
old_string: "function processOrder(id: string)"
new_string: "function processOrder(id: string, validate = true)"When Edit fails: the match has to be unique. Where the text you gave appears more than once, Edit stops rather than guessing which occurrence you meant. That refusal is the feature — a guess would silently modify code you never looked at.
When Edit can't find a unique anchor. The fix per the Edit tool docs is to widen old_string with more surrounding context until it pins down one location, or set replace_all: true if every occurrence genuinely should change. Both keep the operation on Edit and cost almost nothing extra. Read + Write — pulling the entire file in, sending the entire file back — is the last resort. It works, and it spends a whole file's worth of context on what was usually a single line.
The ordering:
- Try Edit with the shortest anchor that's plausibly unique.
- If the match is not unique, extend
old_stringwith surrounding lines until exactly one place matches — or setreplace_all: truewhere every occurrence really should change. - Reach for Read + Write only once neither of those can single out the target.
Two habits are penalised here, and they are different mistakes. Reaching for Read + Write as the standard way to modify a file wastes context on every edit. Reaching for it the instant Edit reports a non-unique match skips the documented recovery, which was two more words of anchor away.
Incremental Codebase Understanding
The order you explore in matters as much as the tools you explore with, and there is a wrong order.
Wrong: Read all files upfront. Loading everything before you know what is relevant is the single most expensive mistake available. Read a 200-file codebase in full and the context window is gone, spent overwhelmingly on files with no bearing on the task.
Right: Incremental discovery. Start narrow. Expand only as needed.
-
Grep to find entry points. Search the name or message that anchors the investigation. The result tells you which files are worth opening.
-
Read to follow imports and trace flows. With the relevant files identified, read them to understand structure, and follow their imports outward to whatever else is implicated.
-
Grep again to trace usage. A wrapper or re-export found along the way becomes a new search term, revealing consumers the first search could not have matched.
-
Read only what you need. Every file opened should be justified by something the previous step turned up.
The result is understanding built at the cost of the files that mattered, rather than the cost of the repository.
Tracing Function Usage Across Wrapper Modules
A common codebase pattern defeats a single search: a function defined in one module, re-exported through a wrapper, and called everywhere under the wrapper's name. Grep for the original and every one of those consumers is invisible.
The correct approach:
- Grep for the function definition — locate the module that declares it
- Read the defining file — note every name under which it leaves that module
- Grep for each exported name — one search per alias, since each has its own consumers
- Where a barrel file such as
index.tsre-exports it, Grep for the barrel's module name as well, to catch imports written against the barrel rather than the source
Each pass supplies the search terms for the next, which is how indirect consumers surface at all.
The Deprecation Scenario
This one turns up constantly in exam prep: find every file that calls a deprecated function AND the test files that exercise it. The correct sequence:
- Grep for the function name — finds every file whose contents reference the function, including any tests that import it directly (content search)
- Glob for sibling test files — finds the test file that pairs with each caller by naming convention, e.g.
OrderProcessor.ts→OrderProcessor.test.tsx, even when the test exercises the function indirectly through the source module (path matching) - Grep again for wrapper names — when a caller exposes the function through a wrapper (e.g.
applyLegacyOrdercallsprocessLegacyOrderinternally), Grep for the wrapper name to find tests that cover the function transitively through it
Concretely: the first pass shows OrderProcessor.ts and RefundHandler.ts among the callers. Globbing **/OrderProcessor.test.* and **/RefundHandler.test.* then brings in their paired tests, which matter even though they may never write processLegacyOrder anywhere. And where one of those files re-exposes the function under another name, a third pass on that name finds the tests reaching it indirectly.
Grep, then Glob, then Grep — contents for the direct references, paths for the tests sitting alongside them, contents again for the coverage that arrives through a wrapper. Beginning with Glob inverts it and finds only the tests whose names you could already guess.
Deep Dive
The built-in roster is bigger than the six this lesson names
This task statement names six built-ins (Read, Write, Edit, Bash, Grep, Glob), but the documented roster is larger. The Agent SDK overview lists built-in tools as covering "Read, write, edit files, run commands, and search the web", and the SDK's tool-input-type reference names them explicitly: "Built-in tools include Bash, Read, Write, Edit, Glob, Grep, WebFetch, Agent, and others." WebFetch fetches external content; Agent spawns subagents (see below). In the SDK, the tools option controls which built-ins are actually available to a given agent: tools: ["Read", "Grep"] keeps only the listed built-ins in context (MCP tools are unaffected), while tools: [] strips every built-in so the agent can only call your MCP tools. That's the mechanism behind "scope an agent's tools to its role" when the tools in question are built-ins rather than MCP tools.
Sourcescode.claude.com › overviewcode.claude.com › hookscode.claude.com › custom-toolsfetched 2026-07-30
Agent — the built-in for spawning subagents (formerly named Task)
Practically: "Claude invokes subagents through the Agent tool, so include Agent in allowedTools to auto-approve subagent invocations without a permission prompt." If a coordinator's tool-use log shows Task instead of Agent (or vice versa), that's a version artefact, not a different tool.
Sourcecode.claude.com › subagentsfetched 2026-07-30
Permission-rule syntax scopes what a built-in can actually do
--allowedTools lists tools (using permission-rule syntax) that run without a prompt; to restrict which tools are available at all use --tools instead — allow-listing and availability-restriction are different mechanisms. In --disallowedTools, a bare tool name removes the tool from Claude's context entirely ("Edit" removes Edit outright, "*" removes every tool), while a scoped rule such as Bash(rm *) leaves the tool available but denies only matching calls. Bash rules support prefix matching, and the trailing space matters: Bash(git diff *) allows any command starting with git diff, but without the space, Bash(git diff*) would also wrongly match git diff-index. WebFetch uses its own rule shape — a domain: prefix matched against the hostname: WebFetch(domain:example.com) matches that host; WebFetch(domain:*.example.com) matches any subdomain at any depth but not the apex domain itself.
--allowedTools "Bash(git diff *),Read,Edit"
--disallowedTools "Bash(rm *)" # Bash stays available; rm is denied
--disallowedTools "Edit" # Edit removed from context entirelySourcescode.claude.com › cli-referencecode.claude.com › headlesscode.claude.com › permissionsfetched 2026-07-30
Built-ins and MCP tools share a permission surface but a different naming convention
Built-in tools are referenced by their bare name (Read, Grep, Bash(...)) in permission rules. MCP tools instead use the namespaced pattern mcp__<server-name>__<tool-name> — for example a list_issues tool on a server named github becomes mcp__github__list_issues. Permission rules can target a whole server (mcp__puppeteer, matching any of its tools), every tool on a server via wildcard (mcp__puppeteer__*), or one specific tool (mcp__puppeteer__puppeteer_navigate). This naming convention is how you tell, in a permission prompt or a tool-use log, whether a given call is a built-in or an MCP-provided tool — directly relevant when deciding (per Task 2.4) whether the agent should prefer a built-in like Grep or a better-described MCP alternative.
Sourcescode.claude.com › permissionscode.claude.com › mcpfetched 2026-07-30
Quick Reference
| Fact | Value |
|---|---|
| Grep | Searches file contents — function callers, error messages, imports |
| Glob | Matches file paths by naming pattern — **/*.test.tsx, **/config.* |
| Edit | Targeted modification via unique old_string match; fails on non-unique text |
| Edit non-unique fix | Widen old_string with more context, or set replace_all: true |
| Read + Write | Last-resort fallback only when neither widening nor replace_all disambiguates |
| Documented built-in roster | Bash, Read, Write, Edit, Glob, Grep, WebFetch, Agent, "and others" |
SDK tools option | tools: [...] keeps only listed built-ins; tools: [] removes all built-ins (MCP tools unaffected) |
| Agent tool | Spawns subagents; renamed from Task in Claude Code v2.1.63 — exam guide text still says "Task" |
--allowedTools vs --tools | --allowedTools skips the permission prompt; --tools restricts availability |
--disallowedTools bare name | Removes the tool from context entirely (e.g. "Edit", or "*" for all) |
--disallowedTools scoped rule | e.g. Bash(rm *) — tool stays available, only matching calls denied |
| Bash prefix matching | Bash(git diff *) (trailing space) matches any git diff… command; without the space it would also match git diff-index |
| WebFetch domain rule | WebFetch(domain:example.com); domain:*.example.com matches subdomains, not the apex |
| MCP tool naming | mcp__<server-name>__<tool-name>, e.g. mcp__github__list_issues |
| MCP permission rule scoping | mcp__server (whole server) · mcp__server__* (wildcard) · mcp__server__tool (one tool) |
| Incremental exploration order | Grep for entry points → Read to trace flows → Grep again for wrapper/barrel names → Read only what's justified |
Exam Traps
Practice Scenario
A developer needs to find all files that call a deprecated function processLegacyOrder() and also find all test files for those callers. Which tool sequence is correct?
Build Exercise
Trace and Refactor a Deprecated Function Using Built-in Tools
Difficulty: Intermediate (2/4)
30 minutes
- Use Grep to search for all callers of a target function (e.g. processLegacyOrder) across the codebase
Why: Grep searches file contents — it is the correct tool for finding function callers. Using Glob here would fail because Glob matches file paths, not contents. The exam tests this distinction directly and penalises candidates who confuse the two.
You should see: A list of file paths containing calls to processLegacyOrder, with line numbers and matching lines showing the exact call sites. For example: src/OrderProcessor.ts:42: await processLegacyOrder(orderId).
- Use Glob to find test files matching the caller filenames (e.g. **/*.test.tsx)
Why: Glob matches file paths by naming pattern — it is the correct tool for finding test files by extension or naming convention. This completes the Grep-then-Glob pattern: content search to find callers, then path matching to find their tests.
You should see: A list of test file paths matching the pattern, such as src/OrderProcessor.test.tsx and src/RefundHandler.test.tsx. These correspond to the caller files found by Grep in the previous step.
- Use Read to examine each caller file and understand the usage pattern and context
Why: Reading files incrementally — only after Grep identifies which files matter — is the correct approach. Reading all source files upfront is a context-budget killer that the exam explicitly penalises. Each Read should be justified by what you discovered in the previous step.
You should see: The full contents of each caller file, showing how processLegacyOrder is called, what parameters are passed, how the return value is used, and whether the function is imported directly or through a wrapper module.
- Use Edit to replace the deprecated function call with the new API in each caller file
Why: Edit is the preferred modification tool because it targets specific text and uses less context than Read + Write. The exam penalises defaulting to Read + Write for every modification. Always try Edit first — it is faster and more precise.
You should see: Each caller file updated with the new API call replacing the deprecated one. For example, processLegacyOrder(orderId) replaced with processOrder(orderId, { validate: true }). The Edit tool confirms the replacement was made successfully.
- When Edit fails with a non-unique match, widen old_string with more surrounding lines until it pins down one location (or set replace_all: true if you actually want every occurrence updated). Only fall back to Read + Write if neither option can disambiguate the target
Why: Edit fails when the target text appears multiple times in the file — this is a safety mechanism, not a bug. Per the Edit tool documentation, the documented recovery is to expand the anchor with more surrounding context until it matches one place, or to use replace_all for global replacements. Both keep you on Edit and cost almost nothing in context. Read + Write loads the entire file for what is usually a single-line change — keep it as a last resort.
You should see: On the first try, Edit fails with an error like: old_string matches 3 locations. On the retry with a wider old_string that includes the surrounding function name or unique adjacent line, Edit succeeds and changes exactly one occurrence. If replace_all: true was the right call, every occurrence is updated atomically.
Sources
- Claude Certified Architect Foundations Exam Guide — Domain 2, Task Statement 2.5 — Anthropic
- Claude Code Documentation — Built-in Tools — Anthropic
- Building with Claude API — Anthropic — Anthropic
- Agent SDK overview — Anthropic
- CLI reference — Anthropic
- Permissions — Anthropic
- Headless mode — Anthropic
Appendix A — Build Exercise Step Hints
Progressive hints revealed by the "Stuck? Get a nudge" control on each step.
Step 1. Use Grep to search for all callers of a target function (e.g. processLegacyOrder) across the codebase
Why: Grep searches file contents — it is the correct tool for finding function callers. Using Glob here would fail because Glob matches file paths, not contents. The exam tests this distinction directly and penalises candidates who confuse the two.
You should see: A list of file paths containing calls to processLegacyOrder, with line numbers and matching lines showing the exact call sites. For example: src/OrderProcessor.ts:42: await processLegacyOrder(orderId).
Stuck? Get a nudge
Step 2. Use Glob to find test files matching the caller filenames (e.g. **/*.test.tsx)
Why: Glob matches file paths by naming pattern — it is the correct tool for finding test files by extension or naming convention. This completes the Grep-then-Glob pattern: content search to find callers, then path matching to find their tests.
You should see: A list of test file paths matching the pattern, such as src/OrderProcessor.test.tsx and src/RefundHandler.test.tsx. These correspond to the caller files found by Grep in the previous step.
Stuck? Get a nudge
Step 3. Use Read to examine each caller file and understand the usage pattern and context
Why: Reading files incrementally — only after Grep identifies which files matter — is the correct approach. Reading all source files upfront is a context-budget killer that the exam explicitly penalises. Each Read should be justified by what you discovered in the previous step.
You should see: The full contents of each caller file, showing how processLegacyOrder is called, what parameters are passed, how the return value is used, and whether the function is imported directly or through a wrapper module.
Stuck? Get a nudge
Step 4. Use Edit to replace the deprecated function call with the new API in each caller file
Why: Edit is the preferred modification tool because it targets specific text and uses less context than Read + Write. The exam penalises defaulting to Read + Write for every modification. Always try Edit first — it is faster and more precise.
You should see: Each caller file updated with the new API call replacing the deprecated one. For example, processLegacyOrder(orderId) replaced with processOrder(orderId, { validate: true }). The Edit tool confirms the replacement was made successfully.
Stuck? Get a nudge
Step 5. When Edit fails with a non-unique match, widen old_string with more surrounding lines until it pins down one location (or set replace_all: true if you actually want every occurrence updated). Only fall back to Read + Write if neither option can disambiguate the target
Why: Edit fails when the target text appears multiple times in the file — this is a safety mechanism, not a bug. Per the Edit tool documentation, the documented recovery is to expand the anchor with more surrounding context until it matches one place, or to use replace_all for global replacements. Both keep you on Edit and cost almost nothing in context. Read + Write loads the entire file for what is usually a single-line change — keep it as a last resort.
You should see: On the first try, Edit fails with an error like: old_string matches 3 locations. On the retry with a wider old_string that includes the surrounding function name or unique adjacent line, Edit succeeds and changes exactly one occurrence. If replace_all: true was the right call, every occurrence is updated atomically.
Stuck? Get a nudge
Appendix B — Interactive Study Prompts
Two prompts to paste into Claude. B1 drills the judgement the exam actually measures; B3 reviews the code you wrote for the Build Exercise above. The exam simulator between them is the interactive quiz on this page.
B1. Concept Check — Discrimination Drill
You are examining me for the Claude Certified Architect – Foundations (CCAR-F) exam, Domain 2: Tool Design & MCP Integration (18% of the exam), Task Statement 2.5: Built-in Tools. Use British English throughout.
What this exam actually measures. Not one item on the official exam asks what something is. Every item drops you into a production system that is already misbehaving, offers four defensible engineering responses, and asks which is best. The skill being tested is proportionality: fix the root cause with the cheapest instrument that gives the guarantee the situation demands. So do not quiz me on definitions. Make me choose between options that are both defensible, then attack whatever I chose.
How to run this session.
- One question at a time. Stop and wait. Never answer your own question, and never move on until I have committed.
- Never reveal which option is right before I commit to one.
- Do not praise me. A correct answer earns "Yes" and the next question. If I am right for the wrong reason, say so — that is the failure that costs marks on exam day.
- When I am wrong, quote the exact phrase in my answer that gave it away, correct it in one sentence, and move on. One correction at a time.
- If I write something fluent but empty, name it: "That is a restatement, not a reason."
- Set every scenario inside one of the exam's production contexts: the Customer Support Resolution Agent (Agent SDK, MCP tools
get_customer,lookup_order,process_refund,escalate_to_human), the Multi-Agent Research System (a coordinator delegating to web-search, document-analysis, synthesis and report-generation subagents), or Developer Productivity with Claude (an agent over an unfamiliar codebase usingRead,Write,Bash,Grep,Glob).
Session plan — about twelve questions.
Round 1 — Anchor (1 question). One concrete question to check I have actually read the material. If I cannot answer it, stop the session and tell me to read the lesson before continuing.
Round 2 — Discrimination (5 questions). Each one: describe a symptom in one of the contexts above, with a number or a log observation in it. Offer exactly two responses, both defensible. Ask me to pick one and justify it in a single sentence. Then argue the case for the option I rejected as strongly as you can, and ask whether I am holding or changing my answer. Only after I answer that, tell me which is right and why the other one is the more tempting trap.
Round 3 — Proportionality (2 questions). Take one symptom and run it twice with different stakes: once where the cost of an error is a wasted retry, once where it is an incorrect refund or a corrupted production branch. The right answer must change between the two. If I answer the same way both times without noticing the stakes moved, that is the finding — tell me.
Round 4 — Code review (3 questions). Present a colleague's confident proposal containing one of the trap errors listed below, written the way a teammate would write it in a pull request. Ask me what is wrong with it. Do not signal that anything is wrong.
Round 5 — Verdict. Rate me green, amber or red on each concept below. Name the single weakness most likely to cost me marks, and give me one specific next action: a section of this lesson to re-read, or a step of the Build Exercise to redo. If I am not ready for this task statement, say so plainly.
Concepts in scope
GrepagainstGlob— one searches inside files for text such as call sites, error strings and import statements; the other matches file paths against a naming pattern such as a test-file or config-file glob. Contents versus names, and the exam punishes the swap in both directions.Editand its non-unique failure —Editmodifies through a uniquely matching anchor and refuses when that anchor matches more than one place, which is a safety mechanism; the documented recovery is to widen the anchor with surrounding context, or to setreplace_allwhen every occurrence genuinely should change.ReadplusWriteas the last resort — loading a whole file and writing it back works, but spends a file's worth of tokens on what is usually a single line, so it is reserved for the case where neither a wider anchor norreplace_allcan pin the target.- Incremental codebase understanding — search for the entry point, read to follow imports and trace the flow, search again for wrapper or barrel names, and open nothing that the previous step did not justify; reading the whole tree upfront is the costliest mistake in this task statement.
- Tracing through wrappers — a function re-exported under another name hides its consumers from a single search, so you find the definition, read it for the exported names, search for each of those, and search for the barrel module's name to catch anyone importing through it.
- The deprecation sequence — search for the function to find its direct callers, glob for their sibling test files by naming convention, then search again for wrapper names to catch tests that exercise it indirectly. Content search, then path matching, then content search again — never path matching first.
Trap errors to plant in Round 4
- Reaching for
Globto find every caller of a function. - Reaching for
Grepto collect files by extension or naming convention. - Reading every source file before knowing which ones the task actually touches.
- Defaulting to
ReadplusWritefor routine modifications instead of tryingEditfirst. - Escalating to
ReadplusWritethe momentEditreports a non-unique match, rather than widening the anchor or settingreplace_all.
Stay inside the material above. If I raise something outside it, tell me it is out of scope for this task statement and return to the drill. Begin with Round 1.
B2. Exam Simulator
Exam simulator
Question 1 of 10
Scenario · Developer Productivity with Claude
processLegacyOrder is being removed next sprint. You need every file that calls it, plus the test files that exercise those callers — including tests that reach it indirectly through the caller's own module and never name the function. What's the correct approach?
B3. Build Coach — Code Review
The Build Exercise and its hint ladder are already on this page. This prompt is for the one thing the page cannot do: review the work you actually did.
You are a staff engineer reviewing my implementation of a build exercise for the Claude Certified Architect – Foundations exam, Domain 2, Task Statement 2.5: Built-in Tools. Use British English throughout.
I am building a traced refactor of a deprecated function across an unfamiliar codebase, using only the built-in tools: a content search to find every direct caller, a path-pattern search to pull in the sibling test files by naming convention, reads confined to the files those two steps justified, Edit to swap each deprecated call for the new API, and — where Edit reports a non-unique match — a widened anchor or replace_all before Read plus Write is considered at all. The artefact under review is the sequence of tool calls I made with their arguments, plus the resulting diffs.
It has to satisfy all of the following:
- The hunt for callers is a content search returning file paths, line numbers and the matching call sites, not a list of files that merely look relevant by name.
- The test files are found by path pattern against the caller names, and only after the callers are known.
- Every file opened is one the previous step pointed at; nothing resembling a bulk read of the tree happens at any point.
- Each caller is modified with
Edit, with the deprecated call replaced by the new API and the tool confirming a single replacement. - The non-unique match is resolved by widening the anchor until it pins one location, or by
replace_allwhere every occurrence genuinely should change, withReadplusWriteused only if neither disambiguates.
How to review.
- Ask me to paste my code — the tool calls in the order I made them, with their arguments, and the diffs they produced. If I have not pasted any, ask for it and nothing else. Do not do the trace for me, do not offer a reference solution, and do not fill in a step I have skipped.
- Work through the criteria above in order. For each one, quote the line of my code that satisfies it, or say plainly that nothing does.
- Then hunt for the failure modes below. Each is a real production bug, not a style preference.
- Rank everything you find: (1) would fail in production, (2) would lose marks on the exam, (3) style. Give me the first item under (1) and then stop — wait for my fix before giving me the next one.
- If my code satisfies everything, do not congratulate me. Change the requirements — one caller reaches the deprecated function through a barrel re-export under a different name — and make me find that caller's tests.
- If I ask you to just do it for me, refuse once and give me the smallest nudge that would unblock me instead.
Failure modes to probe
- Path matching used for the caller hunt, which returns files whose names happen to fit the pattern and silently misses every actual call site.
- A read of the whole source tree ahead of the search, which fills the context window with files the task never touches and leaves no room for the ones it does.
ReadplusWritereached for the instantEditreports a non-unique match, rewriting an entire file to change one line that a wider anchor would have pinned.replace_allused to get past a non-unique match that was only ever meant to change in one place, so unrelated occurrences are rewritten without anyone noticing.- Wrapper consumers never traced — one search on the original name, no read of the defining file for its exported names — so the tests that exercise the function through the wrapper are left pointing at the deprecated path.
Start by asking me for my code.