[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71EJ6C5V2MCCNT33NH7DT2Y":3,"skill-same:01M71EJ6C5V2MCCNT33NH7DT2Y":79},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":43,"linkOnly":44,"markdownContent":45,"markdownBody":46,"frontMatter":47,"refName":52,"commitSha":53,"skillDirectory":54,"forksCount":55,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":58,"install":59,"resources":72},"01M71EJ6C5V2MCCNT33NH7DT2Y","proof",null,"Create, share, view, comment on, edit, and run human-in-the-loop review loops over markdown documents via Proof, the collaborative markdown editor at proofeditor.ai (\"Proof editor\"). Use when the user wants to render or view a local markdown file in Proof, share markdown to get a URL, iterate collaboratively on a Proof doc, comment on or suggest edits in Proof, HITL a spec\u002Fplan\u002Fdraft for human review, sync a Proof doc back to local, or work from a proofeditor.ai URL. Trigger on phrases like \"view this in proof\", \"share to proof\", \"iterate with proof\", or \"HITL this doc\", and on gh-brainstorm \u002F gh-ideate \u002F gh-plan handoffs for human review. Also match clear requests for a rendered\u002Fshared markdown review surface even if the user does not name Proof. Do not trigger on \"proof\" meaning evidence, math\u002Flogic proof, burden of proof, proof-of-concept, or bare \"proofread this\" requests where inline text review is expected.","JGXC100\u002FGaleHarnessCodingCLI","JGXC100","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F11926809?v=4","01M71EEBHJ3EGYSNNDDSVDKXNG","JGX","01M71EEBJ995S5J2HDEQCBA268",0,"MIT","https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Fplugins\u002Fgaleharness-cli\u002Fskills\u002Fproof\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000002","文档处理","SCENARIO","使用场景",[5,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"shared","when","bare","proof-of-concept","meaning","URL","render","loops","get","review","local","back","work","brainstorm","text","loop","Bash","create","documents","2026-11-10 10:12:30",false,"---\nname: proof\ndescription: Create, share, view, comment on, edit, and run human-in-the-loop review loops over markdown documents via Proof, the collaborative markdown editor at proofeditor.ai (\"Proof editor\"). Use when the user wants to render or view a local markdown file in Proof, share markdown to get a URL, iterate collaboratively on a Proof doc, comment on or suggest edits in Proof, HITL a spec\u002Fplan\u002Fdraft for human review, sync a Proof doc back to local, or work from a proofeditor.ai URL. Trigger on phrases like \"view this in proof\", \"share to proof\", \"iterate with proof\", or \"HITL this doc\", and on gh-brainstorm \u002F gh-ideate \u002F gh-plan handoffs for human review. Also match clear requests for a rendered\u002Fshared markdown review surface even if the user does not name Proof. Do not trigger on \"proof\" meaning evidence, math\u002Flogic proof, burden of proof, proof-of-concept, or bare \"proofread this\" requests where inline text review is expected.\nallowed-tools:\n  - Bash\n  - Read\n  - Write\n  - WebFetch\n---\n\n# Proof - Collaborative Markdown Editor\n\nProof is a collaborative document editor for humans and agents. It supports two modes:\n\n1. **Web API** - Create and edit shared documents via HTTP (no install needed)\n2. **Local Bridge** - Drive the macOS Proof app via localhost:9847\n\n## Identity and Attribution\n\nEvery write to a Proof doc must be attributed. Two fields carry the agent's identity:\n\n- **Machine ID (`by` on every op, `X-Agent-Id` header):** `ai:galeharness-cli` — stable, lowercase-hyphenated, machine-parseable. Appears in marks, events, and the API response.\n- **Display name (`name` on `POST \u002Fpresence`):** `GaleHarness CLI` — human-readable, shown in Proof's presence chips and comment-author badges.\n\nSet 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\u002Fhitl-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.\n\n## Human-in-the-Loop Review Mode\n\nHuman-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\u002Fhitl-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:\n\n- **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.\n- **Upstream skill handoff** — `gh-brainstorm`, `gh-ideate`, or `gh-plan` finishes a draft and hands it off for human review before the next phase, passing the file path and title explicitly.\n\n## Web API (Primary for Sharing)\n\n### Create a Shared Document\n\nNo authentication required. Returns a shareable URL with access token.\n\n```bash\ncurl -X POST https:\u002F\u002Fwww.proofeditor.ai\u002Fshare\u002Fmarkdown \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"title\":\"My Doc\",\"markdown\":\"# Hello\\n\\nContent here.\"}'\n```\n\n**Response format:**\n```json\n{\n  \"slug\": \"abc123\",\n  \"tokenUrl\": \"https:\u002F\u002Fwww.proofeditor.ai\u002Fd\u002Fabc123?token=xxx\",\n  \"accessToken\": \"xxx\",\n  \"ownerSecret\": \"yyy\",\n  \"_links\": {\n    \"state\": \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fstate\",\n    \"ops\": \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fops\"\n  }\n}\n```\n\nUse the `tokenUrl` as the shareable link. The `_links` give you the exact API paths.\n\n### Read a Shared Document\n\n```bash\ncurl -s \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F{slug}\u002Fstate\" \\\n  -H \"x-share-token: \u003Ctoken>\"\n```\n\n### Edit a Shared Document\n\nAll operations go to `POST https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F{slug}\u002Fops`\n\n**Note:** Use the `\u002Fapi\u002Fagent\u002F{slug}\u002Fops` path (from `_links` in create response), NOT `\u002Fapi\u002Fdocuments\u002F{slug}\u002Fops`.\n\n**Authentication for protected docs:**\n- Header: `x-share-token: \u003Ctoken>` or `Authorization: Bearer \u003Ctoken>`\n- Token comes from the URL parameter: `?token=xxx` or the `accessToken` from create response\n- Header: `X-Agent-Id: ai:galeharness-cli` (required for presence; include on ops for consistent attribution)\n\n**Wire-format reminder.** `\u002Fapi\u002Fagent\u002F{slug}\u002Fops` uses a top-level `type` field; `\u002Fapi\u002Fagent\u002F{slug}\u002Fedit\u002Fv2` uses an `operations` array where each entry has `op`. Do not mix — sending `op` to `\u002Fops` returns 422.\n\n**Every mutation requires a `baseToken`.** Use the `mutationBase.token` from your most recent `\u002Fstate` or `\u002Fsnapshot` read and include it in the request body. These tokens do not go stale within seconds just because another write happened; `STALE_BASE` is recoverable. If you get `BASE_TOKEN_REQUIRED`, `MISSING_BASE`, `INVALID_BASE_TOKEN`, or `STALE_BASE`, re-read and retry once. Only do a pre-mutation read when you have not read `\u002Fstate` or `\u002Fsnapshot` in the current session. See the baseToken recipe in `references\u002Fhitl-review.md`.\n\n**`Idempotency-Key` header** is recommended on every mutation and required when `\u002Fstate.contract.idempotencyRequired` is true. Reuse the same key only when retrying the exact same logical write with the same body. A changed body or fresh key is a new logical write.\n\n**Retry discipline after mutation errors — verify before retrying.**\n\n- Token errors (`STALE_BASE`, `BASE_TOKEN_REQUIRED`, `MISSING_BASE`, `INVALID_BASE_TOKEN`) are safe to auto-retry once after a fresh `\u002Fstate` or `\u002Fsnapshot`.\n- Anchor errors (`QUOTE_NOT_FOUND`, `AMBIGUOUS_QUOTE`, missing block `ref`) mean the write did not commit, but do not blindly retry. Re-read, update the quote\u002Fref, and decide whether the original intent still applies.\n- Payload errors (`422`, invalid op shape, unsupported field) should not be retried unchanged.\n- Ambiguous failures (`COLLAB_SYNC_FAILED`, `REWRITE_BARRIER_FAILED`, `PROJECTION_STALE`, `INTERNAL_ERROR`, `5xx`, network timeout, or any `202` with `collab.status: \"pending\"`) may already have written. Re-read `\u002Fstate`, verify whether the intended mark\u002Fedit exists, and retry only if it is absent.\n- Idempotency only protects retries of the exact same request. If you change the body or key, the server treats it as a new write.\n\nDuplicate marks usually come from retrying after an ambiguous failure without first verifying current state.\n\n**Comment on text:**\n```json\n{\"type\": \"comment.add\", \"quote\": \"text to comment on\", \"by\": \"ai:galeharness-cli\", \"text\": \"Your comment here\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Reply to a comment:**\n```json\n{\"type\": \"comment.reply\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"text\": \"Reply text\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Resolve \u002F unresolve a comment:**\n```json\n{\"type\": \"comment.resolve\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n{\"type\": \"comment.unresolve\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Suggest a replacement (pending — user must accept\u002Freject):**\n```json\n{\"type\": \"suggestion.add\", \"kind\": \"replace\", \"quote\": \"original text\", \"by\": \"ai:galeharness-cli\", \"content\": \"replacement text\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Suggest and immediately apply (tracked but committed — user can reject to revert):**\n```json\n{\"type\": \"suggestion.add\", \"kind\": \"replace\", \"quote\": \"original text\", \"by\": \"ai:galeharness-cli\", \"content\": \"replacement text\", \"status\": \"accepted\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n`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\"`.\n\n**Accept or reject an existing suggestion:**\n```json\n{\"type\": \"suggestion.accept\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n{\"type\": \"suggestion.reject\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n`suggestion.resolve` is not supported — use accept or reject instead.\n\n**Bulk rewrite (whole-doc replacement):**\n```json\n{\"type\": \"rewrite.apply\", \"content\": \"full new markdown\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Block-level edits via `\u002Fedit\u002Fv2`** (separate endpoint, separate shape):\n```bash\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F{slug}\u002Fedit\u002Fv2\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: \u003Ctoken>\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -H \"Idempotency-Key: \u003Cuuid>\" \\\n  -d '{\n    \"by\": \"ai:galeharness-cli\",\n    \"baseToken\": \"mt1:\u003Ctoken>\",\n    \"operations\": [\n      {\"op\": \"replace_block\", \"ref\": \"b3\", \"block\": {\"markdown\": \"Updated paragraph.\"}},\n      {\"op\": \"insert_after\", \"ref\": \"b3\", \"blocks\": [{\"markdown\": \"## New section\"}]}\n    ]\n  }'\n```\n\nSupported `op` kinds inside `operations`:\n\n| op | Shape |\n|----|-------|\n| `replace_block` | `{\"op\":\"replace_block\",\"ref\":\"b8\",\"block\":{\"markdown\":\"new content\"}}` |\n| `insert_after` | `{\"op\":\"insert_after\",\"ref\":\"b3\",\"blocks\":[{\"markdown\":\"new block\"}]}` |\n| `insert_before` | `{\"op\":\"insert_before\",\"ref\":\"b3\",\"blocks\":[{\"markdown\":\"new block\"}]}` |\n| `delete_block` | `{\"op\":\"delete_block\",\"ref\":\"b6\"}` |\n| `replace_range` | `{\"op\":\"replace_range\",\"fromRef\":\"b2\",\"toRef\":\"b5\",\"blocks\":[{\"markdown\":\"replacement\"}]}` |\n| `find_replace_in_block` | `{\"op\":\"find_replace_in_block\",\"ref\":\"b4\",\"find\":\"old\",\"replace\":\"new\",\"occurrence\":\"first\"}` |\n\n`\u002Fedit\u002Fv2` commits the whole `operations` array atomically and can batch dozens of block edits in one request. Read `\u002Fsnapshot` to get block `ref` IDs and the `mutationBase.token`; if any write has landed since the last snapshot, re-fetch `\u002Fsnapshot` before building block operations.\n\n**Editing while a client is connected is fine.** `\u002Fedit\u002Fv2`, `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.\n\n**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:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fbridge\u002Freport_bug` with the failing request ID, slug, and raw response. The server enriches and files an issue.\n\n### Known Limitations (Web API)\n\n- Bridge-style endpoints (`\u002Fd\u002F{slug}\u002Fbridge\u002F*`) 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 `\u002Fapi\u002Fagent\u002F{slug}\u002Fops` instead.\n\n## Local Bridge (macOS App)\n\nRequires Proof.app running. Bridge at `http:\u002F\u002Flocalhost:9847`.\n\n**Required headers:**\n- `X-Agent-Id: ai:galeharness-cli` (identity for presence)\n- `Content-Type: application\u002Fjson`\n- `X-Window-Id: \u003Cuuid>` (when multiple docs open)\n\n### Key Endpoints\n\n| Method | Endpoint | Purpose |\n|--------|----------|---------|\n| GET | `\u002Fwindows` | List open documents |\n| GET | `\u002Fstate` | Read markdown, cursor, word count |\n| GET | `\u002Fmarks` | List all suggestions and comments |\n| POST | `\u002Fmarks\u002Fsuggest-replace` | `{\"quote\":\"old\",\"by\":\"ai:galeharness-cli\",\"content\":\"new\"}` |\n| POST | `\u002Fmarks\u002Fsuggest-insert` | `{\"quote\":\"after this\",\"by\":\"ai:galeharness-cli\",\"content\":\"insert\"}` |\n| POST | `\u002Fmarks\u002Fsuggest-delete` | `{\"quote\":\"delete this\",\"by\":\"ai:galeharness-cli\"}` |\n| POST | `\u002Fmarks\u002Fcomment` | `{\"quote\":\"text\",\"by\":\"ai:galeharness-cli\",\"text\":\"comment\"}` |\n| POST | `\u002Fmarks\u002Freply` | `{\"markId\":\"\u003Cid>\",\"by\":\"ai:galeharness-cli\",\"text\":\"reply\"}` |\n| POST | `\u002Fmarks\u002Fresolve` | `{\"markId\":\"\u003Cid>\",\"by\":\"ai:galeharness-cli\"}` |\n| POST | `\u002Fmarks\u002Faccept` | `{\"markId\":\"\u003Cid>\"}` |\n| POST | `\u002Fmarks\u002Freject` | `{\"markId\":\"\u003Cid>\"}` |\n| POST | `\u002Frewrite` | `{\"content\":\"full markdown\",\"by\":\"ai:galeharness-cli\"}` |\n| POST | `\u002Fpresence` | `{\"status\":\"reading\",\"summary\":\"...\"}` |\n| GET | `\u002Fevents\u002Fpending` | Poll for user actions |\n\n### Presence Statuses\n\n`thinking`, `reading`, `idle`, `acting`, `waiting`, `completed`\n\n## Workflow: Review a Shared Document\n\nWhen given a Proof URL like `https:\u002F\u002Fwww.proofeditor.ai\u002Fd\u002Fabc123?token=xxx`:\n\n1. Extract the slug (`abc123`) and token from the URL\n2. Read the document state via the API\n3. Add comments or suggest edits using the ops endpoint\n4. The author sees changes in real-time\n\n```bash\n# Read once and reuse the mutationBase token from that response\nSTATE=$(curl -s \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fstate\" \\\n  -H \"x-share-token: xxx\")\nBASE=$(printf '%s' \"$STATE\" | jq -r '.mutationBase.token')\n# Inspect doc fields from \"$STATE\" as needed...\n\n# Comment\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fops\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: xxx\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d \"$(jq -n --arg base \"$BASE\" '{type:\"comment.add\",quote:\"text\",by:\"ai:galeharness-cli\",text:\"comment\",baseToken:$base}')\"\n\n# Suggest edit (tracked, pending)\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fops\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: xxx\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d \"$(jq -n --arg base \"$BASE\" '{type:\"suggestion.add\",kind:\"replace\",quote:\"old\",by:\"ai:galeharness-cli\",content:\"new\",baseToken:$base}')\"\n\n# Suggest and immediately apply (tracked, committed)\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fops\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: xxx\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d \"$(jq -n --arg base \"$BASE\" '{type:\"suggestion.add\",kind:\"replace\",quote:\"old\",by:\"ai:galeharness-cli\",content:\"new\",status:\"accepted\",baseToken:$base}')\"\n```\n\n## Workflow: Create and Share a New Document\n\n```bash\n# 1. Create\nRESPONSE=$(curl -s -X POST https:\u002F\u002Fwww.proofeditor.ai\u002Fshare\u002Fmarkdown \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"title\":\"My Doc\",\"markdown\":\"# Title\\n\\nContent here.\"}')\n\n# 2. Extract URL and token\nURL=$(echo \"$RESPONSE\" | jq -r '.tokenUrl')\nSLUG=$(echo \"$RESPONSE\" | jq -r '.slug')\nTOKEN=$(echo \"$RESPONSE\" | jq -r '.accessToken')\n\n# 3. Bind display name via presence\ncurl -s -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F$SLUG\u002Fpresence\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: $TOKEN\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d '{\"name\":\"GaleHarness CLI\",\"status\":\"reading\",\"summary\":\"Uploaded doc\"}'\n\n# 4. Share the URL\necho \"$URL\"\n\n# 5. Make edits using the ops endpoint (baseToken required)\nBASE=$(curl -s \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F$SLUG\u002Fstate\" \\\n  -H \"x-share-token: $TOKEN\" | jq -r '.mutationBase.token')\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F$SLUG\u002Fops\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: $TOKEN\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d \"$(jq -n --arg base \"$BASE\" '{type:\"comment.add\",quote:\"Content here\",by:\"ai:galeharness-cli\",text:\"Added a note\",baseToken:$base}')\"\n```\n\n## Workflow: Pull a Proof Doc to Local\n\nSync the current Proof doc state to a local markdown file. Used by:\n\n- HITL review end-sync (`references\u002Fhitl-review.md` Phase 5) when the doc originated from a local file\n- Ad-hoc snapshots of a Proof doc to disk (before closing the tab, archiving, handing off)\n- Refreshing a local working copy against the live Proof version\n\n```bash\nSLUG=\u003Cslug>\nTOKEN=\u003CaccessToken>\nLOCAL=\u003Cabsolute-path>\n\n# One read to a temp file — avoids passing markdown through $(...), which would strip trailing newlines.\nSTATE_TMP=$(mktemp)\ncurl -s \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F$SLUG\u002Fstate\" \\\n  -H \"x-share-token: $TOKEN\" > \"$STATE_TMP\"\nREVISION=$(jq -r '.revision' \"$STATE_TMP\")\n\n# Atomic write: stream .markdown bytes directly to a temp sibling, then rename.\nTMP=\"${LOCAL}.proof-sync.$$\"\njq -jr '.markdown' \"$STATE_TMP\" > \"$TMP\" && mv \"$TMP\" \"$LOCAL\"\nrm \"$STATE_TMP\"\n```\n\n`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.\n\n**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 `\u003ClocalPath>`?\" 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.\n\n## Safety\n\n- Use `\u002Fstate` content as source of truth before editing\n- During active collab use `edit\u002Fv2` (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\n- Don't span table cells in a single replace\n- Always include `by: \"ai:galeharness-cli\"` on every op and `X-Agent-Id: ai:galeharness-cli` in headers for consistent attribution\n- Reuse `baseToken` from your most recent `\u002Fstate` or `\u002Fsnapshot` read; on token errors, re-read and retry once\n","# Proof - Collaborative Markdown Editor\n\nProof is a collaborative document editor for humans and agents. It supports two modes:\n\n1. **Web API** - Create and edit shared documents via HTTP (no install needed)\n2. **Local Bridge** - Drive the macOS Proof app via localhost:9847\n\n## Identity and Attribution\n\nEvery write to a Proof doc must be attributed. Two fields carry the agent's identity:\n\n- **Machine ID (`by` on every op, `X-Agent-Id` header):** `ai:galeharness-cli` — stable, lowercase-hyphenated, machine-parseable. Appears in marks, events, and the API response.\n- **Display name (`name` on `POST \u002Fpresence`):** `GaleHarness CLI` — human-readable, shown in Proof's presence chips and comment-author badges.\n\nSet 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\u002Fhitl-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.\n\n## Human-in-the-Loop Review Mode\n\nHuman-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\u002Fhitl-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:\n\n- **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.\n- **Upstream skill handoff** — `gh-brainstorm`, `gh-ideate`, or `gh-plan` finishes a draft and hands it off for human review before the next phase, passing the file path and title explicitly.\n\n## Web API (Primary for Sharing)\n\n### Create a Shared Document\n\nNo authentication required. Returns a shareable URL with access token.\n\n```bash\ncurl -X POST https:\u002F\u002Fwww.proofeditor.ai\u002Fshare\u002Fmarkdown \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"title\":\"My Doc\",\"markdown\":\"# Hello\\n\\nContent here.\"}'\n```\n\n**Response format:**\n```json\n{\n  \"slug\": \"abc123\",\n  \"tokenUrl\": \"https:\u002F\u002Fwww.proofeditor.ai\u002Fd\u002Fabc123?token=xxx\",\n  \"accessToken\": \"xxx\",\n  \"ownerSecret\": \"yyy\",\n  \"_links\": {\n    \"state\": \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fstate\",\n    \"ops\": \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fops\"\n  }\n}\n```\n\nUse the `tokenUrl` as the shareable link. The `_links` give you the exact API paths.\n\n### Read a Shared Document\n\n```bash\ncurl -s \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F{slug}\u002Fstate\" \\\n  -H \"x-share-token: \u003Ctoken>\"\n```\n\n### Edit a Shared Document\n\nAll operations go to `POST https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F{slug}\u002Fops`\n\n**Note:** Use the `\u002Fapi\u002Fagent\u002F{slug}\u002Fops` path (from `_links` in create response), NOT `\u002Fapi\u002Fdocuments\u002F{slug}\u002Fops`.\n\n**Authentication for protected docs:**\n- Header: `x-share-token: \u003Ctoken>` or `Authorization: Bearer \u003Ctoken>`\n- Token comes from the URL parameter: `?token=xxx` or the `accessToken` from create response\n- Header: `X-Agent-Id: ai:galeharness-cli` (required for presence; include on ops for consistent attribution)\n\n**Wire-format reminder.** `\u002Fapi\u002Fagent\u002F{slug}\u002Fops` uses a top-level `type` field; `\u002Fapi\u002Fagent\u002F{slug}\u002Fedit\u002Fv2` uses an `operations` array where each entry has `op`. Do not mix — sending `op` to `\u002Fops` returns 422.\n\n**Every mutation requires a `baseToken`.** Use the `mutationBase.token` from your most recent `\u002Fstate` or `\u002Fsnapshot` read and include it in the request body. These tokens do not go stale within seconds just because another write happened; `STALE_BASE` is recoverable. If you get `BASE_TOKEN_REQUIRED`, `MISSING_BASE`, `INVALID_BASE_TOKEN`, or `STALE_BASE`, re-read and retry once. Only do a pre-mutation read when you have not read `\u002Fstate` or `\u002Fsnapshot` in the current session. See the baseToken recipe in `references\u002Fhitl-review.md`.\n\n**`Idempotency-Key` header** is recommended on every mutation and required when `\u002Fstate.contract.idempotencyRequired` is true. Reuse the same key only when retrying the exact same logical write with the same body. A changed body or fresh key is a new logical write.\n\n**Retry discipline after mutation errors — verify before retrying.**\n\n- Token errors (`STALE_BASE`, `BASE_TOKEN_REQUIRED`, `MISSING_BASE`, `INVALID_BASE_TOKEN`) are safe to auto-retry once after a fresh `\u002Fstate` or `\u002Fsnapshot`.\n- Anchor errors (`QUOTE_NOT_FOUND`, `AMBIGUOUS_QUOTE`, missing block `ref`) mean the write did not commit, but do not blindly retry. Re-read, update the quote\u002Fref, and decide whether the original intent still applies.\n- Payload errors (`422`, invalid op shape, unsupported field) should not be retried unchanged.\n- Ambiguous failures (`COLLAB_SYNC_FAILED`, `REWRITE_BARRIER_FAILED`, `PROJECTION_STALE`, `INTERNAL_ERROR`, `5xx`, network timeout, or any `202` with `collab.status: \"pending\"`) may already have written. Re-read `\u002Fstate`, verify whether the intended mark\u002Fedit exists, and retry only if it is absent.\n- Idempotency only protects retries of the exact same request. If you change the body or key, the server treats it as a new write.\n\nDuplicate marks usually come from retrying after an ambiguous failure without first verifying current state.\n\n**Comment on text:**\n```json\n{\"type\": \"comment.add\", \"quote\": \"text to comment on\", \"by\": \"ai:galeharness-cli\", \"text\": \"Your comment here\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Reply to a comment:**\n```json\n{\"type\": \"comment.reply\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"text\": \"Reply text\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Resolve \u002F unresolve a comment:**\n```json\n{\"type\": \"comment.resolve\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n{\"type\": \"comment.unresolve\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Suggest a replacement (pending — user must accept\u002Freject):**\n```json\n{\"type\": \"suggestion.add\", \"kind\": \"replace\", \"quote\": \"original text\", \"by\": \"ai:galeharness-cli\", \"content\": \"replacement text\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Suggest and immediately apply (tracked but committed — user can reject to revert):**\n```json\n{\"type\": \"suggestion.add\", \"kind\": \"replace\", \"quote\": \"original text\", \"by\": \"ai:galeharness-cli\", \"content\": \"replacement text\", \"status\": \"accepted\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n`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\"`.\n\n**Accept or reject an existing suggestion:**\n```json\n{\"type\": \"suggestion.accept\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n{\"type\": \"suggestion.reject\", \"markId\": \"\u003Cid>\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n`suggestion.resolve` is not supported — use accept or reject instead.\n\n**Bulk rewrite (whole-doc replacement):**\n```json\n{\"type\": \"rewrite.apply\", \"content\": \"full new markdown\", \"by\": \"ai:galeharness-cli\", \"baseToken\": \"\u003Ctoken>\"}\n```\n\n**Block-level edits via `\u002Fedit\u002Fv2`** (separate endpoint, separate shape):\n```bash\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F{slug}\u002Fedit\u002Fv2\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: \u003Ctoken>\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -H \"Idempotency-Key: \u003Cuuid>\" \\\n  -d '{\n    \"by\": \"ai:galeharness-cli\",\n    \"baseToken\": \"mt1:\u003Ctoken>\",\n    \"operations\": [\n      {\"op\": \"replace_block\", \"ref\": \"b3\", \"block\": {\"markdown\": \"Updated paragraph.\"}},\n      {\"op\": \"insert_after\", \"ref\": \"b3\", \"blocks\": [{\"markdown\": \"## New section\"}]}\n    ]\n  }'\n```\n\nSupported `op` kinds inside `operations`:\n\n| op | Shape |\n|----|-------|\n| `replace_block` | `{\"op\":\"replace_block\",\"ref\":\"b8\",\"block\":{\"markdown\":\"new content\"}}` |\n| `insert_after` | `{\"op\":\"insert_after\",\"ref\":\"b3\",\"blocks\":[{\"markdown\":\"new block\"}]}` |\n| `insert_before` | `{\"op\":\"insert_before\",\"ref\":\"b3\",\"blocks\":[{\"markdown\":\"new block\"}]}` |\n| `delete_block` | `{\"op\":\"delete_block\",\"ref\":\"b6\"}` |\n| `replace_range` | `{\"op\":\"replace_range\",\"fromRef\":\"b2\",\"toRef\":\"b5\",\"blocks\":[{\"markdown\":\"replacement\"}]}` |\n| `find_replace_in_block` | `{\"op\":\"find_replace_in_block\",\"ref\":\"b4\",\"find\":\"old\",\"replace\":\"new\",\"occurrence\":\"first\"}` |\n\n`\u002Fedit\u002Fv2` commits the whole `operations` array atomically and can batch dozens of block edits in one request. Read `\u002Fsnapshot` to get block `ref` IDs and the `mutationBase.token`; if any write has landed since the last snapshot, re-fetch `\u002Fsnapshot` before building block operations.\n\n**Editing while a client is connected is fine.** `\u002Fedit\u002Fv2`, `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.\n\n**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:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fbridge\u002Freport_bug` with the failing request ID, slug, and raw response. The server enriches and files an issue.\n\n### Known Limitations (Web API)\n\n- Bridge-style endpoints (`\u002Fd\u002F{slug}\u002Fbridge\u002F*`) 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 `\u002Fapi\u002Fagent\u002F{slug}\u002Fops` instead.\n\n## Local Bridge (macOS App)\n\nRequires Proof.app running. Bridge at `http:\u002F\u002Flocalhost:9847`.\n\n**Required headers:**\n- `X-Agent-Id: ai:galeharness-cli` (identity for presence)\n- `Content-Type: application\u002Fjson`\n- `X-Window-Id: \u003Cuuid>` (when multiple docs open)\n\n### Key Endpoints\n\n| Method | Endpoint | Purpose |\n|--------|----------|---------|\n| GET | `\u002Fwindows` | List open documents |\n| GET | `\u002Fstate` | Read markdown, cursor, word count |\n| GET | `\u002Fmarks` | List all suggestions and comments |\n| POST | `\u002Fmarks\u002Fsuggest-replace` | `{\"quote\":\"old\",\"by\":\"ai:galeharness-cli\",\"content\":\"new\"}` |\n| POST | `\u002Fmarks\u002Fsuggest-insert` | `{\"quote\":\"after this\",\"by\":\"ai:galeharness-cli\",\"content\":\"insert\"}` |\n| POST | `\u002Fmarks\u002Fsuggest-delete` | `{\"quote\":\"delete this\",\"by\":\"ai:galeharness-cli\"}` |\n| POST | `\u002Fmarks\u002Fcomment` | `{\"quote\":\"text\",\"by\":\"ai:galeharness-cli\",\"text\":\"comment\"}` |\n| POST | `\u002Fmarks\u002Freply` | `{\"markId\":\"\u003Cid>\",\"by\":\"ai:galeharness-cli\",\"text\":\"reply\"}` |\n| POST | `\u002Fmarks\u002Fresolve` | `{\"markId\":\"\u003Cid>\",\"by\":\"ai:galeharness-cli\"}` |\n| POST | `\u002Fmarks\u002Faccept` | `{\"markId\":\"\u003Cid>\"}` |\n| POST | `\u002Fmarks\u002Freject` | `{\"markId\":\"\u003Cid>\"}` |\n| POST | `\u002Frewrite` | `{\"content\":\"full markdown\",\"by\":\"ai:galeharness-cli\"}` |\n| POST | `\u002Fpresence` | `{\"status\":\"reading\",\"summary\":\"...\"}` |\n| GET | `\u002Fevents\u002Fpending` | Poll for user actions |\n\n### Presence Statuses\n\n`thinking`, `reading`, `idle`, `acting`, `waiting`, `completed`\n\n## Workflow: Review a Shared Document\n\nWhen given a Proof URL like `https:\u002F\u002Fwww.proofeditor.ai\u002Fd\u002Fabc123?token=xxx`:\n\n1. Extract the slug (`abc123`) and token from the URL\n2. Read the document state via the API\n3. Add comments or suggest edits using the ops endpoint\n4. The author sees changes in real-time\n\n```bash\n# Read once and reuse the mutationBase token from that response\nSTATE=$(curl -s \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fstate\" \\\n  -H \"x-share-token: xxx\")\nBASE=$(printf '%s' \"$STATE\" | jq -r '.mutationBase.token')\n# Inspect doc fields from \"$STATE\" as needed...\n\n# Comment\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fops\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: xxx\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d \"$(jq -n --arg base \"$BASE\" '{type:\"comment.add\",quote:\"text\",by:\"ai:galeharness-cli\",text:\"comment\",baseToken:$base}')\"\n\n# Suggest edit (tracked, pending)\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fops\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: xxx\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d \"$(jq -n --arg base \"$BASE\" '{type:\"suggestion.add\",kind:\"replace\",quote:\"old\",by:\"ai:galeharness-cli\",content:\"new\",baseToken:$base}')\"\n\n# Suggest and immediately apply (tracked, committed)\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002Fabc123\u002Fops\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: xxx\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d \"$(jq -n --arg base \"$BASE\" '{type:\"suggestion.add\",kind:\"replace\",quote:\"old\",by:\"ai:galeharness-cli\",content:\"new\",status:\"accepted\",baseToken:$base}')\"\n```\n\n## Workflow: Create and Share a New Document\n\n```bash\n# 1. Create\nRESPONSE=$(curl -s -X POST https:\u002F\u002Fwww.proofeditor.ai\u002Fshare\u002Fmarkdown \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"title\":\"My Doc\",\"markdown\":\"# Title\\n\\nContent here.\"}')\n\n# 2. Extract URL and token\nURL=$(echo \"$RESPONSE\" | jq -r '.tokenUrl')\nSLUG=$(echo \"$RESPONSE\" | jq -r '.slug')\nTOKEN=$(echo \"$RESPONSE\" | jq -r '.accessToken')\n\n# 3. Bind display name via presence\ncurl -s -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F$SLUG\u002Fpresence\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: $TOKEN\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d '{\"name\":\"GaleHarness CLI\",\"status\":\"reading\",\"summary\":\"Uploaded doc\"}'\n\n# 4. Share the URL\necho \"$URL\"\n\n# 5. Make edits using the ops endpoint (baseToken required)\nBASE=$(curl -s \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F$SLUG\u002Fstate\" \\\n  -H \"x-share-token: $TOKEN\" | jq -r '.mutationBase.token')\ncurl -X POST \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F$SLUG\u002Fops\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -H \"x-share-token: $TOKEN\" \\\n  -H \"X-Agent-Id: ai:galeharness-cli\" \\\n  -d \"$(jq -n --arg base \"$BASE\" '{type:\"comment.add\",quote:\"Content here\",by:\"ai:galeharness-cli\",text:\"Added a note\",baseToken:$base}')\"\n```\n\n## Workflow: Pull a Proof Doc to Local\n\nSync the current Proof doc state to a local markdown file. Used by:\n\n- HITL review end-sync (`references\u002Fhitl-review.md` Phase 5) when the doc originated from a local file\n- Ad-hoc snapshots of a Proof doc to disk (before closing the tab, archiving, handing off)\n- Refreshing a local working copy against the live Proof version\n\n```bash\nSLUG=\u003Cslug>\nTOKEN=\u003CaccessToken>\nLOCAL=\u003Cabsolute-path>\n\n# One read to a temp file — avoids passing markdown through $(...), which would strip trailing newlines.\nSTATE_TMP=$(mktemp)\ncurl -s \"https:\u002F\u002Fwww.proofeditor.ai\u002Fapi\u002Fagent\u002F$SLUG\u002Fstate\" \\\n  -H \"x-share-token: $TOKEN\" > \"$STATE_TMP\"\nREVISION=$(jq -r '.revision' \"$STATE_TMP\")\n\n# Atomic write: stream .markdown bytes directly to a temp sibling, then rename.\nTMP=\"${LOCAL}.proof-sync.$$\"\njq -jr '.markdown' \"$STATE_TMP\" > \"$TMP\" && mv \"$TMP\" \"$LOCAL\"\nrm \"$STATE_TMP\"\n```\n\n`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.\n\n**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 `\u003ClocalPath>`?\" 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.\n\n## Safety\n\n- Use `\u002Fstate` content as source of truth before editing\n- During active collab use `edit\u002Fv2` (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\n- Don't span table cells in a single replace\n- Always include `by: \"ai:galeharness-cli\"` on every op and `X-Agent-Id: ai:galeharness-cli` in headers for consistent attribution\n- Reuse `baseToken` from your most recent `\u002Fstate` or `\u002Fsnapshot` read; on token errors, re-read and retry once\n",{"name":5,"description":7,"allowed-tools":48},[40,49,50,51],"Read","Write","WebFetch","main","94fc651a7c5ff227f3e8f4b9678dc4566f535677","plugins\u002Fgaleharness-cli\u002Fskills\u002Fproof",2,"https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI","https:\u002F\u002Fgithub.com\u002FJGXC100","2026-05-19 17:04:59",{"source":8,"skillName":5,"commands":60,"prompt":70,"zipAvailable":71},[61,64,67],{"tool":62,"command":63},"npx","npx skills add JGXC100\u002FGaleHarnessCodingCLI --skill proof",{"tool":65,"command":66},"bunx","bunx skills add JGXC100\u002FGaleHarnessCodingCLI --skill proof",{"tool":68,"command":69},"pnpm","pnpm dlx skills add JGXC100\u002FGaleHarnessCodingCLI --skill proof","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Fplugins\u002Fgaleharness-cli\u002Fskills\u002Fproof\u002FSKILL.md",true,[73],{"path":74,"resourceType":75,"resourceTypeDesc":76,"sizeBytes":77,"sourceHtmlUrl":78},"references\u002Fhitl-review.md","REFERENCE","参考文档",24026,"https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Fplugins\u002Fgaleharness-cli\u002Fskills\u002Fproof\u002Freferences\u002Fhitl-review.md",[80,94,108,120,128,136],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":89,"publishedAt":43},"01M71EJT9M91X2T91N4ZPCWHN3","skill-one","Sample skill","https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fsample-plugin\u002Fskills\u002Fskill-one\u002FSKILL.md",[86],{"categoryNo":87,"categoryName":88,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[90,91,92,93],"skill one","one","sample skill","sample",{"skillNo":95,"name":96,"nameZh":6,"description":97,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":101,"publishedAt":43},"01M71EJRH7M0DGZ1QXJ9PSFMB5","disabled-skill","A skill with model invocation disabled","https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fsample-plugin\u002Fskills\u002Fdisabled-skill\u002FSKILL.md",[100],{"categoryNo":87,"categoryName":88,"taxonomyType":21,"taxonomyTypeDesc":22},[102,103,104,105,106,107],"disabled skill","a skill","with model","with","true","model",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":112,"categories":113,"keywords":115,"publishedAt":43},"01M71EJQMRH6JC9H9V5BQWM7RJ","claude-only-skill","A skill restricted to Claude Code only","https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fsample-plugin\u002Fskills\u002Fclaude-only-skill\u002FSKILL.md",[114],{"categoryNo":87,"categoryName":88,"taxonomyType":21,"taxonomyTypeDesc":22},[116,117,118,119,103],"only","claude only skill","claude only","code",{"skillNo":121,"name":122,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":125,"publishedAt":43},"01M71EJPXZ0644M41M587FVKYQ","default-skill","https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fcustom-paths\u002Fskills\u002Fdefault-skill\u002FSKILL.md",[],[126,127],"default skill","default",{"skillNo":129,"name":130,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":133,"publishedAt":43},"01M71EJP6RPF6PDAJ2SY4VMBDT","custom-skill","https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fcustom-paths\u002Fcustom-skills\u002Fcustom-skill\u002FSKILL.md",[],[134,135],"custom skill","custom",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":145,"publishedAt":43},"01M71EJK74AZ929S8GF55G5CDV","test-xcode","Build and test iOS apps on simulator using XcodeBuildMCP. Use after making iOS code changes, before creating a PR, or when verifying app behavior and checking for crashes on simulator.","https:\u002F\u002Fgithub.com\u002FJGXC100\u002FGaleHarnessCodingCLI\u002Fblob\u002Fmain\u002Fplugins\u002Fgaleharness-cli\u002Fskills\u002Ftest-xcode\u002FSKILL.md",[142],{"categoryNo":143,"categoryName":144,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",[146,147,148,149,150,151,152,153,127,106,154,155,156,25,119,157,158,159,160,161],"test","xcode","test xcode","apps","app","build and test","pr","for","xcodebuildmcp","use","scheme","changes","build","ios","name","behavior"]