# Share files safely between autonomous writers

Your tools already know how to read and write files. syncroot can give them the
same folder on several trusted devices without adding another storage API. The
rules below help each writer stay in its lane and avoid assumptions that folder
sync cannot guarantee.

## What an agent can rely on

syncroot replicates one folder directly between peer devices on an existing
trusted network. A file becomes readable only after all of its chunks arrive and its
content hash matches, so an agent never opens a partially transferred file.
Each device orders its own changes, and every peer records how far it has caught
up with every other peer.

| You can rely on | What that means for your workflow |
| --- | --- |
| Complete publication | A path resolves to complete, hash-verified content, or does not resolve yet. |
| Attributable writes | Every change records the device that made it. |
| Per-peer sequence | Each peer's changes are ordered and its progress is readable. |
| Content addressing | Chunks are named by hash. |
| Eventual convergence | Connected devices converge, but there is no latency bound. |

## What an agent must not assume

1. **A missing file does not claim a task.** Two agents can both see that a
   result is absent and start the same work. When a task needs exactly one
   owner, claim it in a coordination store with compare-and-swap. Do not build
   locks from synchronized files.
2. **Separate paths may arrive in either order.** Writing an artifact and then a
   marker does not guarantee that another device sees the artifact first.
3. **syncroot keeps conflicts; it does not understand them.** Concurrent
   versions receive deterministic names, but syncroot cannot decide which edit
   is correct. Avoid shared write paths instead of asking agents to merge
   surprises later.
4. **There is no delivery deadline.** A device can stay offline indefinitely.
   Missing now does not mean never written.
5. **Every member can write everywhere.** There are no per-path permissions.
6. **The folder is already inside the trust boundary.** syncroot cannot isolate
   other devices from a compromised agent.
7. **Sync is not backup.** Deletes propagate to every device.

## Give every writer its own subtree

```text
~/shared/
├── plan.md                  # human-owned; agents read only
├── inputs/                  # human-owned; agents read only
└── agents/
    ├── planner/
    │   ├── journal.d/       # one write-once file per entry
    │   └── out/
    │       └── 01J8F…-plan.md
    └── scraper/
        ├── journal.d/
        └── out/
            └── 01J8F…-rows.json
```

- **Write only in your subtree.** An agent owns `agents/<agent-id>/` and treats
  every other path, including other agents' subtrees, as read-only.
- **Create a new name for every result.** Include a ULID or content hash. A new
  version is a new file; do not overwrite or rename in place.
- **Use a directory as the journal.** Write `journal.d/<ulid>.md`, one entry per
  file. Appending to one shared file creates a read-modify-write conflict.
- **Delete only in your subtree.** Cleanup elsewhere can remove another
  writer's input from every device.

## Make completion markers verify themselves

A marker and its artifact are separate paths and may arrive in either order.
Include enough information for a reader to identify the exact complete
artifact:

```json
{
  "task": "scrape-index",
  "agent": "scraper",
  "finished_at": "2026-07-28T09:14:22Z",
  "artifact": "agents/scraper/out/01J8F…-rows.json",
  "bytes": 148223,
  "sha256": "9f2c…"
}
```

If the artifact has not arrived, wait. If its size or hash differs, the visible
file is another complete version—not a partial transfer—and must not be consumed
as the artifact named by this marker.

## Check freshness before interpreting absence

Pass the root explicitly in automation:

```bash
syncroot status ~/shared --json
syncroot doctor ~/shared --json
```

`status` reports live progress for each peer when the daemon is available and
last-known state otherwise. `doctor` exits nonzero when a check fails, so it can
serve as a precondition. If the runtime heartbeat is stale, the daemon stopped
uncleanly; wait for recovery before treating the local tree as current.

Do not turn one `ENOENT` into “the work failed.” First inspect the producing
peer in `status --json`. If that device is unreachable or behind, your local
folder may simply be stale.

## A safe agent loop

```text
1. doctor --json        → stop and report if checks fail
2. status --json        → record how current each peer is
3. read inputs and plan → only from paths you do not own
4. claim the work       → in a coordination store, not this folder
5. write once           → under your own subtree
6. write a marker       → include path, byte length, and hash
7. journal              → record what you did and what you read
```

## Before you rely on it

syncroot is pre-launch. Formats may change without migration. Run the same build
on every device, evaluate it with disposable data, and keep a backup. Files
larger than 20 MiB are currently ignored.
