English
Conflict Resolution
Conflict Resolution Strategies

Conflict Resolution Strategies

Understand the strategies PuppyOne uses to handle concurrent editing conflicts, and when to use each one.


Three-way merge

Three-way merge is the smartest way to handle concurrent edits. The MUT engine compares three versions to decide how to merge:

        Base version
       ┌──────┴──────┐
       │             │
   Changes from A  Changes from B
    (Agent A)       (Agent B)
       │             │
       └──────┬──────┘

        Merged result

Workflow

  1. Agent A and Agent B both read the file at version v3
  2. Agent A writes first (with base_version: 3), creating v4
  3. When Agent B writes (with base_version: 3), the MUT engine detects the version mismatch
  4. The engine compares Base (v3), current (v4), and Agent B's incoming changes
  5. Non-conflicting parts are merged automatically, and conflicting parts are flagged

When auto-merge succeeds

If the two actors changed different parts of the file, the system can merge automatically:

// Base version (v3)
{
  "title": "API Design Document",
  "author": "Alice",
  "status": "draft"
}
 
// Agent A changed author (now v4)
{
  "title": "API Design Document",
  "author": "Alice & Bob",
  "status": "draft"
}
 
// Agent B's incoming write (base_version: 3) changes status
{
  "title": "API Design Document",
  "author": "Alice",
  "status": "review"
}
 
// Auto-merged result (v5) — both changes are kept
{
  "title": "API Design Document",
  "author": "Alice & Bob",
  "status": "review"
}

When merge conflicts happen

If both actors change the same part of the file, the system cannot choose automatically:

// Base version
{ "price": 99 }
 
// Agent A changes price to 89 (now current version)
{ "price": 89 }
 
// Agent B changes price to 79 (incoming write with base_version)
{ "price": 79 }
 
// Conflict! The system cannot merge automatically and needs human input

At that point, the write returns conflict information containing both versions so you can decide what to keep.


Last-write-wins

The simplest and most direct strategy: the later write overwrites the earlier one without merging. This is the default when base_version is not provided.

Timeline:
  t1: Agent A writes content "Version A"
  t2: Agent B writes content "Version B"  (t2 > t1)

Result: final content becomes "Version B"
        "Version A" is automatically preserved in commit history

Common use cases

  • Filesystem sync: this is the default for syncing local folders with the cloud. A local file update is pushed directly to the cloud and overwrites the current version
  • External data source sync: when pulling from Notion, GitHub, and similar sources, the newest external content overwrites old data directly
  • Workloads that need real-time behavior and have low conflict probability

Safety net

Even though the strategy is simple, data is not lost:

  • Before each overwrite, the current version is automatically saved in commit history
  • You can inspect history and roll back anytime
# View the version history of a file
curl -X GET "https://api.puppyone.ai/api/v1/content/{project_id}/versions?path=/data/config.json" \
  -H "Authorization: Bearer {token}"
 
# Roll back to a specific version
curl -X POST "https://api.puppyone.ai/api/v1/content/{project_id}/rollback" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/data/config.json", "version": 3}'

Manual conflict resolution

When three-way merge cannot resolve a conflict automatically, the system returns conflict details and you decide how to proceed.

Example conflict response

{
  "status": "conflict",
  "base_version": 3,
  "current_version": 4,
  "conflicts": [
    {
      "path": "/price",
      "base_value": 99,
      "current_value": 89,
      "incoming_value": 79
    }
  ]
}

Resolution options

You can choose to:

  1. Keep the current version - ignore the incoming change
  2. Force overwrite - resubmit without base_version to use last-write-wins
  3. Merge manually - combine both changes yourself and submit a new write with the current base_version

Best practices

Use base_version for critical data

For business-critical data that cannot tolerate silent overwrites, always include base_version in your write requests:

curl -X POST "https://api.puppyone.ai/api/v1/content/{project_id}/write" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "path": "/specs/pricing.json",
    "content": "{\"price\": 99}",
    "base_version": 5
  }'

Reduce conflicts with path permissions

Use path permissions to assign different working areas to different agents so they do not write to the same files in the first place:

# Agent A can only write to /specs
Agent A:
  paths: ["/specs"]
 
# Agent B can only write to /docs
Agent B:
  paths: ["/docs"]

Each agent stays in its own area, so they do not conflict.

Rely on commit history as a safety net

No matter which strategy you use, commit history preserves every change. Even if something is overwritten unexpectedly, you can always roll back.

Watch the audit log

Review the audit log regularly to understand which agents are modifying which files and to catch abnormal concurrent-editing patterns early:

curl -X GET "https://api.puppyone.ai/api/v1/nodes/{path}/audit-logs" \
  -H "Authorization: Bearer {token}"

Next steps