mcpField
P
proof

proof

github.com/everyinc文档处理25.8k277 次安装今天更新
代码仓库

关于 proof

proof 是面向人类与 Agent 的协作式 Markdown 编辑器技能,支持通过 Web API 共享编辑,也可驱动 macOS Proof 应用。它提供评论、建议修改及带身份标记的变更流程。

主要功能

  1. 01通过 Web API 创建和编辑共享文档
  2. 02连接 macOS Proof 应用本地桥接
  3. 03评论、回复及处理评论
  4. 04提交、接受或拒绝修改建议
  5. 05文档操作附带 Agent 身份

适用场景

  1. 01邀请他人审阅共享 Markdown 文档
  2. 02收集结构化反馈并同步回本地文件
  3. 03在协作编辑中跟踪建议与评论

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/everyinc/compound-engineering-plugin --skill proof

安装后在 Claude Code 中输入/proof确认已加载。

附带文件references/hitl-review.md

详细介绍

Proof - 协作式 Markdown 编辑器

Proof 是一款供人类和 Agent 使用的协作文档编辑器。它支持两种模式:

  1. Web API - 通过 HTTP 创建和编辑共享文档(无需安装)
  2. 本地桥接 - 通过 localhost:9847 操控 macOS Proof 应用

身份与署名

对 Proof 文档的每次写入都必须注明身份。以下两个字段承载 Agent 的身份信息:

  • 机器 ID(每个操作中的 by、X-Agent-Id 标头): ai:compound-engineering — 稳定、采用小写连字符格式,且可由机器解析。显示在标记、事件和 API 响应中。
  • 显示名称(POST /presence 中的 name): Compound Engineering — 便于人类阅读,显示在 Proof 的在线状态标签和评论作者徽章中。

通过携带 X-Agent-Id 标头向在线状态接口发送请求,为每个文档会话设置一次显示名称。Proof 会在该会话中将名称绑定到对应的 Agent ID。这些值是使用此技能的所有调用方的默认值;运行 HITL 审核(references/hitl-review.md)的调用方可传入不同的 identity 对,以便由不同的子 Agent 负责文档。请勿使用 ai:compound 或其他临时变体,除非调用方明确覆盖,否则身份应保持统一。

Human-in-the-Loop 审核模式

当调用方(例如 ce-brainstorm、ce-plan)需要上传本地 Markdown 文档、在 Proof 中收集结构化的人类反馈,并将最终文档同步回磁盘时,请加载 references/hitl-review.md,查看完整的流程规范:调用约定、标记分类(修改 / 问题 / 异议 / 模糊)、幂等摄取流程、基于异常的终止报告,以及最终同步时的原子写入。

Web API(共享文档的首选方式)

创建共享文档

无需身份验证。返回包含访问令牌的可分享 URL。

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

响应格式:

{
  "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 路径。

读取共享文档
curl -s "https://www.proofeditor.ai/api/agent/{slug}/state" \
  -H "x-share-token: <token>"
编辑共享文档

所有操作均发送到 POST https://www.proofeditor.ai/api/agent/{slug}/ops

注意: 使用 /api/agent/{slug}/ops 路径(来自创建响应中的 _links),而不是 /api/documents/{slug}/ops。

受保护文档的身份验证:

  • 请求头:x-share-token: <token> 或 Authorization: Bearer <token>
  • Token 来自 URL 参数:?token=xxx,或来自创建响应中的 accessToken
  • 请求头:X-Agent-Id: ai:compound-engineering(presence 必需;在 ops 请求中也包含此项,以确保归属信息一致)

线路格式提醒。 /api/agent/{slug}/ops 使用顶层 type 字段;/api/agent/{slug}/edit/v2 使用 operations 数组,其中每个条目都有 op。不要混用——向 /ops 发送 op 会返回 422。

每次修改都需要 baseToken。 在每次写入之前,立即从 /state.mutationBase.token(或 /snapshot.mutationBase.token)读取,并将其包含在请求正文中。遇到 BASE_TOKEN_REQUIRED 或 STALE_BASE 时,重新读取并重试一次。请参阅 references/hitl-review.md 中的 baseToken 操作方法。

Idempotency-Key 请求头 建议用于每次修改,以便安全地自动重试;当 /state.contract.idempotencyRequired 为 true 时则为必需。

对文本发表评论:

{"type": "comment.add", "quote": "text to comment on", "by": "ai:compound-engineering", "text": "Your comment here", "baseToken": "<token>"}

回复评论:

{"type": "comment.reply", "markId": "<id>", "by": "ai:compound-engineering", "text": "Reply text", "baseToken": "<token>"}

解决 / 取消解决评论:

{"type": "comment.resolve", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
{"type": "comment.unresolve", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}

提出替换建议(待处理——用户必须接受或拒绝):

{"type": "suggestion.add", "kind": "replace", "quote": "original text", "by": "ai:compound-engineering", "content": "replacement text", "baseToken": "<token>"}

提出并立即应用(有记录但已提交——用户可以拒绝以撤销):

{"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"。

接受或拒绝现有建议:

{"type": "suggestion.accept", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}
{"type": "suggestion.reject", "markId": "<id>", "by": "ai:compound-engineering", "baseToken": "<token>"}

不支持 suggestion.resolve——请改用接受或拒绝。

批量重写(替换整个文档):

{"type": "rewrite.apply", "content": "full new markdown", "by": "ai:compound-engineering", "baseToken": "<token>"}

通过 /edit/v2 进行块级编辑(独立端点,格式独立):

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", "block": {"markdown": "## New section"}}
    ]
  }'

operations 中支持的 op 类型:replace_block、insert_before、insert_after、delete_block、replace_range(使用 fromRef + toRef)、find_replace_in_block(接受 occurrence: "first" | "all")。读取 /snapshot 以获取稳定的块 ref ID 和 mutationBase.token。

客户端已连接时可以编辑。 /edit/v2、suggestion.add(包括 status: "accepted")以及所有评论操作都可以在协作进行期间使用。只有 rewrite.apply 会因 LIVE_CLIENTS_PRESENT 而被阻止——它会覆盖正在进行的 Yjs 编辑。

循环中断时。 如果修改在重新读取并重试一次后仍持续失败,或多次读取到的状态看起来不一致,请调用 POST https://www.proofeditor.ai/api/bridge/report_bug,并提供失败请求 ID、slug 和原始响应。服务器会补充信息并提交问题。

已知限制(Web API)
  • Bridge 风格的端点(/d/{slug}/bridge/*)需要客户端版本请求头(x-proof-client-version、x-proof-client-build、x-proof-client-protocol);如果缺少这些请求头,则会返回 426 CLIENT_UPGRADE_REQUIRED。请改用 /api/agent/{slug}/ops。

本地 Bridge(macOS 应用)

需要运行 Proof.app。Bridge 位于 http://localhost:9847。

必需的请求头:

  • X-Agent-Id: claude(用于 presence 的身份标识)
  • Content-Type: application/json
  • X-Window-Id: <uuid>(同时打开多个文档时需要)
主要端点
方法端点用途
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轮询用户操作
在线状态

thinking、reading、idle、acting、waiting、completed

工作流:审阅共享文档

收到 Proof URL(如 https://www.proofeditor.ai/d/abc123?token=xxx)时:

  1. 从 URL 中提取 slug(abc123)和 token
  2. 通过 API 读取文档状态
  3. 使用 ops 端点添加评论或提出编辑建议
  4. 作者会实时看到更改
# Read
curl -s "https://www.proofeditor.ai/api/agent/abc123/state" \
  -H "x-share-token: xxx"

# Get baseToken for the next mutation
BASE=$(curl -s "https://www.proofeditor.ai/api/agent/abc123/state" \
  -H "x-share-token: xxx" | jq -r '.mutationBase.token')

# 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}')"

# 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}')"

# 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}')"

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

# 1. Create
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
URL=$(echo "$RESPONSE" | jq -r '.tokenUrl')
SLUG=$(echo "$RESPONSE" | jq -r '.slug')
TOKEN=$(echo "$RESPONSE" | jq -r '.accessToken')

# 3. Bind display name via 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"}'

# 4. Share the URL
echo "$URL"

# 5. Make edits using the ops endpoint (baseToken required)
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}')"

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

将当前 Proof 文档状态同步到本地 Markdown 文件。适用于:

  • 本地文件创建的文档在 HITL 审阅结束时同步(references/hitl-review.md 第 5 阶段)
  • 将 Proof 文档临时快照保存到磁盘(关闭标签页、归档或交接前)
  • 根据实时 Proof 版本刷新本地工作副本
SLUG=<slug>
TOKEN=<accessToken>
LOCAL=<absolute-path>

# One read to a temp file — avoids passing markdown through $(...), which would strip trailing newlines.
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.
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 在明确要求拉取之前始终作为权威版本。

安全

  • 编辑前,以 /state 的内容为准
  • 协作期间使用 edit/v2(直接修改区块)或 suggestion.add(跟踪更改);仅在没有客户端连接时使用 rewrite.apply,因为只要有人连接,该操作就会被 LIVE_CLIENTS_PRESENT 阻止
  • 单次替换不要跨越多个表格单元格
  • 每个 op 都必须包含 by: "ai:compound-engineering",并在请求头中包含 X-Agent-Id: ai:compound-engineering,以确保归属信息一致
  • 每次修改前都读取最新的 baseToken;如果遇到 STALE_BASE,重新读取并重试一次

评论

支持 Markdown