# `Issho.Engine.Comments`
[🔗](https://github.com/hattoriai/issho/blob/v0.4.0/lib/issho/engine/comments.ex#L1)

The threads of comments of a room: the engine of its comments document
(`Issho.Comments`). Its browser twin is `commentsEngine`, held to the
same cases (`test/corpus/engine_comments.json`).

The state is `%{"threads" => [thread]}`, in the order they began:

    %{
      "id" => "t1",
      "place" => %{"doc" => "board:42", "at" => %{"node" => "n7"}},
      "status" => "open",
      "resolved" => nil,
      "comments" => [
        %{
          "id" => "c1",
          "author" => %{"key" => "user:ada", "name" => "Ada", "kind" => "human"},
          "body" => "Should this go first?",
          "mentions" => ["agent:claude"],
          "at" => "2026-10-23T10:00:00Z",
          "edited" => nil,
          "reactions" => %{"👍" => ["user:ken"]}
        }
      ]
    }

A thread's place is where it is, in a component's own terms
(`Issho.Place`), or `nil` for the page as a whole. `"resolved"` is
`%{"by" => key, "at" => time}` while it is resolved.

## Operations

    %{"op" => "start", "thread" => "t1", "place" => place, "comment" => comment}
    %{"op" => "reply", "thread" => "t1", "comment" => comment}
    %{"op" => "edit", "thread" => "t1", "comment" => "c1", "body" => "...", "mentions" => [], "at" => time}
    %{"op" => "delete", "thread" => "t1", "comment" => "c1"}
    %{"op" => "react", "thread" => "t1", "comment" => "c1", "emoji" => "👍"}
    %{"op" => "unreact", "thread" => "t1", "comment" => "c1", "emoji" => "👍"}
    %{"op" => "resolve", "thread" => "t1", "at" => time}
    %{"op" => "reopen", "thread" => "t1"}
    %{"op" => "place", "thread" => "t1", "place" => place}

A new comment (`"comment"` of `start` and `reply`) is `%{"id", "author",
"body", "mentions", "at"}`. Its author's key is the key of whoever made
the transaction (the engine's `:author` option), and only its author
edits or deletes it; a reaction is the author's own. Deleting a thread's
last comment deletes the thread. Anyone who may comment resolves,
reopens and places a thread (a component places it again as its content
moves).

Concurrent changes merge: a reply, an edit, a reaction to a thread or a
comment that is gone does nothing, as does resolving a resolved thread.
The time of a comment is its writer's: `Issho.Comments` holds it, and
the author's name, to the writer's signed identity and the server's
clock before the change is accepted.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
