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

  1. Confirm the base and preserve unrelated working changes with their owner.
  2. Inspect each exact delivery, separating module edits from shared-file proposals.
  3. Record the threshold decision before accepting either shared configuration hunk.
  4. Assemble the two module changes and the selected configuration as one candidate.
  5. Inspect the full candidate for omitted or unintended changes.
  6. 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.