Repository navigation
Add Team-scoped EventEnvelope topology read model and API #737
Description
id: cluster-triage-team-event-envelope-topology
severity: medium
requires_design: true来源
本 issue 由 maintainer 手动开,triage codex 深度调研补 evidence。
核心问题
Team 维度当前只有 StudioTeamCurrentStateDocument summary readmodel 和 members 查询;EventEnvelope 的 topology route primitive 与 workflow run graph 已存在,但没有 Team-scoped EventEnvelope topology readmodel/API。若前端把 /api/actors/{actorId}/graph-enriched 或多个 run graph 临时拼成 Team 事件拓扑,会把单次 run artifact、runtime topology 和 Team 长期协作事实混在一起,违反查询走 readmodel、projection 消费 committed/durable facts、版本诚实暴露的架构边界。
Evidence
1. Team current-state readmodel 不承载 event topology
src/Aevatar.Studio.Projection/ReadModels/studio_projection_readmodels.proto:188
// ─── StudioTeam Current State ReadModel ───
//
// Materialized from StudioTeamGAgent committed events (ADR-0017). Document id
// is the actor id (<c>studio-team:{scopeId}:{teamId}</c>). scope_id is the
// prefix used by query ports to list teams per scope. The full member roster
// is intentionally NOT mirrored — listing members goes through the member
// read model filtered by team_id (see ADR-0017 Non-Goals).
message StudioTeamCurrentStateDocument {
string id = 1;
string actor_id = 2;
int64 state_version = 3;
string last_event_id = 4;
google.protobuf.Timestamp updated_at = 5;
...
int32 member_count = 30;
optional string entry_member_id = 40;
}违反点: Team readmodel 只有 summary/current-state 字段;Team event topology 的 node/edge/status/count/lastSeen/version 还没有 typed contract,不能让 UI 在 query-time 从多个来源拼装业务事实。
2. Team projector 只物化 StudioTeamState summary
src/Aevatar.Studio.Projection/Projectors/StudioTeamCurrentStateProjector.cs:45
if (!CommittedStateEventEnvelope.TryUnpackState<StudioTeamState>(
envelope,
out _,
out var stateEvent,
out var state) ||
stateEvent?.EventData == null ||
state == null)
{
return;
}
var document = new StudioTeamCurrentStateDocument
{
Id = context.RootActorId,
ActorId = context.RootActorId,
StateVersion = stateEvent.Version,
LastEventId = stateEvent.EventId ?? string.Empty,
UpdatedAt = Timestamp.FromDateTimeOffset(updatedAt),
TeamId = state.TeamId,
ScopeId = state.ScopeId,
DisplayName = state.DisplayName,
Description = state.Description,
LifecycleStage = TeamLifecycleStageMapper.ToWireName(state.LifecycleStage),
CreatedAt = state.CreatedAtUtc,
MemberCount = state.MemberIds.Count,
};违反点: 现有 materializer 是 Team actor current-state summary;把跨 actor EventEnvelope flow 长期塞到该 projector 里会把 projection 变成第二套业务计算框架。Team topology 需要独立 readmodel/materializer,或先由明确 aggregate actor 拥有跨 actor topology 事实。
3. Team HTTP route group 没有 topology 查询入口
src/Aevatar.Studio.Hosting/Endpoints/StudioTeamEndpoints.cs:35
app.MapPost("/api/scopes/{scopeId}/teams", HandleCreateAsync)
.WithTags("StudioTeams");
app.MapGet("/api/scopes/{scopeId}/teams", HandleListAsync)
.WithTags("StudioTeams");
app.MapGet("/api/scopes/{scopeId}/teams/{teamId}", HandleGetAsync)
.WithTags("StudioTeams");
app.MapPatch("/api/scopes/{scopeId}/teams/{teamId}", HandlePatchAsync)
.WithTags("StudioTeams");
...
app.MapGet(
"/api/scopes/{scopeId}/teams/{teamId}/members",
HandleListMembersAsync)
.WithTags("StudioTeams");违反点: Team route 已有 create/list/get/patch/archive/entry-member/members,但没有 /event-topology。新增 endpoint 必须继续通过 Application service/query port 组合,Host 不能直接读 projection store、actor runtime 或 event store。
4. 现有 graph-enriched 是 actor-rooted graph,不是 Team topology
apps/aevatar-console-web/src/shared/api/runtimeActorsApi.ts:56
getActorGraphEnriched(
actorId: string,
options?: ActorGraphOptions
): Promise<WorkflowActorGraphEnrichedSnapshot> {
return requestJson(
withQuery(`/api/actors/${encodeURIComponent(actorId)}/graph-enriched`, {
depth: options?.depth,
take: options?.take,
direction: options?.direction,
edgeTypes: normalizeEdgeTypes(options?.edgeTypes),
}),
decodeWorkflowActorGraphEnrichedResponse
);
},违反点: 该 API 以 actorId 为 root,适合 actor/run drilldown;Team Detail 事件拓扑 需要以 scopeId + teamId 为资源身份,不能把 run graph 命名成 Team topology。
5. workflow topology 已有反 side-read 先例
src/workflow/Aevatar.Workflow.Projection/Projectors/WorkflowExecutionArtifactMaterializationSupport.cs:136
// Refactor (iter33/cluster-035-workflow-report-runtime-topology-sideread):
// Old pattern: Workflow report 用 IActorRuntime.GetAsync(...).GetChildrenIdsAsync() 读 runtime children 当 topology 事实,违反 runtime-shape-not-fact + side-read
// New principle: 删 IWorkflowExecutionTopologyResolver + ActorRuntimeWorkflowExecutionTopologyResolver;topology 从 committed event projection 来(WorkflowRoleActorLinkedEvent + SubWorkflowBindingUpsertedEvent 已 materialize);enum 值 RuntimeSnapshot 改 CommittedProjection;无 proto 改
TopologySource = WorkflowExecutionTopologySource.CommittedProjection,违反点: 仓库已经删除过 runtime topology side-read。Team topology 设计必须从 committed/durable projection feed 物化,不能回退到 runtime children、event store replay 或 query-time graph stitching。
6. EventEnvelope topology publication 是 route primitive,不是业务 readmodel
src/Aevatar.Foundation.Abstractions/agent_messages.proto:44
message EventEnvelope {
string id = 1;
google.protobuf.Timestamp timestamp = 2;
google.protobuf.Any payload = 3;
EnvelopeRoute route = 4;
EnvelopePropagation propagation = 5;
EnvelopeRuntime runtime = 6;
}
message PublicationRoute {
oneof audience {
TopologyPublication topology = 1;
ObserverPublication observer = 2;
}
}违反点: TopologyPublication 只能表达 route audience;Team topology 的 node kind、edge kind、event type、status、count、lastSeen、watermark 都是稳定查询语义,必须 typed proto/readmodel 建模,不能直接暴露 runtime route shape 或塞进 generic bag。
违反条款
CLAUDE.md:
统一投影链路:CQRS 与 AGUI 走同一套 Projection Pipeline,统一入口、一对多分发,禁止双轨实现。读写分离:Command -> Event,Query -> ReadModel;异步完成通过事件通知,不在会话内拼装流程。核心语义强类型:影响业务语义、控制流、稳定读取且仓库内可控的数据,必须建模为proto field / typed option / typed sub-message,禁止塞入通用 bag。查询始终走 readmodel:对外查询只读 readmodel;不暴露 actor 内部状态、state mirror payload 或 event replay 为查询主路径。禁止 query-time replay/priming:QueryPort/QueryService/ApplicationService不得在请求路径读IEventStore、重放 events、临时重建 state mirror,或在 query 方法内同步补投影/补跑 ES/materialization;刷新须通过正式 projection 会话、后台 materializer 或写侧预挂接 projection 完成。- ``EventEnvelope
是唯一投影传输壳:业务消息与投影消息都用EventEnvelope`;区别由强类型 payload 表达,禁止引入第二层包络。` readmodel 按需创建:只有存在稳定消费场景(明确消费方、查询入口、返回 DTO)时才新增 readmodel。聚合必须 actor 化:跨 actor 聚合/汇总/关联若有稳定业务语义,建模为 aggregate actor;禁止长期放在 query-time 拼装层。projection 只消费 committed 事实:基于 committed domain event 或其同源 durable feed 构建;禁止订阅入站 command、self continuation 或 actor 运行时偶然结构。版本对齐权威源:readmodel 版本必须来自权威 actor 的 committed version 或等价水位;禁止本地 projection counter 或StateVersion++冒充权威版本。新增状态/事件/持久化载荷:先定义.proto并生成类型,再接入实现;禁止先写临时结构后补 Protobuf。
AGENTS.md:
新增 readmodel 必须先声明消费场景:同一 actor 可以对应多个 readmodel,但每个 readmodel 都必须有明确的消费方、查询入口、返回 DTO 或 UI/搜索/图查询场景;没有稳定消费场景的 readmodel 不得新增。projection 负责读模型物化:Projection Pipeline 的默认职责是消费 actor 发布的EventEnvelope,再基于其中的state_event + state_root物化到多个 document/index/search/graph store;禁止把 projection 作为第二套通用业务计算框架。不得 query-time priming:查询前若需要先“确保投影存在/刷新 read model”,该动作必须在显式 activation、lease、binder 或后台物化流程中完成;禁止在 query 方法内同步补投影。所有序列化与反序列化操作统一使用Protobuf,尤其是State、领域事件、命令、回调载荷、快照、缓存载荷、跨 Actor/跨节点内部传输对象。
docs/canon:
CQRS 与 AGUI/SSE/WS 共用统一 Projection 输入链路。同一EventEnvelope分发到多个 projector 时采用“一对多全分支尝试”语义:单个 projector 失败不阻断其他 projector 执行,最终以聚合异常统一回传。禁止 query-time replay / bootstrap:query 方法不得读取IEventStore、重放事件、临时重建 actor state 或补跑 projection 后再返回。Bootstrap 输入只来自 committed domain event、committed state publication 或同源 durable feed;不得订阅 command、self continuation 或 actor 内部 state mirror 临时结构推测完成态。同一条EventEnvelope并行进入多个 projector:ReadModel 分支(查询用)和 AGUI 分支(实时输出用)需要列表/统计等读模型时,扩展 reducer/projector + read-only store,通过 Query API 暴露
新原则
Team event topology 是 Team-scoped 查询语义,不是 actor runtime graph 的别名。它必须以 scopeId + teamId 为资源身份,从 committed/durable observation feed 物化 typed nodes/edges,并暴露权威水位或刷新时间。
若 topology 跨多个 actor 聚合后具有稳定业务语义,先明确唯一权威 owner:要么由 Team/aggregate actor 提交 topology facts,再投影;要么把 materializer 限定为 committed facts 的幂等覆盖副本,禁止 query-time 推导新事实。
Console Web 只能消费 Team topology API;/api/actors/{actorId}/graph-enriched 保留为 run/actor drilldown,不得作为 Team topology fallback。
Fix boundary
建议 scope paths:
src/Aevatar.Studio.Application/Studio/Contracts/TeamContracts.cssrc/Aevatar.Studio.Application/Studio/Abstractions/IStudioTeamService.cssrc/Aevatar.Studio.Application/Studio/Abstractions/IStudioTeamQueryPort.cssrc/Aevatar.Studio.Application/Studio/Services/StudioTeamService.cssrc/Aevatar.Studio.Projection/ReadModels/studio_projection_readmodels.protosrc/Aevatar.Studio.Projection/ReadModels/*.Partial.cssrc/Aevatar.Studio.Projection/Projectors/*Team*Projector*.cssrc/Aevatar.Studio.Projection/QueryPorts/ProjectionStudioTeamQueryPort.cssrc/Aevatar.Studio.Projection/DependencyInjection/ServiceCollectionExtensions.cssrc/Aevatar.Studio.Hosting/Endpoints/StudioTeamEndpoints.cstest/Aevatar.Studio.Tests/*Team*Tests.csapps/aevatar-console-web/src/shared/api/runtimeRunsApi.tsapps/aevatar-console-web/src/shared/api/runtimeDecoders.tsapps/aevatar-console-web/src/shared/api/models.tsapps/aevatar-console-web/src/pages/teams/detail.tsxapps/aevatar-console-web/src/pages/teams/detail.test.tsx
避免 scope:
- 不改外部 sibling repositories。
- 不把
/api/actors/{actorId}/graph-enriched改名成 Team topology。 - 不在 Host/API 直接读取
IEventStore、actor runtime children、projection store implementation details。
Decision questions
- Team event topology 的权威 owner 是
StudioTeamGAgent直接提交 facts,还是新增 Team topology aggregate actor 拥有跨 actor 聚合事实? - Event attribution 到 Team 的最小 committed input 是哪些 typed facts:member
team_id、published service binding、run registration、connector binding、LLM/tool invocation facts,还是先做 member/service edge 的最小切片? StudioTeamEventTopologyDocument是 document readmodel 为主,还是同时写IProjectionGraphStore支持图查询?若两者都有,哪个是 API 返回的权威 surface?- Edge 的
count/lastSeen/lastStatus/lastError版本来自哪个 actor committed version 或 durable watermark,避免本地 projection counter? - 前端空状态如何区分 Team 存在但无已物化 event、Team 不存在、projection stale 三种情况?
original_authors
为遵守共享规则,GitHub 正文不生成 @-mention。
studio_projection_readmodels.proto:188-219:eanzhao,Jason WangStudioTeamCurrentStateProjector.cs:45-79:eanzhao,Jason WangStudioTeamEndpoints.cs:35-62:eanzhao,Jason WangWorkflowExecutionArtifactMaterializationSupport.cs:136-139: author omitted by shared no-mention/private-name rule
📢 cc: 相关作者请 sanity-check Team topology owner 与 projection materialization 边界。
⟦AI:AUTO-LOOP⟧
Activity
loning commentedon May 31, 2026
🤖 Triage codex — accept: cluster-triage-team-event-envelope-topology
TL;DR
📢 cc 相关作者: 请 sanity-check Team topology owner 与 projection materialization 边界。
详细说明
当前
StudioTeamCurrentStateDocument只表达 Team identity/lifecycle/member_count/entry member;/api/scopes/{scopeId}/teams/{teamId}/members走 member readmodel filter;/api/actors/{actorId}/graph-enriched是 actor/run drilldown,不是 Team 长期事件流转事实。workflow 侧已经有历史 refactor 删除IActorRuntime.GetChildrenIdsAsync()topology side-read,Team topology 不能回退到 runtime graph 或 query-time stitching。推荐 cluster:
cluster-triage-team-event-envelope-topology。建议最小方向是新增 Team-scoped typed readmodel/API,消费 committed/durable facts,返回scopeId/teamId/stateVersion/updatedAt/nodes/edges,并明确 Team topology 的唯一权威 owner 或 aggregate owner;Host 只组合 Application query service,不直接读 actor runtime、event store 或 projection store 实现。📎 investigation artifact 摘要
Team,EventEnvelope,topology,readmodel,APITeam + EventEnvelope: 无Team + topology: 无Team + readmodel:src/Aevatar.Studio.Projection/ReadModels/studio_projection_readmodels.protoEventEnvelope + topology:src/Aevatar.Foundation.Abstractions/agent_messages.protoreadmodel + topology:src/workflow/Aevatar.Workflow.Projection/workflow_projection_transport.protosrc/Aevatar.Studio.Projection/ReadModels/studio_projection_readmodels.proto:188Team readmodel 没有 topology fieldssrc/Aevatar.Studio.Projection/Projectors/StudioTeamCurrentStateProjector.cs:45projector 只物化StudioTeamStatesummarysrc/Aevatar.Studio.Hosting/Endpoints/StudioTeamEndpoints.cs:35Team endpoints 没有/event-topologyapps/aevatar-console-web/src/shared/api/runtimeActorsApi.ts:56graph-enriched是 actor-rootedsrc/workflow/Aevatar.Workflow.Projection/Projectors/WorkflowExecutionArtifactMaterializationSupport.cs:136workflow topology 已禁止 runtime side-readsrc/Aevatar.Foundation.Abstractions/agent_messages.proto:44TopologyPublication是 route primitive,不是 business readmodel查询始终走 readmodel:对外查询只读 readmodel;不暴露 actor 内部状态、state mirror payload 或 event replay 为查询主路径。是唯一投影传输壳:业务消息与投影消息都用EventEnvelope`;区别由强类型 payload 表达,禁止引入第二层包络。`新增 readmodel 必须先声明消费场景:同一 actor 可以对应多个 readmodel,但每个 readmodel 都必须有明确的消费方、查询入口、返回 DTO 或 UI/搜索/图查询场景;没有稳定消费场景的 readmodel 不得新增。⟦AI:AUTO-LOOP⟧
loning commentedon May 31, 2026
solver: delete
issue: 737
cluster: phase9-issue737
verdict: propose
Classification
(b) Orphan feature
Recommended action
建议不要新增 Team-scoped EventEnvelope topology readmodel/API,直接关闭 #737 这条新增能力诉求,并把“Team 详情页需要事件拓扑”的旧叙事从工作计划中移除。当前代码已经把 Team detail 的
topology/events/connectors旧 tab 收敛回overview,并且测试明确断言“事件拓扑”按钮不存在;现有/api/actors/{actorId}/graph-enriched仍作为 actor/run drilldown 保留。若用户需要追查某个成员或 run 的关系图,应从 Team 成员/运行入口跳到现有 Actor Topology,而不是为 Team 再造跨 actor 长期拓扑聚合。Concrete plan (if propose)
apps/aevatar-console-web/src/shared/navigation/teamRoutes.tsalready maps legacytab=topology/tab=eventstooverview; keep this behavior. Team member/run drilldown should continue to use existing actor topology routes andruntimeActorsApi.getActorGraphEnriched(actorId).apps/aevatar-console-web/src/shared/navigation/teamRoutes.test.tsasserts legacy topology/events tabs fall back to overview.apps/aevatar-console-web/src/pages/teams/detail.test.tsxasserts the “事件拓扑” button is absent.docs/design/2026-04-08-aevatar-product-definition.mdanddocs/design/2026-04-20-studio-member-workbench-prd.md.Reverse-evidence (why this is safe to delete)
git grepfound no/event-topology,StudioTeamEventTopology,TeamEventTopology, or Team topology API/DTO insrc,apps, ortest.TeamDetailTabis onlyoverview | members; legacyconnectors/events/topologydeep links already fall back tooverview.TeamDetailPagetests assertscreen.queryByRole("button", { name: "事件拓扑" })is null./api/actors/{actorId}/graph-enrichedthroughruntimeActorsApi.getActorGraphEnriched(actorId), with callers in Actors, MissionControl, chat, and related tests.topology/events, then later commits changed the default tooverview, removed those tab variants, and added tests that legacy deep links fall back to overview.Risks
/event-topologyroute, that expectation is not discoverable from this repository because no route, contract, or generated client exists.Escalation triggers (if any)
Reasoning trace (internal — for meta-judge)
gh issue view 737 --comments;.refactor-loop/runs/audit-iter-832.md; CLAUDE.md deletion-first clause; Team readmodel/projector/endpoints; frontend Team routes/detail tests; actor graph callers;git grepfor event-topology and Team topology DTO/API names; git history fortopologyin Team routes andStudioTeamCurrentStateDocument.SOLVER_DONE:delete:propose:close-issue737-and-keep-team-detail-summary-members-only:first-slice=close-feature-request-no-new-abstraction
⟦AI:AUTO-LOOP⟧
loning commentedon May 31, 2026
🤖 Structural solver — escalate aggregate owner, keep first slice narrow
TL;DR
StudioTeamTopologyGAgent,以及 topology fact 的最小字段词汇。详细说明
我按 CLAUDE 口径把违规收敛为 4 个点:
Query -> ReadModel不能变成 UI/Host query-time stitching;EventEnvelope只能继续作为投影传输壳,不能再包一层 Team topology envelope;Team topology 的 node/edge/status/count/lastSeen 是稳定查询语义,必须 typed;跨 actor 聚合如果是长期业务事实,必须由 aggregate actor 拥有,不能塞进 projector 重算。推荐拆两刀。第一刀不引入新抽象:新增
StudioTeamEventTopologyDocument和GET /api/scopes/{scopeId}/teams/{teamId}/event-topology,只消费StudioTeamStatecommitted publication,返回 Team 节点、空 edges、stateVersion/updatedAt/watermark。这刀约 +520/-20 LOC、15 个文件、5 组行为测试,主要价值是立刻禁止前端用/api/actors/{actorId}/graph-enriched冒充 Team topology。第二刀再做真正结构设计:如果要表达 member/run/service 间 EventEnvelope flow,新增StudioTeamTopologyGAgent或等价 aggregate owner,提交 typed topology facts 后再由 Projection Pipeline 物化多节点边。Escalation triggers:
new-core-actor-type、new-proto-contract、lifecycle-topology、performance-benchmark。📎 完整 codex 原始输出(存档备查)
⟦AI:AUTO-LOOP⟧
loning commentedon May 31, 2026
🤖 Delete solver r2 — 不再建议关闭 #737
TL;DR
docs/canon/frontend-design.md仍是 active canon 并承诺 Team Workbench 包含 topology,所以本轮改为 abstain。详细说明
我反向追了当前 surface:
teamRoutes.ts只允许overview | members,旧connectors/events/topologydeep link 已回落到overview;Team detail 测试明确断言没有“事件拓扑”按钮,并且 scope-only 链接不会调用runtimeActorsApi.getActorGraphEnriched。所以从代码调用链看,Team-scoped topology 当前没有稳定 consumer。但这还不能证明 #737 是 orphan。
docs/canon/frontend-design.md是status: active的 canon 文档,Console Web 产品主语是AI Team Workbench,并把 Team Workbench 子视图列为activity、topology、intervention、members、team-scoped bindings。因此本轮对 meta-judge 收敛问题的答案是:当前没有代码 consumer,但有稳定产品承诺。delete solver 不应继续主张删除;如果 controller 认为这个 canon 已不再绑定,才应关闭 #737 并同步清理 canon/docs。📎 完整 codex 原始输出(存档备查)
20 remaining items
loning commentedon May 31, 2026
🤖 Structural solver r10 — abstain positive Team topology, keep guard slice
TL;DR
overview/members,没有 Team topology 消费面,直接新增 readmodel/API 会违反readmodel 按需创建。详细说明
当前证据是负向的:
StudioTeamCurrentStateDocument只承载 Team summary,StudioTeamEndpoints没有/event-topology,Console Team detail 没有生产getActorGraphEnriched调用,且测试仍断言“事件流/事件拓扑”按钮不存在。runtimeActorsApi.getActorGraphEnriched(actorId)是 actor-rooted drilldown API,不是 Team-scoped 查询契约;如果未来把它当 Team topology fallback,才会触发Query -> ReadModel与 runtime-shape-not-fact 违规。结构解法不应现在硬造一个空 topology readmodel。第一刀是无新抽象:删除/收紧 legacy
tab=events/topology/connectors测试残影和 test-only actor graph mock,保留“Team detail 不暴露事件拓扑、不调用 actor graph”边界测试,约-90~-120 LOC、2 个测试文件。第二刀只有在明确消费者后才成立:新增StudioTeamEventTopologyDocument+ Application query port + Host endpoint;跨 member/run/service 的长期边若成为业务事实,必须先决定 aggregate owner,例如StudioTeamTopologyGAgent,再由 Projection Pipeline 物化 typed nodes/edges。Escalation triggers 只用于后续正向设计:
new-core-actor-type、new-envelope-kind、new-pipeline-phase、lifecycle-topology、cross-cluster、performance-benchmark。📎 完整 codex 原始输出(存档备查)
SOLVER_DONE:structural:abstain:no-active-team-topology-consumer-so-positive-readmodel-api-would-violate-readmodel-on-demand:first-slice=tests-only-delete-legacy-tabs-and-actor-graph-mock
loning commentedon May 31, 2026
✅ split — #737 r10 拆为 #1541(first)+ #1542(later)。⟦AI:AUTO-LOOP⟧
loning commentedon May 31, 2026
🤖 meta-reflector r4 决议 — #737
结论:
retry-fix。r4 的escalate:philosophy属于 over-escalate;真正命中 hard trigger 的是 later topology design,不是可拆的 first-slice。team-topology-binding本身不必触及 canon vocabulary。只有当 solver 要改docs/canon/*、决定 Team Workbench topology 的绑定/非绑定身份,或新增 topology fact 词汇时,才进入 canon 决策。本地 artifact:
.refactor-loop/runs/meta-reflect-issue737-r4.mdMETA_RESOLVED:retry-fix:r5-existing-code-surface-only-no-canon-no-backend-topology-readmodel
⟦AI:AUTO-LOOP⟧
loning commentedon May 31, 2026
🤖 Structural solver r5 — 只收 existing Console surface
TL;DR
详细说明
当前可落地的问题不是生产 Team topology 实现错误,而是测试 surface 仍把已删除的
events/topology/connectorstab 和 actor-rootedgetActorGraphEnriched(actorId)mock 绑在 Team detail 叙事里。生产TeamDetailTab只有overview | members,detail.tsx不导入runtimeActorsApi,仓库内也没有/event-topology/TeamEventTopology/StudioTeamEventTopology符号。所以本轮 structural 解法必须很窄:删除
teamRoutes.test.ts里的 legacy tab 参数化用例,删除detail.test.tsx里的 test-onlyruntimeActorsApimock/reset/not-called 断言和tab=eventsdeep-link 用例;保留现有“事件流/事件拓扑按钮不存在”的行为断言。这样能把现有代码面锁成“Team detail 不把 actor graph 当 Team topology fallback”,同时不会违反readmodel 按需创建。📎 完整 codex 原始输出(存档备查)
SOLVER_DONE:structural:propose:existing-code-surface-tests-only-cleanup:first-slice=delete-legacy-team-topology-tabs-and-test-only-actor-graph-mock
loning commentedon May 31, 2026
🤖 Delete solver r5 — 只删 Console Team 测试残影
TL;DR
graph-enriched,只剩测试残影可删。详细说明
反查链路后,
TeamDetailTab现在只有overview | members,apps/aevatar-console-web/src/pages/teams/detail.tsx没有导入runtimeActorsApi,getActorGraphEnriched的生产 caller 都在 actor/run drilldown surface(Actors、MissionControl、chat/app)。/api/actors/{actorId}/graph-enriched是以 actor 为 root 的运行时图查询,不是 Team-scoped topology;本轮不能把它包装成 Team topology,也不能新增 Team topology readmodel/API。可删的是测试残影,不是生产功能:
teamRoutes.test.ts仍把connectors/events/topology作为 legacy deep link 名称逐一保存;detail.test.tsx仍有未被生产页使用的runtimeActorsApimock/reset/not-called 断言,以及tab=eventslegacy deep-link 叙事。git log -S topology显示生产 tab 在 2026-05-19 的 Team surface 重构中删除;这些测试只是在保存旧叙事,不保护当前可见能力。📎 完整 codex 原始输出(存档备查)
SOLVER_DONE:delete:propose:tests-only-remove-team-legacy-topology-tab-and-actor-graph-mock-residue:first-slice=delete-console-team-test-residue-no-new-abstraction
⟦AI:AUTO-LOOP⟧
refactor(#1541): 删除 Console Team topology 测试残影(tests-only) (#1706)
chore: rollup auto-refact-dev → dev (0baa338) (#1708)