Skip to content

Turn status card into a live stream with @micro AI mentions#562

Merged
asim merged 2 commits intomainfrom
claude/add-wallet-transfers-74PHC
Apr 15, 2026
Merged

Turn status card into a live stream with @micro AI mentions#562
asim merged 2 commits intomainfrom
claude/add-wallet-transfers-74PHC

Conversation

@asim
Copy link
Copy Markdown
Member

@asim asim commented Apr 15, 2026

Users were already using the status card as chat — everyone posting updates that read like replies to each other. Instead of fighting it, make the stream the thing. The card is now a live scrollable feed of every status from everyone, and the AI is a first-class participant you can summon with @micro.

Data model:

  • user.UpdateProfile now always pushes the previous status onto the history (not just on change), and merges the stored history with whatever the caller passed so a freshly-constructed *Profile{} can't accidentally drop history. History cap raised 20 → 100 per user.
  • user.StatusStream(max) is new: flattens every user's current + history into one chronological feed, newest first, within the existing 7-day cutoff.

Home card:

  • Replaced the "latest status per user" render with a shared RenderStatusStream helper used by both the home page and a new /user/status/stream fragment endpoint.
  • The card body is wrapped in #home-status-wrap and followed by an inline <script> that polls /user/status/stream every 10 seconds, pauses when the tab is hidden, refreshes on focus, and preserves whatever the user is typing in the compose input.
  • The compose form submits via fetch with the CSRF header, then refreshes the stream in place — no full page reload. Falls back to a native submit on network error.
  • Removed the hover "clear status" button. Every post is appended to history, so clearing just trims the current entry and is functionally meaningless for a stream.
  • Removed the "hide card when there's nothing" branch in favour of an empty-state line so the card is discoverable on new instances.

@micro AI participant:

  • Posting a status containing @micro (word-bounded, so @microsoft and email@micro.xyz don't match) fires a background agent call whose answer is posted as a status from the existing app. SystemUserID ("micro") account. user.AIReplyHook is wired from main.go to agent.Query so the asker's wallet pays for the reply.
  • user.PostSystemStatus posts as the system user without going through CanPost / CheckPostRate, and trims to MaxStatusLength.
  • containsMention enforces word boundaries so mentions inside URLs or longer words don't trigger.

UX / mobile:

  • MaxStatusLength raised 100 → 512 (tweet-ish).
  • #home-statuses is capped at min(55vh, 420px) with overflow-y: auto and -webkit-overflow-scrolling so the card can never take the whole screen on mobile.
  • .home-status-text now wraps properly (pre-wrap + overflow-wrap: anywhere) and the row uses align-items: flex-start so the avatar stays put when text wraps.
  • Added a .home-status-system variant to tint @micro replies green.

Tests:

  • user/status_test.go covers containsMention word boundaries, StatusStream chronological order across users and history, StatusStream max cap, and UpdateProfile always appending history (including repeat text).

The production /mu --serve deployment is unaffected — this touches handlers and renderers only, no startup or config changes.

claude added 2 commits April 15, 2026 21:03
Users were already using the status card as chat — everyone posting
updates that read like replies to each other. Instead of fighting
it, make the stream the thing. The card is now a live scrollable
feed of every status from everyone, and the AI is a first-class
participant you can summon with @micro.

Data model:
- user.UpdateProfile now always pushes the previous status onto the
  history (not just on change), and merges the stored history with
  whatever the caller passed so a freshly-constructed *Profile{}
  can't accidentally drop history. History cap raised 20 → 100 per
  user.
- user.StatusStream(max) is new: flattens every user's current +
  history into one chronological feed, newest first, within the
  existing 7-day cutoff.

Home card:
- Replaced the "latest status per user" render with a shared
  RenderStatusStream helper used by both the home page and a new
  /user/status/stream fragment endpoint.
- The card body is wrapped in #home-status-wrap and followed by an
  inline <script> that polls /user/status/stream every 10 seconds,
  pauses when the tab is hidden, refreshes on focus, and preserves
  whatever the user is typing in the compose input.
- The compose form submits via fetch with the CSRF header, then
  refreshes the stream in place — no full page reload. Falls back
  to a native submit on network error.
- Removed the hover "clear status" button. Every post is appended
  to history, so clearing just trims the current entry and is
  functionally meaningless for a stream.
- Removed the "hide card when there's nothing" branch in favour of
  an empty-state line so the card is discoverable on new instances.

@micro AI participant:
- Posting a status containing @micro (word-bounded, so @microsoft
  and email@micro.xyz don't match) fires a background agent call
  whose answer is posted as a status from the existing app.
  SystemUserID ("micro") account. user.AIReplyHook is wired from
  main.go to agent.Query so the asker's wallet pays for the reply.
- user.PostSystemStatus posts as the system user without going
  through CanPost / CheckPostRate, and trims to MaxStatusLength.
- containsMention enforces word boundaries so mentions inside URLs
  or longer words don't trigger.

UX / mobile:
- MaxStatusLength raised 100 → 512 (tweet-ish).
- #home-statuses is capped at min(55vh, 420px) with overflow-y: auto
  and -webkit-overflow-scrolling so the card can never take the
  whole screen on mobile.
- .home-status-text now wraps properly (pre-wrap + overflow-wrap:
  anywhere) and the row uses align-items: flex-start so the avatar
  stays put when text wraps.
- Added a .home-status-system variant to tint @micro replies green.

Tests:
- user/status_test.go covers containsMention word boundaries,
  StatusStream chronological order across users and history,
  StatusStream max cap, and UpdateProfile always appending history
  (including repeat text).

The production /mu --serve deployment is unaffected — this touches
handlers and renderers only, no startup or config changes.
Limit how many statuses are shown on the home card to stop the feed
from becoming a scroll-wall. Two caps apply:

- StatusStreamMax (default 30, STATUS_STREAM_LIMIT to override) —
  total entries in the visible stream. Past ~30 the scroll becomes
  noise rather than signal and the card stops feeling live.

- StatusStreamPerUser (default 10, STATUS_STREAM_LIMIT_PER_USER to
  override) — how many entries any one user can contribute to the
  visible window. Without this, a single chatty user or a long
  @micro conversation would flood the feed and push everyone else
  off. Applied to each user's list (newest-first) BEFORE the
  chronological merge so older entries from flooders can't displace
  more recent entries from quieter users.

Exposed via StatusStreamCapped(maxTotal, maxPerUser) so future
callers (profile history pages, admin views) can pick different
shapes without re-implementing.

Test coverage: new TestStatusStream_PerUserCapPreventsFlood builds a
profile for Alice with 20 recent entries and Bob with 1, verifies
Alice contributes at most 3 when cap is 3/user and that Bob's single
entry still appears.
@asim asim merged commit 5024058 into main Apr 15, 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