Skip to content

feat(agent-org): [10/10] ship bounded Group projection and enable the product path #765

Description

@ShiboSheng

Effort

Delivery boundary P50 P90 Substantive files
Group projection, complete UI/E2E, locale, and measured performance rollout 2,050 review lines 3,900 review lines 20–32 plus at most 13 locale files

Delivery contract

Dependency and single goal

Strictly stack on PR 9. Delete the develop N-session merge and timestamp-guessed reply path, establish one bounded Team projection and run-scoped shared frontend store, complete cross-entry rendered E2E plus locale/performance evidence, and enable the default product path. Backend behavior and owning tests from earlier PRs cannot be deferred here.

State after merge

After performance and complete E2E gates pass, the final long-lived Team product path is enabled by default. Group feed shows each target's own message, queued/running/failed state, and exact reply. Direct conversation never enters Group. Each Team has one logical projection subscription rather than N Member Session subscriptions. Status/error copy is aligned across 13 languages. If real performance data is incomplete, this PR remains Draft and the rollout gate remains closed; code shape alone cannot claim completion.

Primary files

src/engines/ChatPanel/ChatHistory/GroupChatView/*
src/engines/ChatPanel/hooks/{useAgentOrgGroupChatHistory,useAgentOrgGroupChatLiveSessions}.ts*
src/engines/ChatPanel/InputArea/components/{AgentOrgOverviewPanel,AgentOrgTaskList}.tsx
src/i18n/locales/*/sessions.json
tests/e2e/specs/core/agent-org-*.spec.mjs
tests/e2e/support/core/agentOrgUiDriver.mjs

develop paths that must be deleted

Delete AgentOrgGroupChatLiveSessions N-Member session channels, AgentEventsTap N complete event atoms, useGroupChatMergedEvents full frontend merge, annotateRepliesToUser guessing “the first later assistant” by read_at, direct-event fallback into Group, and the controller's single-pending-message assumption. The new projection replaces these paths and cannot sit beside them as a second read source.

Implementation steps and authoritative entry points

  1. The backend provides stable keyset pages ordered by org_run_id + source=group_mention + context_sequence. An opaque cursor may use (context_sequence,item_ordinal). User bubble and assistant reply use different ordinals in the same context, while causal pairing still uses exact Inbox/EventStore IDs.
  2. Default page size is 50, maximum 100, with a response-byte cap. Fetch one context page, then batch-join source Inbox, assistant final, and Member snapshot. Use at most four SQL queries per page and no per-Member query. Exclude direct at the SQL predicate. A malformed row returns a bounded diagnostic and never substitutes a timestamp-near reply.
  3. One run-scoped shared Group store owns single-flight, coalesced push invalidation, initial/load-older/head refresh, stable-ID deduplication, and stale-generation rejection. Hidden marks dirty only; focus/reconnect performs at most one refresh; there is no interval. With zero subscribers, release listeners/timers. Bound cache TTL and retained pages.
  4. Replace the UI's single pending object with a turnIntentId map. Multi-mention renders independent target bubbles with independent Stop/Retry and no group-wide progress. Show typed conflict, queue, and target errors directly. Group copy explains: “queued by default; use the Member direct page for immediate correction.”
  5. Lifecycle, Task, settings, and direct UI belong to their owning PRs. This PR adds only cross-entry projection glue, hiding of internal enums/receipts, 13-language parity, real rendered journeys, and the rollout switch.
  6. Archive, Delete, and unmount clean projection resources. A missed push is repaired by one reconnect/focus revalidation. A failed request retains the old page and can retry. Generation guards discard late responses.

Scope boundaries

Do not retain N channels or N complete EventStores, guess replies by timestamp, rely on frontend filters for direct privacy, add Group identity/shared lifecycle, compensate for push with polling, or substitute debug endpoints for user operations. If real queries miss the budget, keep the gate closed and update the Impact Spike; do not silently loosen the budget.

Failure scenarios that must be rejected or remain bounded

  • N Members create N channels.
  • Replies are guessed by timestamp.
  • Direct enters Group.
  • One multi-Member mention is recombined into a shared bubble/lifecycle.
  • Cursor overlap duplicates messages.
  • A stale response writes after unmount.
  • A missing causal reply is replaced with someone else's reply.
  • 50 Members/10k events cause a full scan.
  • Hidden state refreshes.
  • Open/close leaks listeners or Maps.
  • Locale or internal status leaks.
  • E2E fabricates results through debug endpoints.

Acceptance and completion definition

Verify 50 Members and 10k events; O(1) Team subscription for initial and incremental reads; at most four SQL queries per page; rows visited no more than five times page limit; fixture P90 ≤ 200 ms; bounded page and bytes; no listener/timer/Map growth after 20 open/close cycles; zero hidden refresh; exact direct/Group provenance and fast-reply pairing; real rendered multi-mention, linked Inbox, direct, intervention, Pause, and Archive journeys; packaged Tauri ⌘5/Ctrl+5 for five minutes each in foreground, hidden, and multiple Idle Teams; measured Provider/runtime/Wake/SQL/request/channel/CPU/RSS; 13-language parity; and ordinary SDE Send/Queue/Force Send/Stop/Resume/Compaction regression. Only with all evidence may the performance verdict move from blocked to pass and default rollout open.

Suggested review commits — still one PR

A. Projection query/API. B. Shared store plus deletion of old N-channel paths. C. UI and locales. D. Rendered E2E, performance, and rollout. Every commit must compile and consume only PR 9's frozen wire.

Plain-language contract

Dependency

PR 9.

How it works

The backend provides keyset pages by Team, Group source, and stable context sequence, pairing replies through exact Inbox/EventStore IDs. The frontend has one shared store/subscription per Team using push, single-flight, hidden-dirty state, one focus refresh, and bounded cache. Delete the current N Member channels, N EventStores, full frontend merge, and timestamp-based reply guessing. The UI tracks each target by turnIntentId. Complete 13 languages, real E2E, and measured performance.

State after merge

The complete product is enabled by default. Group shows only Group-origin content and direct never leaks. Multi-target messages remain independent. History is paginated and one Team has one logical subscription. Rollout happens only after real performance and E2E pass; otherwise the PR remains Draft and the gate remains closed.

Boundaries

PR 10 is not where earlier missing functionality or tests are completed. Do not keep the old N-channel bypass, use polling to replace push, use debug endpoints instead of real operations, or quietly relax a missed budget.

How to test

Use 50 Members/10k events, at most four SQL queries per page, rows visited ≤ five times limit, P90 ≤ 200 ms, no listener/timer/Map growth after 20 open/close cycles, zero hidden refresh, direct/Group causal isolation, 13 languages, packaged Tauri foreground/hidden five-minute measurements, CPU/RSS/Provider/Wake/request/channel measurements, and complete ordinary-SDE regression.

Stack completion budget

P50 consists of 9,800 production review lines, 10,600 test/E2E/measurement lines, and 2,800 mechanical/delete/locale lines. The stack is expected to touch approximately 82–112 unique substantive files plus at most 26 locale files. PRs 2, 4, 7, 9, and 10 use verifiable schema/store/service/RPC/UI/test commits inside one PR; those commits are review order, not independently mergeable features.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Effort: HighUXImprovements to user experience, workflow smoothnessenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions