Workspaces
A workspace is a named draft of the store design (ADR 0027 §3). The builder's own draft is the workspace main; every agent and developer workspace is a separate row beside it — same bundle format, same validation, different identity. Design work by agents happens only in their own workspace: an Ajan token is bound to exactly one, and a write to main is refused with 403 agent_workspace_only.
The draft model
workspaces.list— every workspace with its kind, status, draft rev and sandbox state.workspaces.create— creates one; for kindagentit also mints the bound Ajan token (returned once). At mostworkspacesPerStoreper store; idle workspaces archive afterworkspaceIdleArchiveDaysdays.- Every draft route takes
?workspace=(defaultmain):design.draft.get,design.draft.put,design.draft.delete,design.draftFromTemplate.
Draft writes are whole-draft compare-and-swap: PUT carries expectedRev, and a mismatch is HTTP 409 with the current state in the body — {rev, hash, updatedAt, updatedBy}. On 409, re-read the draft, redo your edit on top of the new body, and PUT again with the new rev. The server never merges — there is no three-way merge endpoint, no "force" flag, and a lost race is always resolved client-side. Through the CLI the same contract surfaces as push exiting 4 on conflict.
Workspace writes carry the workspace agent policy: they execute directly for every token kind — no proposal is recorded — because a workspace draft changes nothing live. The proposal boundary sits at publish, not at draft edits.
Stable preview URL
design.previewUrl.get with ?workspace=ws_… returns a signed link that follows the workspace's current draft — push again and the same URL shows the new state (a lightweight poll reloads the open tab). With ?hash= instead, the link freezes one snapshot. Hand the workspace link to the owner once; it stays valid as you iterate. CLI: preview, or dev to watch, push on change and print it.
Builder always wins
The acceptance rule is literal: *builder open + agent edit + builder save = no data loss.* It holds structurally on the agent path — your workspace and the builder's main are different rows, so you can never overwrite an owner's unsaved work, and the owner's edits never appear in your draft mid-flight. Developer tokens writing main share the builder's CAS: on a 409 the builder rebases its own unsaved edits onto the new rev client-side; your job on a 409 is the same — rebase your edit, never expect the server to reconcile.
Adopt is owner-side ("Taslağa al")
Getting workspace work into the builder's draft is the owner's click, not your call: workspaces.adopt (POST /v1/workspaces/{ws}/adopt) copies the workspace body into main under expectedMainRev CAS — a copy, never a merge; the builder's unsaved state guards itself with the rev check. The owner does this from the panel after looking at your preview. From there, publishing to the live store is a separate owner decision (design.publish — owner policy; an agent's publish intent travels as a proposal design item, which re-checks the workspace hash and the live sequence before running).
Deleting your draft (design.draft.delete) also takes expectedRev — the same CAS discipline applies to discarding as to writing.