Skip to content

feat(web): highlight resolved mentions - #137

Open
jjjhenriksen wants to merge 5 commits into
openclaw:mainfrom
jjjhenriksen:agent/clickclack-semantic-mentions
Open

feat(web): highlight resolved mentions#137
jjjhenriksen wants to merge 5 commits into
openclaw:mainfrom
jjjhenriksen:agent/clickclack-semantic-mentions

Conversation

@jjjhenriksen

@jjjhenriksen jjjhenriksen commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

What changed

  • Highlight resolvable @handle mentions in normal channel/thread messages, embedded channel/thread views, and agent commentary preambles.
  • Resolve targets from the complete paginated workspace-member set in the main app and embedded views.
  • Load member targets in the background so workspace navigation is not blocked by a serial member crawl.
  • Refresh targets after bot deletion or membership removal.
  • Re-run highlighting when rendered Markdown changes, including realtime edits.
  • Exclude Markdown links, URL-like paths, emails, and inline/code blocks.
  • Regenerate the checked-in embedded web assets.

Why

ClickClack already offers workspace people and bots in the @ composer menu, and #116 adds durable mention resolution for notification delivery. Rendered messages still showed those handles as ordinary text, making agent handoffs difficult to scan.

The decorator runs after Markdown rendering and changes only visible presentation. Message storage, delivery, and Markdown parsing are unchanged.

Codex review revisions

Addressed the six actionable findings from the Codex connector review on 1acfbb95ed:

  • complete member loading no longer blocks route application;
  • embedded channel and thread views load all workspace members;
  • mutation observation re-highlights edited/replaced Markdown;
  • slash-delimited URL paths such as /users/@alice are excluded;
  • agent commentary and expanded tool output receive the same mention treatment;
  • bot membership changes refresh the target cache.

Browser proof

Chromium loaded the branch's actual Vite-served mention resolver and renderer modules. With 30 workspace members, a message mentioning @member-29—past the old 24-item cutoff—produced a live DOM mark:

<mark data-clickclack-mention="true" data-mention-user-id="member-29">@member-29</mark>

The browser snapshot visibly showed @member-29 highlighted. The same renderer excludes URL paths and inline code. Embedded and preamble wiring is now in the production build and covered by the source/type/build checks below; no private workspace data is included in this proof.

Validation

  • node --test apps/web/src/lib/*.test.ts — 20 passed.
  • node_modules/.bin/svelte-kit sync and TypeScript typecheck — passed.
  • Vite production build — passed.
  • git diff --check — passed.
  • Commit: b5be20d.

Related to #116.

AI-assisted implementation and review.

@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Jul 31, 2026
@clawsweeper

clawsweeper Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed August 1, 2026, 1:33 PM ET / 17:33 UTC.

ClawSweeper review

What this changes

Adds presentation-only highlighting for resolvable workspace-member @handle mentions in normal chat, thread, embedded, and agent-commentary Markdown views.

Merge readiness

Blocked until stronger real behavior proof is added - 5 items remain

Keep open. Current main does not yet decorate rendered mentions, so this PR remains necessary; the supplied revisions appear to address the earlier code findings, but real after-fix proof directly covers only an ordinary message, not the embedded or agent-commentary paths the PR claims. The current TypeScript check also fails and needs a resolved run before merge.

Priority: P2
Reviewed head: b5be20da03e560784c42fd695819d5546b197a34

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The implementation is focused and the prior code findings appear addressed, but incomplete cross-view proof and the failing TypeScript check prevent a higher readiness rating.
Proof confidence 🦐 gold shrimp (3/6) Needs stronger real behavior proof before merge: The PR body shows a real Vite-served Chromium DOM result for a normal message, but it does not directly show the embedded or agent-commentary behavior claimed by the patch; add redacted runtime output or a recording for those paths and update the PR body for re-review.
Patch quality 🦐 gold shrimp (3/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs stronger real behavior proof before merge: The PR body shows a real Vite-served Chromium DOM result for a normal message, but it does not directly show the embedded or agent-commentary behavior claimed by the patch; add redacted runtime output or a recording for those paths and update the PR body for re-review.
Evidence reviewed 6 items Current main lacks the requested behavior: The ordinary message renderer applies only Markdown enhancement before inserting rendered HTML; it has no mention-decorator action or mention highlight markup.
Claimed secondary rendering paths exist separately: Current main renders agent commentary through PreambleBlock and gives embedded channel/thread views independent, capped mention-person sources, so the PR needs proof across those distinct paths rather than only the normal message renderer.
PR body contains limited live proof: The supplied PR body reports a Vite-served Chromium DOM mark for @member-29 in a normal rendered message, but it offers no directly observable after-fix result for an embedded view or agent commentary preamble.
Findings None None.
Security None None.

How this fits together

ClickClack renders stored chat and agent text as Markdown in the main application and shareable embedded views. This change derives known workspace members, decorates matching rendered text nodes, and leaves message storage and delivery unchanged.

flowchart LR
  A[Workspace member API] --> B[Mention target list]
  C[Rendered Markdown] --> D[Resolved mention decorator]
  B --> D
  D --> E[Main chat and thread views]
  D --> F[Embedded channel and thread views]
  D --> G[Agent commentary views]
Loading

Before merge

  • Add real behavior proof - Needs stronger real behavior proof before merge: The PR body shows a real Vite-served Chromium DOM result for a normal message, but it does not directly show the embedded or agent-commentary behavior claimed by the patch; add redacted runtime output or a recording for those paths and update the PR body for re-review.
  • Resolve merge risk (P1) - The TypeScript check is failing at the current PR head; its log could not be retrieved from this read-only environment, so the underlying defect remains unverified.
  • Resolve merge risk (P1) - The ordinary-message DOM result does not demonstrate the embedded channel/thread or agent-commentary paths, which use separate renderers.
  • Resolve merge risk (P1) - The local partial checkout could not hydrate the PR head or deeper historical objects because github.com DNS resolution failed; this review relies on supplied PR metadata for branch-only evidence.
  • Complete next step (P2) - This needs contributor-supplied cross-view runtime proof and a resolved TypeScript check, not an automated repair branch.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch surface 38 files affected; 396 additions, 133 deletions The feature spans main and embedded renderers plus regenerated checked-in web assets, so proof should cover both source paths and deployed asset output.

Merge-risk options

Maintainer options:

  1. Decide the mitigation before merge
    Keep the decorator presentation-only, resolve the failing TypeScript check, and add redacted runtime proof that shows the same resolved handle highlighted in an embedded view and an agent-commentary preamble before merging.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Technical review

Best possible solution:

Keep the decorator presentation-only, resolve the failing TypeScript check, and add redacted runtime proof that shows the same resolved handle highlighted in an embedded view and an agent-commentary preamble before merging.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a feature request. The PR body provides a high-confidence live ordinary-message result, but it does not provide equivalent after-fix evidence for the embedded and agent-commentary paths.

Is this the best way to solve the issue?

Yes in principle: decorating post-render Markdown against resolvable workspace members preserves storage and delivery behavior. The remaining requirement is proof that the shared approach works in each claimed renderer and a passing TypeScript check.

AGENTS.md: found, but no applicable review policy affected this item.

Codex review notes: model internal, reasoning high; reviewed against 4843afe2e8eb.

Labels

Label justifications:

  • P2: This is a bounded user-facing chat readability feature with no demonstrated message-delivery, security, or availability regression.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR body shows a real Vite-served Chromium DOM result for a normal message, but it does not directly show the embedded or agent-commentary behavior claimed by the patch; add redacted runtime output or a recording for those paths and update the PR body for re-review.

Evidence

What I checked:

  • Current main lacks the requested behavior: The ordinary message renderer applies only Markdown enhancement before inserting rendered HTML; it has no mention-decorator action or mention highlight markup. (apps/web/src/components/messages/MessageRow.svelte:566, 4843afe2e8eb)
  • Claimed secondary rendering paths exist separately: Current main renders agent commentary through PreambleBlock and gives embedded channel/thread views independent, capped mention-person sources, so the PR needs proof across those distinct paths rather than only the normal message renderer. (apps/web/src/components/messages/PreambleBlock.svelte:76, 4843afe2e8eb)
  • PR body contains limited live proof: The supplied PR body reports a Vite-served Chromium DOM mark for @member-29 in a normal rendered message, but it offers no directly observable after-fix result for an embedded view or agent commentary preamble. (b5be20da03e5)
  • Prior functional review concerns are addressed in the submitted revision: The supplied review history records six earlier findings for paging, background loading, realtime re-decoration, URL-path exclusion, embedded targets, commentary, and bot membership refresh; the current PR body explicitly describes corresponding changes in the latest revision. (b5be20da03e5)
  • Local PR-head inspection was unavailable: The read-only partial checkout attempted to hydrate the PR-head object from its promisor remote, but DNS could not resolve github.com; current-main files and supplied GitHub diff metadata were inspected instead.
  • Recent adjacent ownership trail: Available current-main history identifies Peter Steinberger and Shakker as recent contributors across the ChatApp, message-row, and embed rendering surfaces; deeper blame could not hydrate missing historical objects in this partial checkout. (apps/web/src/ChatApp.svelte:279, e455d43809a0)

Likely related people:

  • Peter Steinberger: The available path history shows recent work on the main application and web display flow, including the newest relevant available commit. (role: recent adjacent web-flow contributor; confidence: medium; commits: e455d43809a0; files: apps/web/src/ChatApp.svelte, apps/web/src/components/messages/MessageRow.svelte)
  • Shakker: The available path history contains a concentrated sequence of recent message interaction and rendering commits on the affected component family. (role: recent message-rendering contributor; confidence: medium; commits: aca7fac054e2, 77982d7577e7, 49c9aa115593; files: apps/web/src/components/messages/MessageRow.svelte, apps/web/src/components/embed/EmbedChannelView.svelte, apps/web/src/components/embed/EmbedThreadView.svelte)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Add redacted live proof for an embedded channel or thread containing a resolved mention.
  • Add redacted live proof for an agent-commentary preamble containing a resolved mention.
  • Resolve the failing TypeScript check and provide its successful rerun.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (14 earlier review cycles; latest 8 shown)
  • reviewed 2026-08-01T02:23:29.951Z sha 1acfbb9 :: needs real behavior proof before merge. :: [P2] Load complete mention targets in embedded views
  • reviewed 2026-08-01T02:29:19.106Z sha 1acfbb9 :: needs real behavior proof before merge. :: [P2] Resolve embedded highlight targets from workspace membership
  • reviewed 2026-08-01T02:39:47.897Z sha 1acfbb9 :: needs real behavior proof before merge. :: [P1] Keep route loading independent of the member crawl | [P2] Re-run highlighting after message HTML changes | [P2] Exclude slash-delimited URL paths from matches | [P2] Resolve embed targets beyond loaded participants | [P2] Highlight agent commentary preambles too | [P2] Refresh mention targets after bot membership changes
  • reviewed 2026-08-01T02:49:20.977Z sha b5be20d :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-01T04:06:07.037Z sha b5be20d :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-01T09:34:40.487Z sha b5be20d :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-01T11:27:20.692Z sha b5be20d :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-01T14:52:35.519Z sha b5be20d :: needs real behavior proof before merge. :: none

@clawsweeper clawsweeper Bot removed the proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. label Jul 31, 2026
@clawsweeper clawsweeper Bot added proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. labels Jul 31, 2026
@jjjhenriksen
jjjhenriksen marked this pull request as ready for review August 1, 2026 02:25

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1acfbb95ed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +919 to +927
do {
const page = await listWorkspaceMembersPage({
workspaceID,
cursor,
limit: 100,
});
members.push(...page.members.map((member) => member.user));
cursor = page.has_more ? page.next_cursor : undefined;
} while (cursor);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid blocking route loading on every member page

When a workspace has more than 100 members, this loop issues one request per page serially, and applyRoute awaits the entire loadWorkspaceMembers call before resolving the route target and loading its messages. Opening or switching a large workspace can therefore leave the conversation blocked behind dozens or hundreds of member-list requests; load these targets in the background or resolve only the handles needed for visible messages.

Useful? React with 👍 / 👎.

Comment on lines +928 to +929
if (serial !== workspaceMembersLoadSerial || workspaceID !== selectedWorkspaceID) return;
workspaceMemberUsers = members;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh mention targets after bot membership changes

This assignment creates a snapshot that is only refreshed when the workspace changes. The existing bot.deleted and bot.membership_removed realtime handlers reload direct conversations, moderation data, and commands but never this list, so a removed bot's old handle remains highlighted as resolvable—and a newly added or replacement bot is absent—until the user reloads or switches workspaces.

Useful? React with 👍 / 👎.

Comment on lines +89 to +93
return {
update(nextPeople: User[] = []) {
targets = mentionTargets(nextPeople);
renderMentionHighlights(node, targets);
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Re-run highlighting when rendered message HTML changes

The action updates only when mentionPeople changes, not when the element's {@html markdown(message.body)} content changes. For example, a realtime edit of a reply in the currently open thread replaces the reply HTML while the workspace people array remains unchanged, leaving mentions in the edited body unhighlighted until some unrelated people-list update or remount; observe child mutations or pass the body/version into the action.

Useful? React with 👍 / 👎.

Comment on lines +33 to +37
function mentionIsInsideURL(text: string, start: number): boolean {
const tokenStart =
Math.max(text.lastIndexOf(" ", start - 1), text.lastIndexOf("\n", start - 1)) + 1;
const prefix = text.slice(tokenStart, start);
return /^(?:www\.[^\s/]+|[A-Za-z][A-Za-z0-9+.-]*:\/\/[^\s/]+)\//u.test(prefix);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude bare URL paths from mention matches

The URL check only recognizes prefixes beginning with www. or a URI scheme. Plain URL-like paths such as /users/@alice and docs/path/@alice?tab=1 therefore highlight @alice, despite the feature's intended exclusion of URL paths; detect slash-delimited path tokens as well as fully qualified URLs.

Useful? React with 👍 / 👎.

<MessageList
{messages}
selectedChannel={channel}
{mentionPeople}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve mentions against all members in embedded views

The embedded channel passes a mentionPeople list derived only from the authors in the currently loaded message window plus the current user, capped at 24 entries; EmbedThreadView similarly uses only conversation members and loaded authors. Consequently, a valid workspace mention remains plain whenever its target has not authored one of those loaded messages, so embedded views do not consistently provide the resolved-mention treatment added here; fetch or otherwise resolve workspace targets for embeds as well.

Useful? React with 👍 / 👎.

{:else}
<QuoteBlock {message} onJump={onJumpToQuote} />
<div class="markdown" use:enhanceMarkdown>{@html markdown(message.body)}</div>
<div class="markdown" use:enhanceMarkdown use:enhanceMentions={mentionPeople}>{@html markdown(message.body)}</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Highlight mentions in agent commentary preambles

The new action is attached only in the ordinary-message branch, while coalesced agent_commentary rows take the earlier PreambleBlock branch and render their commentary Markdown with only enhanceMarkdown. A bot message such as Handing this to @alice therefore remains unhighlighted when it is displayed as a preamble, which omits the semantic treatment from the agent-handoff content this feature is intended to make scannable; pass the mention targets into PreambleBlock and enhance its commentary bodies too.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. and removed proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 1, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. labels Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant