apache / apache/maka

feat(cloud): fork Cloud Sessions at committed revisions

Open
#1,415 3 comments 0 reactions 1 assignee Claimed by @MicroGery View on GitHub
enhancement
Dominant language
TypeScript
Stars
5.4k
Forks
502
Avg merge
1d 2h
Merged PRs (30d)
715

Description

Split from @MicroGery's proposal in #1286 ([#issuecomment-5059344338](https://github.com/maka-agent/maka-agent/issues/1286#issuecomment-5059344338)). Parent RFC: #1286.

## Motivation

A portable bundle makes fork a control-plane/repository operation, with no dependency on OpenSandbox or `maka activate`. Besides user-driven duplication of a session, it enables **template sessions**: warm one base session (workspace set up, dependencies installed, initial context established), then fork per user/session. Every fork starts from the same conversation prefix, so provider prompt caches keep hitting, and inherits a warm workspace, so setup does not rerun per session.

## Definition

Create a new Cloud Session from the complete bundle of one committed source revision; source and target then evolve independently. The target keeps the same `agentId`, receives a new `sessionId`, and starts its own revision/CAS sequence. This is a **Cloud Session fork**, not a sandbox fork or an agent-definition fork.

## Contract

```ts
type SessionRevisionRef = { sessionId: string; revision: string };

type ForkSessionRequest = {
forkId: string; // idempotency key
source: SessionRevisionRef;
targetSessionId: string;
};

type ForkSessionResult = {
target: SessionRevisionRef;
forkedFrom: SessionRevisionRef;
};
```

- `source.revision` is required and never defaults to "latest". This closes the race where the source advances between the decision to fork and the operation.
- The target's first revision is a new revision in the target session; it must not reuse the source revision as its CAS token.
- Lineage lives in control-plane session metadata as `forkedFrom: { sessionId, revision }` (a revision is only unique within its session). It stays separate from Maka's conversation-level `parentSessionId` / `branchOfTurnId`: `branchFromTurn` branches conversation history at a turn boundary, while a Cloud Session fork copies the complete committed snapshot including runtime state, artifacts, and workspace files. Do not overload the Maka lineage fields.

## MVP boundary

- Fork only an explicitly named current committed revision; if the head has moved, fail `source_revision_not_available`. Never silently fork a newer revision.
- A fork does not acquire the source session's write lease: read the exact committed revision, verify it is forkable, create the target with create-if-absent, and persist `forkId -> targetSessionId` so retries return the same target. The source is never modified.
- Only **quiescent** revisions are forkable: reject a revision with a pending approval or another externally resumable action until action identities are re-keyed for the target session.

## Copied vs not copied

Copied: conversation and runtime history, durable Maka state, artifacts, workspace files.

Never copied (control-plane execution state): active leases, sandbox identity, queued/running activation records, activation dedupe entries, scheduler registrations, injected credentials or connection configuration, temporary activation input, logs. Activation dedupe stays scoped by `(sessionId, activationId)` so copied history cannot suppress valid activations in the target.

## Storage

- v1: copy the `tar.zst`, rewrite target-scoped envelope/manifest fields (`sessionId`, `makaSessionId`, `lastActivationId`), reset activation dedupe state, record `forkedFrom`. Two session heads must **not** point at the exact same bundle value.
- The semantic contract must not depend on physical copy. Once revision retention and the envelope/payload manifest seam (see #1286, Session bundle section) exist, both heads may share immutable payload blobs with copy-on-write, which then requires reachability/refcount-aware GC.
- Within-session revision history stays a linear CAS sequence in v1. Per-revision metadata (for example, which activation produced a revision) arrives with retention; v1 records lineage only at fork boundaries.

## Out of scope

Arbitrary historical-revision forks (needs retention); mapping in-bundle conversation branching (`/rewind`, `branchBeforeTurn`) onto cloud sessions; copy-on-write storage and GC; re-keying pending-approval action identities.

## Validation

1. Source and target diverge after the fork.
2. A source-head race never forks an unintended revision.
3. Retrying the same `forkId` creates exactly one target.
4. Target CAS conflicts do not affect the source.
5. Deleting the source does not invalidate the target.
6. Credentials, activation records, leases, and schedules are not copied.
7. A non-quiescent or pending-approval revision is rejected.
8. (When copy-on-write lands) shared bundle data is not collected while either session references it.

## Dependencies

#1338 (state/config root split) and the Session Bundle import/export contract tracked in #1286. No dependency on OpenSandbox or `maka activate`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.