Brief an Agent on a Dependency Upgrade Without Losing Compatibility
Drafted and reviewed using AI assistance.
On this page
A useful dependency-upgrade request names the dependency, its current and target versions, the application behavior that must survive, and the evidence needed before accepting the change. Ask the agent to inspect both the dependency graph and the code that calls the package. A rewritten lockfile establishes neither a compatible API nor correct application behavior.
GitHub's Dependabot error reference describes updates blocked by relationships between direct and indirect dependencies. That is one reason to inspect the graph before treating an upgrade as a version-number edit. The following example adds a separate application-level contract to that investigation.
Draw the two levels that can change
The application, packages, versions, interfaces, and release notes in this article are invented. They illustrate an upgrade exercise and do not describe real packages, security advisories, or executed tests.
Imagine an order-export application with one direct formatting dependency. Its recorded dependency graph is:
order-export application
-> fictive-csv-writer 1.4.0 direct dependency
-> fictive-quote-core 1.2.0 indirect dependency
Proposed target graph
order-export application
-> fictive-csv-writer 2.0.0 direct dependency
-> fictive-quote-core 2.1.0 indirect dependency
For this exercise, these are exact selected versions, not claims about a real package manager's range syntax or lockfile format. The application imports only the direct dependency. A change to the indirect dependency may still matter if it affects the output produced by that direct dependency.
The fictional target notes say:
fictive-csv-writer 2.0.0
- Replace writeRows(rows, { header: true }) with
renderRows(rows, { columns: [...] }).
- Return { text, rowCount } instead of a string.
- Use fictive-quote-core 2.1.0.
- A column's position in the columns array determines output order.
- A selected column missing from any row raises MissingColumnError.
- Keep the defined quoting behavior for commas and double quotes.
- Change the default record separator from CRLF to LF.
- Accept recordSeparator: "\r\n" to retain CRLF output.
Runtime support information: not supplied in this exercise.
These notes identify three different questions. Will the dependency graph resolve? Can the caller use the new API? Will the generated file still satisfy its consumer? They need different evidence.
Put the caller's contract next to the API change
The original application wrapper is:
import { writeRows } from "fictive-csv-writer";
export function exportOrders(rows) {
return writeRows(rows, { header: true });
}
The invented application requirement, EXPORT-4, is:
Input: records with order_id and customer_name string fields.
Output: a string containing columns order_id,customer_name in that order.
Every record, including the header, ends with CRLF.
Commas inside a field require surrounding double quotes.
A double quote inside a field is represented by two double quotes.
Empty input returns the header followed by CRLF.
Rows with missing required fields are outside this upgrade's input contract.
The phrase “upgrade the library” does not carry these requirements. Supply them explicitly, particularly when the new version's defaults differ.
For this fictional input:
[
{"order_id": "o-1", "customer_name": "Moss, Lee"},
{"order_id": "o-2", "customer_name": "Jo \"JJ\""}
]
the required output string, shown with escaped line endings, is:
order_id,customer_name\r\n
o-1,"Moss, Lee"\r\n
o-2,"Jo ""JJ"""\r\n
Each displayed line is one record; \r\n denotes the two required characters at its end. This is manually constructed expected content, not output captured from a package.
An illustrative adaptation is:
import { renderRows } from "fictive-csv-writer";
export function exportOrders(rows) {
return renderRows(rows, {
columns: ["order_id", "customer_name"],
recordSeparator: "\r\n",
}).text;
}
This snippet follows the invented interface. It is a candidate to verify, not evidence that an installation or migration succeeded. In a real upgrade, read the actual target documentation before choosing an option name or adapting a return type.
Fill an impact matrix
| Surface | Current contract | Target change or unknown | Proposed response | Evidence required |
|---|---|---|---|---|
| Direct dependency | Writer 1.4.0 | Writer 2.0.0 | Change the selected writer version | Resolved dependency graph and manifest diff |
| Indirect dependency | Quote core 1.2.0 | Quote core 2.1.0 | Accept only the related graph change | Explain the parent-child path and extra changes |
| Imported symbol | writeRows |
renderRows |
Adapt the one application wrapper | Caller search and small source diff |
| Return value | String | Object with text |
Return .text from the wrapper |
Assert that application output remains a string |
| Column order | order_id,customer_name |
Explicit columns required | Supply the required order | Exact header and two-record comparison |
| Record separator | CRLF | LF default | Supply CRLF explicitly | Compare exact output characters |
| Escaping | Preserve commas and quotes | Stated unchanged in fictional notes | Keep application expectations | Comma and quote fixture assertions |
| Empty input | Header plus CRLF | Not established by the supplied notes | Inspect target behavior; do not assume it | Empty-input check against EXPORT-4 |
| Runtime support | Application's existing runtime | Target support information absent | Obtain target support evidence | Supported-runtime note before acceptance |
| Invalid rows | Outside supplied contract | Missing columns now throw | Document boundary; avoid inventing a policy | Confirm no affected valid caller relies on missing fields |
The empty-input row is deliberately unresolved. A short migration snippet can look right while leaving an application requirement untested. The matrix tells the agent which question to answer next.
Copy this upgrade brief
Upgrade the order-export application's direct fictive-csv-writer
dependency from 1.4.0 to 2.0.0 while preserving EXPORT-4 below.
The named packages and supplied notes belong to this exercise.
Before editing:
- Inspect the actual manifest, lockfile, current wrapper, and callers.
- Confirm the current and proposed direct/indirect dependency graph.
- Read the supplied v2 notes. Flag the missing runtime-support evidence.
- Search for other imports or consumers; do not assume this wrapper is
the only caller because it is the only one shown in the request.
Allowed changes:
The writer's entry in the dependency manifest, related resolved entries
in the lockfile, src/export-orders.js, and its focused tests.
Use the repository's existing dependency manager and update procedure.
Preserve EXPORT-4:
Return a string. Columns order_id,customer_name, in that order.
CRLF after every record including the header. Preserve comma/quote
escaping. Empty input returns the header plus CRLF. Inputs in scope
contain both required string fields.
Checks:
Ordinary record, comma-containing value, embedded quote, empty list,
return type, exact line endings, and the repository's relevant checks.
Compare expected bytes/characters, not only a visual file preview.
Do not upgrade unrelated packages, change the public wrapper signature,
replace the test framework, regenerate unrelated files, or broaden
the input contract. If the target cannot satisfy EXPORT-4 within this
scope, stop at an explanation and a proposed alternative.
Return:
Before/after graph; changed callers; migration diff; commands actually
run and results; unrun checks with reasons; unresolved compatibility
questions; and a rollback note identifying the exact upgrade changes.
Replace the fictional package names, paths, requirement, and versions when adapting the brief. If the real task addresses a security advisory, include that advisory's current official source and the actual affected range; this example supplies no security conclusion.
Define stop and rollback conditions before accepting
Stop the proposed upgrade if its runtime requirements are unresolved, if the dependency manager changes unrelated packages without explanation, or if the target cannot preserve a required output. These are reasons to investigate; they do not automatically justify changing the application's contract.
If an implemented upgrade changes the return type, separators, escaping, or empty-input behavior against the requirement, keep it out of the accepted version until corrected. To reverse the upgrade, restore its specific manifest, lockfile, wrapper, and test changes together from the known pre-upgrade version. Preserve unrelated work, and resolve overlapping edits rather than resetting an entire shared checkout. If the change has already been released, use the project's release rollback procedure as well; local file restoration does not reverse a deployment.
Dependency resolution, focused compatibility checks, and release validation should each have their own result. “Lockfile updated” answers only one part of the request.
When sending this brief through CueSpec, use check the intended conversation for the routing step. Keep the graph, target notes, and application contract with the coding task itself.