M12: MCP comment feedback and live change events

Comments become the task queue for an attached or headless MCP client: comment.prompt returns a bounded Markdown brief, the Comments panel gains Copy for AI, and the MCP server exposes fix_comments, watch_comments, figcraft://comments and wait_for_changes. Mutating comment.* commands append to a bounded in-memory event log; the control channel's events.poll long-polls it without the UI thread, and a successful batch commits its events only if the whole batch lands. No model, network dependency, asset or file-format change.
This commit is contained in:
phonedu
2026-10-28 21:42:31 +08:00
parent 43af145a12
commit 8e6b3bf449
25 changed files with 1228 additions and 16 deletions
+20
View File
@@ -123,6 +123,26 @@ it and duplicate it:
Every command: `[{id, label, params, menu, shortcut, undoable}]`.
### `events.poll {after?, timeoutMs?, topics?, limit?}`
Wait for live changes: the app's in-memory event log records `comment.added`, `comment.replied`,
`comment.edited`, `comment.reacted`, `comment.resolved`, `comment.moved` and `comment.deleted`
(`topics`: `comments` (default), `document`, `all`). Only comment events are emitted today;
`document` and `all` are accepted for forward compatibility. Returns pending events after `after`
at once, otherwise waits up to `timeoutMs` (default 20 000, max 25 000; 0 = no wait):
```json
{"id":1,"method":"events.poll","params":{"after":41,"timeoutMs":20000}}
{"id":1,"ok":true,"result":{"events":[{"seq":42,"kind":"comment.added","document":"Checkout","path":"…","data":{"commentId":12}}],"cursor":42,"reset":false,"dropped":0}}
```
`cursor` is the sequence to pass next; `reset: true` means `after` is ahead of the log (the app
restarted) and the caller should re-read the comments; `dropped` counts events lost because `after`
is older than the retained window (1024 events). The method is answered by the control worker
against the shared log, not by the UI thread, so it does not freeze the app, use a request slot, or
need a drawn frame: it works while the window is minimised. Other requests on the same connection
wait until the poll finishes (at most 25 s); use a separate connection to keep editing meanwhile.
### `document.inspect {depth?, allPages?}`
The active document as JSON: name, path, dirty, currentPage, selection, pages (the current page's
+6
View File
@@ -469,6 +469,11 @@ No alpha blockers: the alpha gate in [`roadmap.md`](roadmap.md#alpha-gate) passe
- **Estimate:** 4–8 h.
### 19. AI features
- **Landed (2026-10-27, narrow slice without a model):** MCP agent feedback — comments as the task
queue (`comment.prompt`, **Copy for AI**, `fix_comments` / `watch_comments`,
`figcraft://comments`), a bounded in-memory event log, `events.poll` and `wait_for_changes` for
live feedback. Any MCP client can drive a headless file or an attached app; no in-app model and no
network dependency.
- **Missing:** Figma AI (first draft, rename layers, remove background, image generation and
editing, visual search, Make).
- **Estimate:** 30–60 h with openly licensed local models. **Owner decision needed.**
@@ -519,6 +524,7 @@ No alpha blockers: the alpha gate in [`roadmap.md`](roadmap.md#alpha-gate) passe
| Date | Change | Summary |
|---|---|---|
| 2026-10-27 | minor | M12: the MCP agent feedback workflow landed (comments as tasks, `comment.prompt`, Copy for AI, `fix_comments` / `watch_comments`, `figcraft://comments`, a bounded event log, `events.poll` and `wait_for_changes`). Figma AI features and local models are still not started, so gap 19's missing list and estimate stand |
| 2026-10-25 | minor | egui/eframe 0.37 verified for gap 18: the remaining limitations are unchanged. egui-wgpu 0.37 still picks an 8-bit sRGB surface with no colour-space option, so P3 colours outside sRGB still clip on screen; eframe 0.37 still gives only the main window an AccessKit adapter, so other windows have no screen-reader tree. Numbers unchanged |
| 2026-10-25 | minor | Known gaps from the #1311 review: gap 4, the export preview follows a slice's first export setting; gap 14, the scopes a paint style's color takes are FigCraft's own rule; gap 15, `proto.linkNotice` from the palette or control channel isn't saved until the next preferences save; gap 16, the file name field still renames in Dev Mode (to check against Figma first). Ranking and hours unchanged |
| 2026-10-24 | minor | Gap 24: the dot grid on board pages, dragging a connector's end to re-attach it, curved connectors and elbows around the objects they join landed; connector waypoints placed by hand stay missing. 30–60 h → 28–56 h; the ranking is unchanged |
+25
View File
@@ -323,6 +323,7 @@ Or in a project's `.mcp.json`:
| `key {key, shift, alt, cmd}` | A shortcut or key as if typed on the canvas (every default shortcut, tool keys, Escape, Delete, arrows, number keys for opacity, arrows that pan the view when nothing is selected; while editing text, the text shortcuts and then text editing keys). Keys are names like `A`, `0`, `Enter`, `ArrowLeft`, `=`, `/`, or egui's (`Plus`, `Questionmark`); `cmd` is Cmd on macOS and Ctrl elsewhere. |
| `type_text {text, id?}` | Type into the text being edited, or replace the contents of text layer `id`. |
| `inspect_ui {}` | Tool, view and status (and panels, timings and the app's `windows` when attached). |
| `wait_for_changes {after?, timeoutMs?, topics?, limit?}` | Wait for new comment events in the attached app; returns pending events at once, else waits up to `timeoutMs` (default 20 s, max 25 s). Pass the returned `cursor` back to keep watching. Headless returns immediately. |
### Starter templates
@@ -1144,6 +1145,27 @@ and opens it in the app, and `comment.next {id?, dir?, …list params}` steps to
thread of a list the same way. `comment.zoom {ids}` zooms in on a group of pins. Comment ids made in
a live session are large numbers (their creator's id space): pass them back as given.
An agent can read every open thread as one resource (`figcraft://comments`) or call
`comment.list`; `comment.prompt {ids?, page? (default "all"), filter? (default open), sort?,
query?, includeResolved?}` returns `{count, truncated, text, comments}`, where `text` is a Markdown
task brief with the document, each thread's page, frame, anchor, point, messages, replies and link,
and the instructions to fix, reply and resolve. `comments` is bounded metadata for at most 200 of
the selected threads (id, page, frame, anchor, status, link, author, preview and reply count), not
the full threads: use `comment.list` for those. The Comments panel's **Copy for AI** action uses
it. The `fix_comments` prompt runs the review loop: inspect the anchored layer, make the
smallest change (one `batch` per thread), reply with what changed, verify with a screenshot, then
resolve. Reply before resolving: `comment.reply` reopens a thread, so resolving first and replying
after leaves it open again. `auto_resolve: "no"` makes the agent reply and leave the thread for the
user. Comments are the feedback queue for any MCP client.
While attached, `wait_for_changes` long-polls the app's event log: `comment.added`, `comment.replied`,
`comment.edited`, `comment.reacted`, `comment.resolved`, `comment.moved` and `comment.deleted` carry
`{command, commentId, reply}`. Read the thread with `comment.list` after an event. A `batch` that
rolls back reports none of its steps' events. The log keeps the newest 1024 events; `reset: true`
means the cursor is ahead (the app restarted), and `dropped` counts events older than the retained
window. Headless returns immediately; the control method behind it is `events.poll` (see
[control-protocol.md](control-protocol.md)).
### Version history
Named snapshots of the document, kept in the `.figcraft` file (they persist once the file is saved;
@@ -1873,6 +1895,7 @@ tool, malformed JSON, wrong parameter types) are JSON-RPC errors. Nothing crashe
|---|---|
| `figcraft://document` | The active document (like `inspect_document` at depth 8). |
| `figcraft://commands` | The command catalog. |
| `figcraft://comments` | Every open comment thread on every page, as JSON. |
| `figcraft://node/{id}` (template) | One layer with children to depth 2. |
| `figcraft://command/{id}` (template) | One command's docs, e.g. `figcraft://command/layout.add`. |
@@ -1884,6 +1907,8 @@ tool, malformed JSON, wrong parameter types) are JSON-RPC errors. Nothing crashe
| `design_system` | `name`, `primary` |
| `landing_page` | `product` (required), `width` (default 1440), `accent` |
| `prototype_flow` | `screens` (comma-separated), `transition` |
| `fix_comments` | `page` (default "all"), `auto_resolve` (default "yes"), `author` (default "AI") |
| `watch_comments` | `minutes` (default 5) |
Each returns a step-by-step plan naming the exact tools and commands to use and how to verify.