ce-proof

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Proof - Collaborative Markdown Editor

Proof - 协作式Markdown编辑器

Proof is a collaborative document editor for humans and agents. It supports two modes:
  1. Web API - Create and edit shared documents via HTTP (no install needed)
  2. Local Bridge - Drive the macOS Proof app via localhost:9847
Proof是一款面向人类与Agent的协作文档编辑器,支持两种模式:
  1. Web API - 通过HTTP创建和编辑共享文档(无需安装)
  2. Local Bridge - 通过localhost:9847驱动macOS版Proof应用

Identity and Attribution

身份标识与归属

Every write to a Proof doc must be attributed. Two fields carry the agent's identity:
  • Machine ID (
    by
    on every op,
    X-Agent-Id
    header):
    ai:compound-engineering
    — stable, lowercase-hyphenated, machine-parseable. Appears in marks, events, and the API response.
  • Display name (
    name
    on
    POST /presence
    ):
    Compound Engineering
    — human-readable, shown in Proof's presence chips and comment-author badges.
Set the display name once per doc session by posting to presence with the
X-Agent-Id
header; Proof binds the name to that agent ID for the session. These values are the defaults for any caller of this skill; callers running HITL review (
references/hitl-review.md
) may pass a different
identity
pair if a distinct sub-agent should own the doc. Do not use
ai:compound
or other ad-hoc variants — identity stays uniform unless a caller explicitly overrides it.
对Proof文档的每一次写入操作都必须标注归属。以下两个字段用于传递Agent的身份信息:
  • 机器ID(每个操作的
    by
    字段、
    X-Agent-Id
    请求头):
    ai:compound-engineering
    — 稳定、小写连字符格式、可被机器解析。会显示在标记、事件和API响应中。
  • 显示名称(
    POST /presence
    接口的
    name
    字段):
    Compound Engineering
    — 便于人类阅读,会显示在Proof的在线状态芯片和评论作者徽章中。
在每个文档会话中,只需通过带
X-Agent-Id
请求头的presence接口请求一次即可设置显示名称;Proof会在会话中将该名称与对应的Agent ID绑定。这些值是本技能调用者的默认值;运行HITL审阅(
references/hitl-review.md
)的调用者若希望由不同的子Agent拥有文档,可传入不同的
identity
对。请勿使用
ai:compound
或其他临时变体 — 身份信息保持统一,除非调用者明确覆盖。

Human-in-the-Loop Review Mode

人工参与审阅模式

Human-in-the-loop iteration over an existing local markdown file: upload to Proof, let the user annotate in Proof's web UI, ingest feedback as in-thread replies and tracked edits, and sync the final doc back to disk. Two entry points, identical mechanics — load
references/hitl-review.md
for the full loop spec (invocation contract, mark classification, idempotent ingest passes, exception-based terminal reporting, end-sync atomic write) in either case:
  • Direct user request — a bare user phrase naming a local markdown file and asking to iterate collaboratively via Proof: "share this to proof so we can iterate", "iterate with proof on this doc", "HITL this file with me", "let's get feedback on this in proof", "open this in proof editor so I can review". The file is whichever markdown the user just created, edited, or referenced; if ambiguous, ask which file. This is a first-class entry point — do not require an upstream caller.
  • Upstream skill handoff
    ce-brainstorm
    ,
    ce-ideate
    , or
    ce-plan
    finishes a draft and hands it off for human review before the next phase, passing the file path and title explicitly.
针对现有本地Markdown文件的人工参与迭代流程:上传至Proof,让用户在Proof网页UI中添加注释,将反馈作为线程回复和跟踪式修改导入,最后将最终文档同步回本地磁盘。有两个入口点,机制相同 — 无论哪种情况,都可查看
references/hitl-review.md
获取完整循环规范(调用契约、标记分类、幂等导入流程、基于异常的终端报告、结束同步原子写入):
  • 直接用户请求 — 用户直接提及本地Markdown文件并要求通过Proof进行协作迭代,例如:“把这个分享到Proof以便我们迭代”“用Proof迭代这份文档”“和我一起对这个文件进行HITL审阅”“在Proof中获取这份内容的反馈”“在Proof编辑器中打开这个让我审阅”。文件为用户刚刚创建、编辑或引用的Markdown文件;若存在歧义,需询问具体是哪个文件。这是一级入口点 — 无需上游调用者触发。
  • 上游技能移交
    ce-brainstorm
    ce-ideate
    ce-plan
    完成草稿后,在进入下一阶段前将其移交进行人工审阅,并明确传递文件路径和标题。

Web API (Primary for Sharing)

Web API(主要用于分享)

Create a Shared Document

创建共享文档

No authentication required. Returns a shareable URL with access token.
bash
curl -X POST https://www.proofeditor.ai/share/markdown \
  -H "Content-Type: application/json" \
  -d '{"title":"My Doc","markdown":"# Hello\n\nContent here."}'
Response format:
json
{
  "slug": "abc123",
  "tokenUrl": "https://www.proofeditor.ai/d/abc123?token=xxx",
  "accessToken": "xxx",
  "ownerSecret": "yyy",
  "_links": {
    "state": "https://www.proofeditor.ai/api/agent/abc123/state",
    "ops": "https://www.proofeditor.ai/api/agent/abc123/ops"
  }
}
Use the
tokenUrl
as the shareable link. The
_links
give you the exact API paths.
无需身份验证。返回带访问令牌的可分享URL。
bash
curl -X POST https://www.proofeditor.ai/share/markdown \
  -H "Content-Type: application/json" \
  -d '{"title":"My Doc","markdown":"# Hello\n\nContent here."}'
响应格式:
json
{
  "slug": "abc123",
  "tokenUrl": "https://www.proofeditor.ai/d/abc123?token=xxx",
  "accessToken": "xxx",
  "ownerSecret": "yyy",
  "_links": {
    "state": "https://www.proofeditor.ai/api/agent/abc123/state",
    "ops": "https://www.proofeditor.ai/api/agent/abc123/ops"
  }
}
使用
tokenUrl
作为可分享链接。
_links
字段提供了准确的API路径。

Read a Shared Document

读取共享文档

bash
curl -s "https://www.proofeditor.ai/api/agent/{slug}/state" \
  -H "x-share-token: <token>"
bash
curl -s "https://www.proofeditor.ai/api/agent/{slug}/state" \
  -H "x-share-token: <token>"

Edit a Shared Document

编辑共享文档

All operations go to
POST https://www.proofeditor.ai/api/agent/{slug}/ops
Note: Use the
/api/agent/{slug}/ops
path (from
_links
in create response), NOT
/api/documents/{slug}/ops
.
Authentication for protected docs:
  • Header:
    x-share-token: <token>
    or
    Authorization: Bearer <token>
  • Token comes from the URL parameter:
    ?token=xxx
    or the
    accessToken
    from create response
  • Header:
    X-Agent-Id: ai:compound-engineering
    (required for presence; include on ops for consistent attribution)
Wire-format reminder.
/api/agent/{slug}/ops
uses a top-level
type
field;
/api/agent/{slug}/edit/v2
uses an
operations
array where each entry has
op
. Do not mix — sending
op
to
/ops
returns 422.
Every mutation requires a
baseToken
.
Reuse the
mutationBase.token
from the most recent
/state
or
/snapshot
read — tokens don't go stale in seconds, and
STALE_BASE
is a recoverable error. On
BASE_TOKEN_REQUIRED
or
STALE_BASE
, re-read and retry once. Only do a pre-mutation read if no prior read has happened in this session. See the baseToken recipe in
references/hitl-review.md
.
/edit/v2
block refs are a separate concern: they can drift across revisions, so re-fetch
/snapshot
for fresh refs before a block edit if any writes have landed since your last snapshot.
Retry discipline after mutation errors — verify before retrying. An error response is not proof that nothing was written.
  • STALE_BASE
    ,
    BASE_TOKEN_REQUIRED
    ,
    MISSING_BASE
    ,
    INVALID_BASE_TOKEN
    — pre-commit, token-related. Re-read
    /state
    and retry once with the same payload and a fresh
    baseToken
    . A generic mutate helper can auto-retry these.
  • ANCHOR_NOT_FOUND
    ,
    ANCHOR_AMBIGUOUS
    — pre-commit, but the
    quote
    no longer uniquely matches content. Re-reading does not help by itself; the caller must tighten or regenerate the anchor before retrying. Do not auto-retry blindly.
  • INVALID_OPERATIONS
    ,
    INVALID_REQUEST
    ,
    INVALID_REF
    ,
    INVALID_BLOCK_MARKDOWN
    ,
    INVALID_RANGE
    ,
    INVALID_MARKDOWN
    , 422 — pre-commit, but the payload is wrong. Do not retry blindly; fix the payload first.
  • COLLAB_SYNC_FAILED
    ,
    REWRITE_BARRIER_FAILED
    ,
    PROJECTION_STALE
    ,
    INTERNAL_ERROR
    , 5xx, network timeout, and any 202 with
    collab.status: "pending"
    — the canonical doc may have been written even though the call looks like a failure. Before any retry, re-read
    /state
    and check whether the intended mark/edit is already present; only retry if it isn't.
  • Idempotency-Key
    (see below) protects against double-apply on the same request (e.g., TCP-level retry). It does not help if you build a new request body and send a second call — that is a new logical write with a new key.
