feat(chat): the window names every member by who they are and posts by the channel shown

Merged
DA
6d ago
+479-321

Summary

This is step 1 of 3 in replacing chat handles with the app's mention links, which the developer decided in Audit Chat page and use common app components/styles. Chat named people and agents by minted handles (@agent-36, @dean-stratakos), which nothing else in the app does. With this PR the window names each member by who they are and writes them only as mention links.

Wire and service

  • The chat read carries each member's name: a person's account name, or an agent's title (its model id until it has one).
    • Agent names come from the same query that already found each agent member's task. agentMembersOf replaces agentMemberTasks.
    • chatMemberSchema.handle is now optional, and the window no longer reads it.
  • A window post can name its place by the channel's id (chatPostRequestSchema.channelId). A DM is therefore never addressed by a member's name or handle.
    • The store already checks a channel id against the workspace, DM membership and archiving.
    • The window's to stays, so desktops already installed keep posting.

Desktop

  • Names, not handles:
    • Bylines no longer show an agent's @handle.
    • DM titles, rail rows, the closed foot and the composer label use names. A DM between two other people shows both names.
    • A member whose account or agent is gone reads "Former member" or "Former agent".
  • Composer @ list:
    • Members are offered by name, matched case-insensitively. An agent or a Luke has its task as the detail.
    • Each member, Luke included, is written as their mention link, in both the editor box and the plain fallback box.
    • No member is offered before the workspace is known, because a member can only be written as a link.
  • Dictation listens for names rather than handles.
  • Fixture: agent messages in the fixture write mention links rather than @handle text.

The agent side (tools, notices, asks and prompts) follows in PR 2. Dropping the handle column and minting follows in PR 3, at least a day after PR 2 per the contraction rule. Per the developer, old @handle text gets no compatibility handling.

Evidence

  • Typecheck is clean in features, database, service, ui, panel, host, desktop and web.
  • Lint and dead code: oxlint, biome and knip pass.
  • Tests:
    • Service: coding-agents-app.test.ts passes, 42 chat tests including the new one.
    • Desktop: desktop-chat.test.ts passes, 26 tests.
    • ui: chat-model.test.ts and chat-mention.test.ts pass, 19 tests.
    • Features: the wire tests pass, 412 tests.
  • New tests:
    • Service: the read names each person by account name and each agent as its tab does, and a post by channelId lands in that channel.
    • Desktop composer:
      • members are offered by name and written as their chip;
      • nothing is offered before the workspace is known;
      • the plain fallback box writes the member's link.
    • Model: names for members whose account or agent is gone.

Invariants

  • ./scripts/check.sh green. (CI)
  • JSON Schema goldens updated, and only for intended changes: chatMemberSchema (handle optional, name added) and chatPostRequestSchema (channelId), plus the schemas that embed them.
  • Every behavior change has, in this PR, the test that fails without it; no change-detector test added.
  • Gateway envelope goldens unchanged. (CI)
  • No new as type assertion outside the allowlisted files. (CI via anti-slop)
  • No Effect.runPromise/runSync/runFork outside the runtime edges. (CI)
  • No new raw async primitives. (CI)
  • No Effect, Stream, or Layer written as a statement and dropped. (CI)
  • Test count: +3, with the handle-pinned tests rewritten.
  • Removed: postTarget, ChatRailRow.sub (unused since the rail moved to ListRow), ChatWho.handle, and the composer's place prop.
  • No CLAUDE.md/AGENTS.md sentence names the changed parts.
  • PRIVACY.md unchanged. A person's name reaches only members of the same workspace, who already see it in its member list.
  • Package deps unchanged. (CI)
  • Barrel/door rule unaffected. (CI)

Deploy note

This is additive for installed desktops. They ignore name, still send to, and still read handle, which the service keeps sending until PR 3.

Made with Luke


Devin Review