mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-30 21:36:46 -06:00
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:
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user