Duplicate-mark incidents usually come from retrying a
comment.add
or
suggestion.add
after a timeout without verifying. When in doubt: re-read, diff, then decide.
Idempotency-Key
header
is recommended on every mutation for safe automation retries; required when
/state.contract.idempotencyRequired
is true. Use the same key when retrying the exact same logical write (same payload) so the server can collapse the retry. A new key means a new write — even if the payload is identical.
Comment on text:
json
{"type": "comment.add", "quote": "text to comment on", "by": "ai:compound-engineering", "text": "Your comment here", "baseToken": "<token>"}
Reply to a comment:
json
{"type": "comment.reply", "markId": "<id>", "by": "ai:compound-engineering", "text": "Reply text", "baseToken": "<token>"}
Resolve / unresolve a comment:
json
{"type": "comment.resolve", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
{"type": "comment.unresolve", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
Suggest a replacement (pending — user must accept/reject):
json
{"type": "suggestion.add", "kind": "replace", "quote": "original text", "by": "ai:compound-engineering", "content": "replacement text", "baseToken": "<token>"}
Suggest and immediately apply (tracked but committed — user can reject to revert):
json
{"type": "suggestion.add", "kind": "replace", "quote": "original text", "by": "ai:compound-engineering", "content": "replacement text", "status": "accepted", "baseToken": "<token>"}
status: "accepted"
creates the suggestion mark and commits the change in one call. The mark persists as an audit trail with per-edit attribution and a reject-to-revert affordance. Works with
kind: "insert" | "delete" | "replace"
.
Accept or reject an existing suggestion:
json
{"type": "suggestion.accept", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
{"type": "suggestion.reject", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
suggestion.resolve
is not supported — use accept or reject instead.
Bulk rewrite (whole-doc replacement):
json
{"type": "rewrite.apply", "content": "full new markdown", "by": "ai:compound-engineering", "baseToken": "<token>"}
Block-level edits via
/edit/v2
(separate endpoint, separate shape):
bash
curl -X POST "https://www.proofeditor.ai/api/agent/{slug}/edit/v2" \
  -H "Content-Type: application/json" \
  -H "x-share-token: <token>" \
  -H "X-Agent-Id: ai:compound-engineering" \
  -H "Idempotency-Key: <uuid>" \
  -d '{
    "by": "ai:compound-engineering",
    "baseToken": "mt1:<token>",
    "operations": [
      {"op": "replace_block", "ref": "b3", "block": {"markdown": "Updated paragraph."}},
      {"op": "insert_after", "ref": "b3", "blocks": [{"markdown": "## New section"}]}
    ]
  }'
Per-op body shape (singular
block
vs plural
blocks
is load-bearing — sending the wrong one returns 422):
opbody fields
replace_block
ref
,
block: {markdown}
insert_after
ref
,
blocks: [{markdown}, ...]
insert_before
ref
,
blocks: [{markdown}, ...]
delete_block
ref
replace_range
fromRef
,
toRef
,
blocks: [{markdown}, ...]
find_replace_in_block
ref
,
find
,
replace
,
occurrence: "first" | "all"
Read
/snapshot
to get stable block
ref
IDs.
operations
commits atomically — either every op lands or none do — so one
/edit/v2
call can batch dozens of block edits safely and efficiently (see the bulk-sweep guidance in
references/hitl-review.md
Phase 2.4).
Editing while a client is connected is fine.
/edit/v2
,
suggestion.add
(including
status: "accepted"
), and all comment ops work during active collab. Only
rewrite.apply
is blocked by
LIVE_CLIENTS_PRESENT
— it would clobber in-flight Yjs edits.
When the loop breaks. If a mutation keeps failing after a fresh read and one retry, or state across reads looks inconsistent, call
POST https://www.proofeditor.ai/api/bridge/report_bug
with the failing request ID, slug, and raw response. The server enriches and files an issue.
所有操作都需发送至
POST https://www.proofeditor.ai/api/agent/{slug}/ops
注意: 使用创建响应中
_links
字段提供的
/api/agent/{slug}/ops
路径,而非
/api/documents/{slug}/ops
受保护文档的身份验证:
  • 请求头:
    x-share-token: <token>
    Authorization: Bearer <token>
  • 令牌来自URL参数:
    ?token=xxx
    或创建响应中的
    accessToken
  • 请求头:
    X-Agent-Id: ai:compound-engineering
    (在线状态接口必填;为保持归属一致,建议在操作接口中也包含)
格式提醒。
/api/agent/{slug}/ops
使用顶层
type
字段;
/api/agent/{slug}/edit/v2
使用
operations
数组,其中每个条目包含
op
字段。请勿混淆 — 向
/ops
发送
op
字段会返回422错误。
每次修改都需要
baseToken
复用最近一次
/state
/snapshot
读取返回的
mutationBase.token
— 令牌不会在几秒内过期,
STALE_BASE
是可恢复错误。遇到
BASE_TOKEN_REQUIRED
STALE_BASE
错误时,重新读取并重试一次。仅当会话中尚未进行过读取操作时,才需在修改前进行读取。请查看
references/hitl-review.md
中的baseToken使用说明。
/edit/v2
的块引用是另一个需要注意的点:它们可能在不同版本间偏移,因此如果自上次快照后有写入操作,在进行块编辑前需重新获取
/snapshot
以获取最新引用。
修改错误后的重试规则 — 重试前需验证。 错误响应并不代表写入操作一定未执行。
  • STALE_BASE
    BASE_TOKEN_REQUIRED
    MISSING_BASE
    INVALID_BASE_TOKEN
    — 提交前的令牌相关错误。重新读取
    /state
    并使用相同负载和新的
    baseToken
    重试一次。通用修改助手可自动重试这些错误。
  • ANCHOR_NOT_FOUND
    ANCHOR_AMBIGUOUS
    — 提交前错误,但
    quote
    不再唯一匹配内容。仅重新读取无济于事;调用者必须收紧或重新生成锚点后再重试。请勿盲目自动重试。
  • INVALID_OPERATIONS
    INVALID_REQUEST
    INVALID_REF
    INVALID_BLOCK_MARKDOWN
    INVALID_RANGE
    INVALID_MARKDOWN
    、422错误 — 提交前错误,但负载格式有误。请勿盲目重试;需先修复负载。
  • COLLAB_SYNC_FAILED
    REWRITE_BARRIER_FAILED
    PROJECTION_STALE
    INTERNAL_ERROR
    、5xx错误、网络超时,以及任何**返回202且
    collab.status: "pending"
    **的情况 — 即使调用看似失败,标准文档可能已被写入。重试前,重新读取
    /state
    并检查预期的标记/修改是否已存在;仅当不存在时才重试。
  • Idempotency-Key
    (见下文)可防止同一请求被重复执行(例如TCP层面的重试)。如果构建新的请求体并发送第二次调用,这属于新的逻辑写入,需要新的键,此时该字段无法提供帮助。
重复标记事件通常是由于超时后未验证就重试
comment.add
suggestion.add
操作导致的。如有疑问:重新读取、对比差异,再做决定。
Idempotency-Key
请求头
建议在每次修改操作中使用,以实现安全的自动化重试;当
/state.contract.idempotencyRequired
为true时为必填项。重试完全相同的逻辑写入(相同负载)时使用相同的键,以便服务器合并重试请求。即使负载相同,使用新键也意味着新的写入操作。
对文本添加评论:
json
{"type": "comment.add", "quote": "text to comment on", "by": "ai:compound-engineering", "text": "Your comment here", "baseToken": "<token>"}
回复评论:
json
{"type": "comment.reply", "markId": "<id>", "by": "ai:compound-engineering", "text": "Reply text", "baseToken": "<token>"}
标记评论为已解决/未解决:
json
{"type": "comment.resolve", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
{"type": "comment.unresolve", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
建议替换内容(待用户接受/拒绝):
json
{"type": "suggestion.add", "kind": "replace", "quote": "original text", "by": "ai:compound-engineering", "content": "replacement text", "baseToken": "<token>"}
建议替换并立即应用(已跟踪且已提交 — 用户可拒绝以回滚):
json
{"type": "suggestion.add", "kind": "replace", "quote": "original text", "by": "ai:compound-engineering", "content": "replacement text", "status": "accepted", "baseToken": "<token>"}
status: "accepted"
会在一次调用中创建建议标记并提交修改。标记会作为审计轨迹保留,包含每次修改的归属信息和拒绝回滚功能。适用于
kind: "insert" | "delete" | "replace"
接受或拒绝现有建议:
json
{"type": "suggestion.accept", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
{"type": "suggestion.reject", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
不支持
suggestion.resolve
— 请使用accept或reject替代。
批量重写(替换整个文档):
json
{"type": "rewrite.apply", "content": "full new markdown", "by": "ai:compound-engineering", "baseToken": "<token>"}
通过
/edit/v2
进行块级编辑
(独立端点,独立格式):
bash
curl -X POST "https://www.proofeditor.ai/api/agent/{slug}/edit/v2" \
  -H "Content-Type: application/json" \
  -H "x-share-token: <token>" \
  -H "X-Agent-Id: ai:compound-engineering" \
  -H "Idempotency-Key: <uuid>" \
  -d '{
    "by": "ai:compound-engineering",
    "baseToken": "mt1:<token>",
    "operations": [
      {"op": "replace_block", "ref": "b3", "block": {"markdown": "Updated paragraph."}},
      {"op": "insert_after", "ref": "b3", "blocks": [{"markdown": "## New section"}]}
    ]
  }'
每个操作的请求体格式(单数
block
与复数
blocks
至关重要 — 使用错误会返回422错误):
op请求体字段
replace_block
ref
,
block: {markdown}
insert_after
ref
,
blocks: [{markdown}, ...]
insert_before
ref
,
blocks: [{markdown}, ...]
delete_block
ref
replace_range
fromRef
,
toRef
,
blocks: [{markdown}, ...]
find_replace_in_block
ref
,
find
,
replace
,
occurrence: "first" | "all"
读取
/snapshot
以获取稳定的块
ref
ID。
operations
会原子提交 — 要么所有操作都生效,要么都不生效 — 因此一次
/edit/v2
调用可安全高效地批量处理数十个块编辑(请查看
references/hitl-review.md
第2.4阶段的批量扫描指南)。
客户端连接时可正常编辑。
/edit/v2
suggestion.add
(包括
status: "accepted"
)以及所有评论操作在协作活跃时均可正常使用。仅
rewrite.apply
会被
LIVE_CLIENTS_PRESENT
阻止 — 因为它会覆盖正在进行的Yjs编辑。
当循环中断时。 如果重新读取并重试一次后修改操作仍持续失败,或多次读取的状态不一致,请调用
POST https://www.proofeditor.ai/api/bridge/report_bug
接口,传入失败请求的ID、slug和原始响应。服务器会补充信息并创建问题工单。

Known Limitations (Web API)

Web API已知限制

  • Bridge-style endpoints (
    /d/{slug}/bridge/*
    ) require client version headers (
    x-proof-client-version
    ,
    x-proof-client-build
    ,
    x-proof-client-protocol
    ) and return 426 CLIENT_UPGRADE_REQUIRED without them. Use
    /api/agent/{slug}/ops
    instead.
  • 桥接风格端点(
    /d/{slug}/bridge/*
    )需要客户端版本请求头(
    x-proof-client-version
    x-proof-client-build
    x-proof-client-protocol
    ),若无这些头会返回426 CLIENT_UPGRADE_REQUIRED错误。请改用
    /api/agent/{slug}/ops

Local Bridge (macOS App)

Local Bridge(macOS应用)

Requires Proof.app running. Bridge at
http://localhost:9847
.
Required headers:
  • X-Agent-Id: claude
    (identity for presence)
  • Content-Type: application/json
  • X-Window-Id: <uuid>
    (when multiple docs open)
需运行Proof.app。桥接地址为
http://localhost:9847
必填请求头:
  • X-Agent-Id: claude
    (在线状态身份标识)
  • Content-Type: application/json
  • X-Window-Id: <uuid>
    (当打开多个文档时)

Key Endpoints

核心端点

MethodEndpointPurpose
GET
/windows
List open documents
GET
/state
Read markdown, cursor, word count
GET
/marks
List all suggestions and comments
POST
/marks/suggest-replace
{"quote":"old","by":"ai:compound-engineering","content":"new"}
POST
/marks/suggest-insert
{"quote":"after this","by":"ai:compound-engineering","content":"insert"}
POST
/marks/suggest-delete
{"quote":"delete this","by":"ai:compound-engineering"}
POST
/marks/comment
{"quote":"text","by":"ai:compound-engineering","text":"comment"}
POST
/marks/reply
{"markId":"<id>","by":"ai:compound-engineering","text":"reply"}
POST
/marks/resolve
{"markId":"<id>","by":"ai:compound-engineering"}
POST
/marks/accept
{"markId":"<id>"}
POST
/marks/reject
{"markId":"<id>"}
POST
/rewrite
{"content":"full markdown","by":"ai:compound-engineering"}
POST
/presence
{"status":"reading","summary":"..."}
GET
/events/pending
Poll for user actions
方法端点用途
GET
/windows
列出已打开的文档
GET
/state
读取Markdown内容、光标位置、字数
GET
/marks
列出所有建议和评论
POST
/marks/suggest-replace
{"quote":"old","by":"ai:compound-engineering","content":"new"}
POST
/marks/suggest-insert
{"quote":"after this","by":"ai:compound-engineering","content":"insert"}
POST
/marks/suggest-delete
{"quote":"delete this","by":"ai:compound-engineering"}
POST
/marks/comment
{"quote":"text","by":"ai:compound-engineering","text":"comment"}
POST
/marks/reply
{"markId":"<id>","by":"ai:compound-engineering","text":"reply"}
POST
/marks/resolve
{"markId":"<id>","by":"ai:compound-engineering"}
POST
/marks/accept
{"markId":"<id>"}
POST
/marks/reject
{"markId":"<id>"}
POST
/rewrite
{"content":"full markdown","by":"ai:compound-engineering"}
POST
/presence
{"status":"reading","summary":"..."}
GET
/events/pending
轮询用户操作

Presence Statuses

在线状态

thinking
,
reading
,
idle
,
acting
,
waiting
,
completed
thinking
,
reading
,
idle
,
acting
,
waiting
,
completed

Workflow: Review a Shared Document

工作流:审阅共享文档

When given a Proof URL like
https://www.proofeditor.ai/d/abc123?token=xxx
:
  1. Extract the slug (
    abc123
    ) and token from the URL
  2. Read the document state via the API
  3. Add comments or suggest edits using the ops endpoint
  4. The author sees changes in real-time
bash
undefined
当收到类似
https://www.proofeditor.ai/d/abc123?token=xxx
的Proof URL时:
  1. 从URL中提取slug(
    abc123
    )和令牌
  2. 通过API读取文档状态
  3. 使用ops端点添加评论或建议修改
  4. 作者会实时看到更改
bash
undefined

Read once — the same response yields both the doc content and the baseToken for every mutation below.

读取一次 — 同一响应可获取文档内容和后续所有修改所需的baseToken。

STATE=$(curl -s "https://www.proofeditor.ai/api/agent/abc123/state"
-H "x-share-token: xxx") BASE=$(printf '%s' "$STATE" | jq -r '.mutationBase.token')
STATE=$(curl -s "https://www.proofeditor.ai/api/agent/abc123/state"
-H "x-share-token: xxx") BASE=$(printf '%s' "$STATE" | jq -r '.mutationBase.token')

Inspect doc fields as needed: printf '%s' "$STATE" | jq '.markdown, .revision'

按需查看文档字段:printf '%s' "$STATE" | jq '.markdown, .revision'

Comment

添加评论

curl -X POST "https://www.proofeditor.ai/api/agent/abc123/ops"
-H "Content-Type: application/json"
-H "x-share-token: xxx"
-H "X-Agent-Id: ai:compound-engineering"
-d "$(jq -n --arg base "$BASE" '{type:"comment.add",quote:"text",by:"ai:compound-engineering",text:"comment",baseToken:$base}')"
curl -X POST "https://www.proofeditor.ai/api/agent/abc123/ops"
-H "Content-Type: application/json"
-H "x-share-token: xxx"
-H "X-Agent-Id: ai:compound-engineering"
-d "$(jq -n --arg base "$BASE" '{type:"comment.add",quote:"text",by:"ai:compound-engineering",text:"comment",baseToken:$base}')"

Suggest edit (tracked, pending)

建议修改(已跟踪,待确认)

curl -X POST "https://www.proofeditor.ai/api/agent/abc123/ops"
-H "Content-Type: application/json"
-H "x-share-token: xxx"
-H "X-Agent-Id: ai:compound-engineering"
-d "$(jq -n --arg base "$BASE" '{type:"suggestion.add",kind:"replace",quote:"old",by:"ai:compound-engineering",content:"new",baseToken:$base}')"
curl -X POST "https://www.proofeditor.ai/api/agent/abc123/ops"
-H "Content-Type: application/json"
-H "x-share-token: xxx"
-H "X-Agent-Id: ai:compound-engineering"
-d "$(jq -n --arg base "$BASE" '{type:"suggestion.add",kind:"replace",quote:"old",by:"ai:compound-engineering",content:"new",baseToken:$base}')"

Suggest and immediately apply (tracked, committed)

建议修改并立即应用(已跟踪,已提交)

curl -X POST "https://www.proofeditor.ai/api/agent/abc123/ops"
-H "Content-Type: application/json"
-H "x-share-token: xxx"
-H "X-Agent-Id: ai:compound-engineering"
-d "$(jq -n --arg base "$BASE" '{type:"suggestion.add",kind:"replace",quote:"old",by:"ai:compound-engineering",content:"new",status:"accepted",baseToken:$base}')"
undefined
curl -X POST "https://www.proofeditor.ai/api/agent/abc123/ops"
-H "Content-Type: application/json"
-H "x-share-token: xxx"
-H "X-Agent-Id: ai:compound-engineering"
-d "$(jq -n --arg base "$BASE" '{type:"suggestion.add",kind:"replace",quote:"old",by:"ai:compound-engineering",content:"new",status:"accepted",baseToken:$base}')"
undefined

Workflow: Create and Share a New Document

工作流:创建并分享新文档

bash
undefined
bash
undefined

1. Create

1. 创建文档

RESPONSE=$(curl -s -X POST https://www.proofeditor.ai/share/markdown
-H "Content-Type: application/json"
-d '{"title":"My Doc","markdown":"# Title\n\nContent here."}')
RESPONSE=$(curl -s -X POST https://www.proofeditor.ai/share/markdown
-H "Content-Type: application/json"
-d '{"title":"My Doc","markdown":"# Title\n\nContent here."}')

2. Extract URL and token

2. 提取URL和令牌

URL=$(echo "$RESPONSE" | jq -r '.tokenUrl') SLUG=$(echo "$RESPONSE" | jq -r '.slug') TOKEN=$(echo "$RESPONSE" | jq -r '.accessToken')
URL=$(echo "$RESPONSE" | jq -r '.tokenUrl') SLUG=$(echo "$RESPONSE" | jq -r '.slug') TOKEN=$(echo "$RESPONSE" | jq -r '.accessToken')

3. Bind display name via presence

3. 通过presence接口绑定显示名称

curl -s -X POST "https://www.proofeditor.ai/api/agent/$SLUG/presence"
-H "Content-Type: application/json"
-H "x-share-token: $TOKEN"
-H "X-Agent-Id: ai:compound-engineering"
-d '{"name":"Compound Engineering","status":"reading","summary":"Uploaded doc"}'
curl -s -X POST "https://www.proofeditor.ai/api/agent/$SLUG/presence"
-H "Content-Type: application/json"
-H "x-share-token: $TOKEN"
-H "X-Agent-Id: ai:compound-engineering"
-d '{"name":"Compound Engineering","status":"reading","summary":"Uploaded doc"}'

4. Share the URL

4. 分享URL

echo "$URL"
echo "$URL"

5. Make edits using the ops endpoint (baseToken required)

5. 使用ops端点进行修改(需要baseToken)

BASE=$(curl -s "https://www.proofeditor.ai/api/agent/$SLUG/state"
-H "x-share-token: $TOKEN" | jq -r '.mutationBase.token') curl -X POST "https://www.proofeditor.ai/api/agent/$SLUG/ops"
-H "Content-Type: application/json"
-H "x-share-token: $TOKEN"
-H "X-Agent-Id: ai:compound-engineering"
-d "$(jq -n --arg base "$BASE" '{type:"comment.add",quote:"Content here",by:"ai:compound-engineering",text:"Added a note",baseToken:$base}')"
undefined
BASE=$(curl -s "https://www.proofeditor.ai/api/agent/$SLUG/state"
-H "x-share-token: $TOKEN" | jq -r '.mutationBase.token') curl -X POST "https://www.proofeditor.ai/api/agent/$SLUG/ops"
-H "Content-Type: application/json"
-H "x-share-token: $TOKEN"
-H "X-Agent-Id: ai:compound-engineering"
-d "$(jq -n --arg base "$BASE" '{type:"comment.add",quote:"Content here",by:"ai:compound-engineering",text:"Added a note",baseToken:$base}')"
undefined

Workflow: Pull a Proof Doc to Local

工作流:将Proof文档拉取到本地

Sync the current Proof doc state to a local markdown file. Used by:
  • HITL review end-sync (
    references/hitl-review.md
    Phase 5) when the doc originated from a local file
  • Ad-hoc snapshots of a Proof doc to disk (before closing the tab, archiving, handing off)
  • Refreshing a local working copy against the live Proof version
bash
SLUG=<slug>
TOKEN=<accessToken>
LOCAL=<absolute-path>
将当前Proof文档状态同步到本地Markdown文件。适用于:
  • 当文档源自本地文件时,HITL审阅结束同步(
    references/hitl-review.md
    第5阶段)
  • 临时将Proof文档快照保存到磁盘(关闭标签页、归档、移交前)
  • 根据Proof实时版本刷新本地工作副本
bash
SLUG=<slug>
TOKEN=<accessToken>
LOCAL=<absolute-path>

One read to a temp file — avoids passing markdown through $(...), which would strip trailing newlines.

读取到临时文件 — 避免通过$(...)传递Markdown内容,否则会丢失末尾换行符。

STATE_TMP=$(mktemp) curl -s "https://www.proofeditor.ai/api/agent/$SLUG/state"
-H "x-share-token: $TOKEN" > "$STATE_TMP" REVISION=$(jq -r '.revision' "$STATE_TMP")
STATE_TMP=$(mktemp) curl -s "https://www.proofeditor.ai/api/agent/$SLUG/state"
-H "x-share-token: $TOKEN" > "$STATE_TMP" REVISION=$(jq -r '.revision' "$STATE_TMP")

Atomic write: stream .markdown bytes directly to a temp sibling, then rename.

原子写入:将.markdown字节直接流式传输到临时同级文件,然后重命名。

TMP="${LOCAL}.proof-sync.$$" jq -jr '.markdown' "$STATE_TMP" > "$TMP" && mv "$TMP" "$LOCAL" rm "$STATE_TMP"

`jq -jr` (`-j` no trailing newline, `-r` raw string) streams the markdown bytes straight to the temp file without going through a shell variable, so trailing newlines survive intact. `mv` within the same filesystem is atomic — a crashed write leaves the original untouched rather than a half-written file.

**Confirm before writing when the pull isn't directly asked for.** If a workflow ends up pulling as a side-effect of a different action (e.g., HITL review completion), surface the impending write with a short confirm like "Sync reviewed doc to `<localPath>`?" A silent overwrite is surprising — the user may have forgotten the local file exists in that session, or expected Proof to stay canonical until they explicitly asked to pull.
TMP="${LOCAL}.proof-sync.$$" jq -jr '.markdown' "$STATE_TMP" > "$TMP" && mv "$TMP" "$LOCAL" rm "$STATE_TMP"

`jq -jr`(`-j`不添加末尾换行,`-r`原始字符串)将Markdown字节直接流式传输到临时文件,无需通过shell变量,因此末尾换行符会完整保留。同一文件系统内的`mv`操作是原子性的 — 写入崩溃时会保留原始文件,而非生成半写入的文件。

**当拉取操作并非用户直接请求时,需先确认。** 如果工作流中因其他操作导致触发拉取(例如HITL审阅完成),需以简短提示告知用户即将执行写入,例如“将审阅后的文档同步到`<localPath>`?”。静默覆盖会让用户感到意外 — 用户可能已忘记会话中存在该本地文件,或希望在明确请求拉取前保持Proof为权威版本。

Safety

注意事项

  • Use
    /state
    content as source of truth before editing
  • During active collab use
    edit/v2
    (direct block changes) or
    suggestion.add
    (tracked changes); reserve
    rewrite.apply
    for no-client scenarios since it's blocked by
    LIVE_CLIENTS_PRESENT
    when anyone is connected
  • Don't span table cells in a single replace
  • Always include
    by: "ai:compound-engineering"
    on every op and
    X-Agent-Id: ai:compound-engineering
    in headers for consistent attribution
  • Reuse
    baseToken
    from your most recent
    /state
    or
    /snapshot
    read; on
    STALE_BASE
    , re-read and retry once
  • 编辑前以
    /state
    内容为事实来源
  • 协作活跃时使用
    edit/v2
    (直接块修改)或
    suggestion.add
    (跟踪式修改);仅当无客户端连接时使用
    rewrite.apply
    ,因为当有用户连接时该操作会被
    LIVE_CLIENTS_PRESENT
    阻止
  • 单次替换操作不要跨表格单元格
  • 每个操作务必包含
    by: "ai:compound-engineering"
    ,请求头中务必包含
    X-Agent-Id: ai:compound-engineering
    ,以保持归属一致
  • 复用最近一次
    /state
    /snapshot
    读取返回的
    baseToken
    ;遇到
    STALE_BASE
    错误时,重新读取并重试一次