Skip to content

feat: restyle Slack cards with a color-bar attachment grammar - #62

Merged
dnhynk merged 2 commits into
mainfrom
feat/slack-card-restyle
Oct 1, 2026
Merged

dnhynk merged 2 commits into
mainfrom
feat/slack-card-restyle

Conversation

@dnhynk

@dnhynk dnhynk commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Why

The user asked for the Slack cards to look like the trading-room project. The cards showed internal IDs, hashes and diagnostic codes, for example a Run card listing [repository_route_blocked] and twelve-character hashes.

What

Every Bridge surface now uses one card grammar (DL-074): Run, collection, Gate decision, Gate resolution, PR digest, terminal prompt and fatal-exit alert.

  • A header line {emoji} {kind} · {head}.
  • A colour-bar attachment holding the two-column fields, a 1–2 sentence note, a divider, a dashboard and a KST footer.
  • No internal IDs, hashes, code spans or diagnostic codes. The detail stays in runs --dry-run and status.
  • Unregistered or old Runs are condensed to counts per reason.
  • The fatal-exit alert keeps its owner mention, which is the user's chosen exception.
  • Action blocks stay top-level. Slack reports clicks inside attachments as message_attachment, which the parsers reject, so renderCardShell throws if an action block would end up in the attachment.
  • chat.update always sends attachments (an empty list when there are none), so old attachments never linger.
  • The render fingerprint covers attachments.
  • Living cards show a 갱신 time. The fingerprint is computed with that time blanked, so a time change alone never triggers an update.
  • Status labels in the resolution text are unchanged, and 작업 재개 still appears only after resume evidence.
  • src/channel/**, src/store/** and plugins/** are untouched.

Tests

  • typecheck and build pass.
  • About 1,700 tests across the touched and related files pass locally. The only failures are the two known fixed-pipe tests, plus the PowerShell status test that times out under load and passes alone.
  • New card-surface-scan.test.ts checks every surface for leaked IDs and codes.
  • The full suite runs in CI.

Deployment note

Every card fingerprint changes, so observed Run, collection and PR cards update once, and open Gate cards update under the write fence. Deploy with no Gate open.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VCzVZL5JSTTKjcoJyhYpzR

donghyun9282-cpu and others added 2 commits October 1, 2026 22:13
Every bridge card (Run, collection, Gate decision, decision record, PR root
and thread events, terminal prompt, fatal alert) now uses one shell from
src/slack/card.ts: a top-level header plus action blocks, and a colored
legacy attachment holding fields, an optional cause -> action note, lists,
a dashboard and a KST footer.

- Buttons stay top-level: attachment clicks arrive as message_attachment
  containers, which the Gate and direct-input handlers reject. Action
  blocks and their IDs are unchanged.
- Transport passes attachments on post, reply and update. chat.update
  always sends attachments (an empty array when absent) so an old body
  cannot survive an update.
- Cards no longer show internal IDs, hashes, paths, snake_case codes,
  mentions (except the fatal alert's owner) or links (except the PR
  button). The runs report keeps the IDs and now also prints Gate
  degraded reasons.
- Living cards (Run, collection, PR root) show a refresh time stamped at
  publish; their fingerprint is computed with the stamp blanked, so time
  alone never updates a card. Gate, resolution and terminal renderers read
  no clock.
- esc/cut/capSectionText/kst are shared instead of copied into five
  renderers; the terminal observer uses renderFingerprint.
- Docs: UX section 1, 3.1-3.3, 3.5, 5, 6; spec 5.4, 6.1, 6.3; OD-067 and
  OD-080 follow-ups; DL-074, with DL-054's observation-time rule marked
  SUPERSEDED.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCzVZL5JSTTKjcoJyhYpzR
Brings in #61; no conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCzVZL5JSTTKjcoJyhYpzR
@dnhynk
dnhynk merged commit 6a42b89 into main Oct 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants