Skip to content

feat(discord): add persistent workspace header cards#67333

Open
marcelomediagroup wants to merge 7 commits into
NousResearch:mainfrom
marcelomediagroup:marcelomediagroup/oe178-workspace-header
Open

feat(discord): add persistent workspace header cards#67333
marcelomediagroup wants to merge 7 commits into
NousResearch:mainfrom
marcelomediagroup:marcelomediagroup/oe178-workspace-header

Conversation

@marcelomediagroup

Copy link
Copy Markdown

Summary

  • persist one workspace header card per canonical Discord workspace and edit it idempotently as metadata changes
  • preserve header identity across gateway restart with strict version and corruption handling
  • add a dry-run-first backfill command that requires explicit apply and revalidates live state
  • preserve human-renamed threads plus existing participation and session bindings

Stack dependency

Depends on #67224. This branch is based on exact reviewed head 5f84aa5.

The OE-178-only review range is:

5f84aa5..93d0277

Verification

  • full adjacent Discord and operator-card regression slice: 661 passed
  • final focused workspace-header, backfill, operator-card, send, and missed-message slice: 131 passed
  • independent Spec and Standards reviews approved
  • Ruff, Python bytecode compilation, diff, and clean-worktree checks passed

Safety

No live Discord mutation was performed. Backfill remains dry-run by default; apply requires the explicit flag and live per-candidate revalidation.

izelmarcelo and others added 7 commits July 18, 2026 23:21
The contract check used `payload["version"] != 1`, but `1.0 == 1` in
Python, so a float `1.0` (and any equal numeric) silently validated as a
v1 card. Require an exact `int` (bool already excluded) so only the
integer 1 passes.

Also replace the `test_constant_sets_match_the_values_accepted_by_the_parser`
change-detector (forbidden per AGENTS.md — froze CARD_TYPES/SEVERITIES
against literal sets) with invariants that assert the real contract: every
declared card_type/severity is accepted by the parser and values outside
the declared sets are rejected. Adds float/bool/str version rejection cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GF1F5oXakwS4N5cL8PFCme
…afely

A contract-valid operator card can still exceed Discord's embed budgets —
up to 12 fields at the 1024-char field ceiling, or a link block wider than
one field, blows past both the per-field 1024 and aggregate 6000 limits.
Discord rejects an oversized embed wholesale (HTTP 400 / code 50035),
dropping the entire message. `_build_operator_card_embed` now truncates
each part to its per-element ceiling (UTF-16 aware) and stops adding fields
once the running aggregate would overflow, so the embed is always
API-valid; the full card still reaches the operator via the plaintext
`render_operator_card_text` content that rides alongside it.

Also fix the forum thread title: it used a naive `[:100]` slice, which
counts code points, not Discord's UTF-16 code units. Route it through the
shared `_truncate_discord_component_text` helper like every other Discord
component label.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GF1F5oXakwS4N5cL8PFCme
@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins platform/discord Discord bot adapter P3 Low — cosmetic, nice to have sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 19, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #67224: this stack adds the distinct persistent Discord workspace-header and safe-backfill layer on top of that operator-card contract.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the careful persistence, corruption, and duplicate-prevention work. I found one blocking completeness gap.

Problems

  • plugins/platforms/discord/workspace_headers.py:333 adds WorkspaceHeaderStore.update_state(), but the PR provides no production caller. plugins/platforms/discord/adapter.py:6638-6643 only reads state and renders the card. The only PR-diff invocation is direct test setup at tests/gateway/test_discord_workspace_headers.py:89, so metadata changes cannot actually update the persisted header as the PR summary claims.

Suggested changes

  • Connect an explicit production metadata input to update_state() (or narrow the feature to static headers), then add an end-to-end adapter test that changes that input and verifies the tracked header is edited.

Automated hermes-sweeper review.

self._write_unlocked(workspaces)
return WorkspaceHeaderBinding(scope_key, thread_key, message_key)

def update_state(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

update_state() has no production caller in this PR: the only diff invocation is test setup, while ensure_workspace_header() only reads this state before rendering. Please wire the intended metadata producer through this method and cover that edit path, or remove/narrow the mutable metadata contract.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have platform/discord Discord bot adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-platform-windows Sweeper risk: may break or behave differently on native Windows sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants