Move Stream

The stream an agent moves in, as every end of it reads and writes it: lnk agent state-send and receive, a cloud that hosts agents (agent-take, agent-give), and lnk bucket for such an agent's Home (link_agent_contract::moving, format 4).

The stream

A tar whose first entry is lnk-move-4.json, the manifest, and whose last is the empty lnk-move-4.end: a stream without it was cut short, and is refused. Both ends must speak format 4, whatever their versions.

Each file's hash

Every file comes after a PAX header LNK.sha256, its SHA-256 in hex: a receiver hashes what it writes and refuses the stream when one differs or has none.

What it may hold

Only files, folders and links, each a plain path under a folder its phase allows (files/, memory/, harness/, connections/). files/ is the agent's folder as the agent sees it, and memory/<engine>/ its memory engine's index.

The manifest

{"format": 4, "phase", "move", "removed"?, "version", "agent": {"id", "name", "owner"?}, "harness", ...}; the rest of it is the sender's to say (Interface).

phase

copy, switch or files: a copy while the agent may run, the switch that puts it in place, or Home alone, for an agent a cloud account hosts.

move

The move's ID, 128 random bits in hex, the same in its copy and its switch, so a receiver refuses a switch of another move than its copy.

removed

In a switch, the paths of files/ and memory/ the other end holds that are gone, which the receiver takes out.

have

A receiver's have is {"<path>": "<sha256>"}, each file it holds by its path in the stream (files/..., memory/...). A sender skips each it holds the same, so a copy tried again, or a move back to a machine that kept the agent's files, sends only what's new.

Collections

Collections cross through their source and receiver's store contracts (link_agent_contract::moving::collections), including file.

What a receiver replaces

A receiver replaces instructions, skills, notes and scheduled jobs with what the stream holds, and appends the conversations' missing events after checking their shared prefix. Conversation tool narrowing travels with each thread, including one without events. Notes travel at memory/notes.md.

Schedules

A switch also carries schedule/<place>/<id>.json, each the store contract's Job, where place is waiting, firing or ending, and schedule/day.json, the pair [day, sent] from job_day. Schedules are sent only while paused, in full on each switch.

One form

Each event (a line of a conversation's events.jsonl), each job and day.json is compact JSON with every object's keys sorted, at every depth, whatever features the sender was built with: two builds hash the same conversation the same, so a move never resends it for its form.

The sealed envelope

A switch's complete tar payload is a link_secret_value::stream envelope, sealed to the key lnk agent receive printed, with HPKE context {"owner":"move","kind":"stream","version":1}.

Its header

It starts with LNKSEAL1, a big-endian 32-bit HPKE-header length (at most 4096), then that sealed stream key. A stream gets a fresh random 32-byte key.

Its records

Each record has a big-endian 32-bit plaintext length (at most 65536), followed by ciphertext and its 16-byte tag. The nonce is four zero bytes plus a big-endian 64-bit record counter, and the authenticated data is that counter and the plaintext length.

Its end

A zero-length authenticated final record is required; bytes after it are refused. Counter overflow and a failed record write make it unusable.