Branching Merging
Tools for isolating an experiment from a session’s main line, and later reconciling it — either by promoting it back in, or discarding it.
create_branch
Section titled “create_branch”Forks a new session from an existing one, either from its current state or from a specific historical version.
Parameters: session_id (required, parent), version_id (optional —
fork from this historical version instead of current state).
Tip: pass
version_idwhen you intend tomerge_branchthe result back later. It records the exact fork point as the branch’sparent_version_id, whichmerge_branchuses automatically as its merge base. Without it,merge_branchneeds an explicitbase_version_id.
Response
{ "session_id": "sess-branch-1", "parent_session_id": "sess-abc123", "parent_version_id": "v-2", "message": "Branch session sess-branch-1 created from parent sess-abc123."}merge_branch
Section titled “merge_branch”Session-aware three-way merge: merges a branch’s changes into a target
session. Unlike merge_knowledge, the merge base is resolved automatically
from the branch’s recorded fork point — you never supply it yourself
(unless the branch wasn’t created via create_branch’s version_id, in
which case pass base_version_id).
Parameters
| Name | Required | Description |
|---|---|---|
target_session_id |
yes | Session to merge into. |
source_session_id |
yes | Branch session being merged in. |
base_version_id |
no | Override the automatic merge base. |
resolutions |
no | Per-object conflict resolutions (see below). |
On success, commits the merge as a new version of the target:
{"merged": true, "serialized": "<canonical JSON>", "session_id": "sess-abc123", "version_id": "v-4"}On conflict, nothing is committed — you get a structured report instead:
{ "merged": false, "message": "Merge conflict detected. For each entry in 'conflicts' below, ...", "conflicts": [ {"object_id": "obj-1", "target_diff": {...}, "source_diff": {...}} ]}Do not retry merge_branch unchanged after a conflict. Either:
- Retry with a
resolutionsargument, keyed byobject_id, valued"branch_a"(keep target’s version),"branch_b"(keep source’s version),null(drop the object), or a full object definition to synthesize a new value. You can resolve only some conflicts per call — everything else merges normally, and unresolved ids are reported again. - Or apply your resolution directly to the target session with
evolve_knowledge, then retrymerge_branchwith noresolutions.
Either way, close_session the source branch once it’s fully integrated.
Many disjoint-field conflicts (edits to different fields of the same
object) are resolved automatically without ever reaching you — see
ADR-007 in cks-runtime. If that fast path is unavailable in your storage
backend, the response includes a field_level_auto_merge_note explaining why.
merge_knowledge
Section titled “merge_knowledge”The base primitive merge_branch is built on: a three-way merge of three
raw structures — you supply the common ancestor yourself instead of it
being resolved from a session’s history. Use this when you’re not working
with live sessions (e.g. merging two externally-produced structures).
Parameters: json_data_base, json_data_branch_a, json_data_branch_b
(all required), resolutions (optional, same shape as merge_branch).
Response shape mirrors merge_branch: {"merged": true, "serialized": ...}
on success, {"merged": false, "conflicts": [...]} on conflict. A
dropped_relations field appears when a relation was dropped because one
of its participants didn’t survive the merge.
fork_sandbox
Section titled “fork_sandbox”The “what-if” tool: forks an isolated branch, optionally applies a
hypothesis (an operations list) to it immediately, and reports the diff
from the fork point — all without ever touching the parent session. Safe to
throw away.
Parameters
| Name | Required | Description |
|---|---|---|
session_id |
yes | Parent session to fork from. |
version_id |
no | Fork from this historical version instead of current state. |
hypothesis |
no | Short description, echoed back for logging. |
operations |
no | Evolution operations to apply immediately in the sandbox. |
Response
{ "sandbox_session_id": "sess-sandbox-1", "parent_session_id": "sess-abc123", "fork_version_id": "v-2", "operations_applied": 1, "diff_from_fork_point": { "summary": {"added_objects": 1, "removed_objects": 0, "added_relations": 0, "removed_relations": 0, "renamed_objects": 0}, "operations": [{"type": "add_object", "identity": {...}}] }, "hypothesis": "what if we add a counter-example object", "message": "Sandbox session 'sess-sandbox-1' is an isolated fork of 'sess-abc123'; ..."}If operations fails validation or provenance, the sandbox is closed
automatically and an error is returned — nothing is left dangling. Keep
exploring the sandbox with evolve_knowledge, promote it with
merge_branch once you’re satisfied, or discard it with close_session —
there’s no obligation to merge.
close_session
Section titled “close_session”Releases a session from the runtime. Typical use: after merge_branch
reports success, close the source branch that was just merged in.
Parameters: session_id (required).
Response: {"session_id": "...", "closed": true}.