Integrate Parallel Agent Changes Without Losing File Ownership
Drafted and reviewed using AI assistance.
On this page
Give one role ownership of the combined result, then integrate each delivery against a known baseline and the intended behavior. Two branches can each satisfy a local check while disagreeing about a shared setting. The useful question is whether their combined code and configuration implement the same feature.
The fictional example below contains two module changes and competing edits to one configuration file. All patches are original teaching proposals; no repository merge or application run is being reported.
Establish the shared baseline
A search feature should be enabled, start after two characters and show the number of matching items. The input is a list of items with string titles. Matching remains case-sensitive in this small example; ranking and language-aware matching are outside the change.
Baseline search-config.json:
{
"enabled": false,
"minChars": 3,
"showCount": false
}
Baseline search-items.js:
export function searchItems(items, text, config) {
if (!config.enabled) return [];
return items.filter(item => item.title.includes(text));
}
Baseline search-view.js:
export function describeResults(matches, config) {
return "Search";
}
Call this illustrative snapshot BASE-SEARCH-v1. In a real delivery, record the actual base revision and exact patch references instead of relying on a branch name alone.
Read the two proposals
The matcher worker proposes enabling search and adding the two-character check:
--- a/search-config.json
+++ b/search-config.json
@@ -1,5 +1,5 @@
{
- "enabled": false,
- "minChars": 3,
+ "enabled": true,
+ "minChars": 2,
"showCount": false
}
--- a/search-items.js
+++ b/search-items.js
@@ -1,4 +1,4 @@
export function searchItems(items, text, config) {
- if (!config.enabled) return [];
+ if (!config.enabled || text.length < config.minChars) return [];
return items.filter(item => item.title.includes(text));
}
The view worker proposes the count label, but also suggests a one-character threshold in the shared configuration:
--- a/search-config.json
+++ b/search-config.json
@@ -1,5 +1,5 @@
{
"enabled": false,
- "minChars": 3,
- "showCount": false
+ "minChars": 1,
+ "showCount": true
}
--- a/search-view.js
+++ b/search-view.js
@@ -1,3 +1,3 @@
export function describeResults(matches, config) {
- return "Search";
+ return config.showCount ? `Search (${matches.length})` : "Search";
}
A module-level check of describeResults could use a prepared list of matches without ever exercising the matcher. That would not resolve the threshold disagreement or show that the combined feature is enabled.
Git's merge documentation describes combining changes relative to their ancestor and resolving conflicting edits. A textual merge does not choose the product policy for you. Here, the decision is explicit: the requested threshold is two characters.
Assign the shared surface to one integrator
| File or decision | Responsible role | How other workers contribute |
|---|---|---|
search-items.js |
Matcher worker | View worker references its agreed input/output contract |
search-view.js |
View worker | Matcher worker supplies expected result fixtures |
search-config.json |
Integrator | Workers submit setting proposals with reasons |
| Threshold policy | Feature decision owner | Resolve the one-versus-two-character disagreement against the request |
| Combined change and checks | Integrator | Workers help investigate specific combined findings |
If deliveries already contain overlapping edits, treat those hunks as proposals for the integrator. Do not have both workers replace the shared file again while integration is underway.
Make the conflict decision inspectable
| Setting | Baseline | Matcher proposal | View proposal | Combined choice and reason |
|---|---|---|---|---|
enabled |
false | true | unchanged | true: the requested feature must run |
minChars |
3 | 2 | 1 | 2: the stated feature rule |
showCount |
false | unchanged | true | true: the requested count label |
The combined proposed configuration is:
{
"enabled": true,
"minChars": 2,
"showCount": true
}
Take the matcher's threshold condition and the view's count implementation. The final changes relative to the same baseline are in the combined proposal patch; the two original proposals are also available as A and B.
Integrate in a traceable order
- Confirm the base and preserve unrelated working changes with their owner.
- Inspect each exact delivery, separating module edits from shared-file proposals.
- Record the threshold decision before accepting either shared configuration hunk.
- Assemble the two module changes and the selected configuration as one candidate.
- Inspect the full candidate for omitted or unintended changes.
- Check the combined behavior, recording results against that candidate's actual revision.
The order is about understanding dependencies, not a command to merge into a live branch. There is no merge, reset, push or deployment command in this example.
Check the combination
Use these fictional items:
[
{"id": "a", "title": "apple"},
{"id": "b", "title": "apricot"},
{"id": "c", "title": "berry"}
]
| Query/configuration | Expected matcher result | Expected label | Actual result |
|---|---|---|---|
a, combined config |
empty list | Search (0) |
— |
ap, combined config |
IDs a, b, in that order | Search (2) |
— |
zz, combined config |
empty list | Search (0) |
— |
ap, enabled=false |
empty list | Search (0) when described |
— |
ap, showCount=false |
IDs a, b | Search |
— |
These are expected outcomes under the proposed functions. An actual application also needs its caller and UI checked: does it pass the selected config and display the returned state? No application test is filled into this table.
Keep a rollback object, not just a vague intention
Combined candidate reference:
Base revision:
Matcher delivery reference:
View delivery reference:
Shared-setting decisions:
Checks actually performed and their evidence:
Rollback object:
[The combined change or release containing the modules and config together.]
State to preserve:
[Unrelated work and any separate data/schema effects.]
Return-to-baseline check:
[What must match again after the chosen rollback procedure?]
For this example, code and configuration belong together. Restoring only the old config could disable the feature while leaving both new modules in place; keeping only one worker's config could lose the other requested behavior. The actual rollback procedure depends on your repository and release state, so identify the candidate before taking action.
A clear integration record tells the next reviewer what came from each delivery, why shared decisions were made and which combination was checked. That is a stronger handoff than forwarding two independent “finished” messages.