Skip to content

feat(web): mark sessions linked to a Mattermost chat - #146

Merged
tusharbhardwaj-bk merged 1 commit into
expbkmainfrom
t3code/bunny
Aug 31, 2026
Merged

feat(web): mark sessions linked to a Mattermost chat#146
tusharbhardwaj-bk merged 1 commit into
expbkmainfrom
t3code/bunny

Conversation

@tusharbhardwaj-bk

@tusharbhardwaj-bk tusharbhardwaj-bk commented Aug 31, 2026

Copy link
Copy Markdown

Problem

The Linear/Mattermost bridge binds a session to a Mattermost thread so a human can steer it from chat, but that binding lived only in the bridge's own Postgres (mattermost_threads). Inside T3 nothing recorded it — the sidebar row looked identical whether or not replies in chat were landing in the session.

Fix

Adds mattermostThreadUrl to thread metadata, mirroring the existing linearIssueUrl manual tag end to end:

  • packages/contracts — the field on OrchestrationThread, the thread shell, the thread.meta.update command and its thread.meta-updated payload, plus a threadMattermostLink capability so an older server hides the affordances instead of failing on click.
  • apps/server — decider passthrough, both projectors, the projection_threads column via migration 1023, and every snapshot query.
  • packages/client-runtime — reducer passthrough.
  • apps/web — the badge itself.

The Mattermost mark renders in the experimental sidebar's bottom-right lane, immediately left of the provider icon, alongside the priority badge and owner avatar — the lane the request asked for.

Notes

  • The badge is a labelled span, not a link. It sits inside the row's <button>, where a nested <a> is invalid HTML and swallows row selection. Opening the conversation is a context-menu item instead.
  • Reverse states are covered: link, change, open, and remove all appear on the row menu, so a stale binding can always be cleared by hand.
  • The mark is the official Mattermost brand icon (docs/site/static/img/brand/icon-denim.svg from mattermost/mattermost), recoloured to currentColor — brand denim disappears in dark mode.
  • The bridge needs no new T3 endpoint: it already speaks thread.meta.update, so it can set this field on attach/bind. That bridge-side change is a follow-up in t3-linear-bridge-next and is not in this PR — until it lands, the badge lights up for links tagged by hand.
  • Fork surface: all new UI lives in fork-owned files (apps/web/src/components/sidebar/); every hunk in an upstream-owned file is a marked T3-CUSTOM(expbkt3) addition beside its linearIssueUrl twin. scripts/check-fork-markers.ts passes.

Verification

Typecheck clean in packages/contracts, packages/client-runtime, apps/web, apps/server (0 errors).

Targeted tests, all passing:

  • apps/web/.../MattermostThreadBadge.test.tsx — 6 new (resolver: channel/DM/permalink labels, blank + unparseable + javascript: rejection; badge: label, sizing, svg)
  • apps/server/.../decider.priority.test.ts — 2 new (set/clear, and omission leaves a live binding untouched)
  • apps/server/.../1023_ProjectionThreadsMattermostLink.test.ts — 1 new (column added)
  • Existing suites updated for the new field and re-run green: projector.test.ts (11), ProjectionSnapshotQuery.test.ts (21), threadReducer.test.ts (33)

No screenshot yet — the badge needs a thread carrying the field, which arrives with the deploy to expbkt3. I'll attach one from expbkt3.dev once it's serving this build.

Model: Claude Opus 5 (1M context), harness: T3 Code.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

The Linear/Mattermost bridge binds a session to a Mattermost thread so a
human can steer it from chat, but that binding lived only in the bridge's
own database. Inside T3 the sidebar looked identical whether or not
replies in chat were landing in the session.

Adds `mattermostThreadUrl` to thread metadata, mirroring the existing
`linearIssueUrl` tag end to end (contract, decider, both projectors,
projection column via migration 1023, client reducer), and renders the
Mattermost mark in the experimental sidebar's bottom-right lane beside
the priority badge, owner avatar and provider icon.

The badge is a labelled span rather than a link: it sits inside the row's
button, where an anchor would be invalid HTML and would swallow row
selection. Opening, changing and clearing the link live on the row's
context menu, gated on the new `threadMattermostLink` capability so an
older server shows none of it.

The bridge writes the field through the `thread.meta.update` command it
already speaks; no new T3 endpoint.

Model: Claude Opus 5 (1M context), harness: T3 Code.
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L labels Aug 31, 2026
@github-actions

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 13.6 KiB 15.1 KiB
Codex Thread snapshot wire 7.2 KiB 7.3 KiB
Codex Live turn WebSocket wire 6.4 KiB 7.8 KiB
Codex Live turn WebSocket decoded 55.7 KiB 66.4 KiB
Codex Live turn messages 11 21
Claude Total thread wire 13.6 KiB 15.1 KiB
Claude Thread snapshot wire 7.2 KiB 7.3 KiB
Claude Live turn WebSocket wire 6.4 KiB 7.8 KiB
Claude Live turn WebSocket decoded 56.5 KiB 66.4 KiB
Claude Live turn messages 11 21

Baseline: unavailable · PR result: 317f7ce · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 110.4 KiB
  • Claude decoded thread snapshot: 111.1 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@tusharbhardwaj-bk
tusharbhardwaj-bk merged commit fe0622e into expbkmain Aug 31, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant