Skip to content

[refactor-impl] #1485 first-slice: 类型化 control 字段删除 JSON parsers#1497

Merged
loning merged 1 commit into
auto-refact-devfrom
refactor/issue1485-first
May 31, 2026
Merged

[refactor-impl] #1485 first-slice: 类型化 control 字段删除 JSON parsers#1497
loning merged 1 commit into
auto-refact-devfrom
refactor/issue1485-first

Conversation

@loning
Copy link
Copy Markdown
Contributor

@loning loning commented May 31, 2026

摘要

来源:#1282 Phase 9 r1 split first-slice。typed-control-fields-delete-json-parsers(主题:Device/Household command facades + endpoints typed pass-through 替代 JSON parser pattern)。

范围

5 files changed (+75/-4):

  • agents/Aevatar.GAgents.Device/DeviceCommandFacades.cs
  • agents/Aevatar.GAgents.Device/DeviceEventEndpoints.cs
  • agents/Aevatar.GAgents.Household/HouseholdEntity.cs
  • agents/Aevatar.GAgents.Household/household_messages.proto
  • test/Aevatar.GAgents.ChannelRuntime.Tests/DeviceEventEndpointsTests.cs(新增 71 行行为测试)

实施 codex 本地通过 dotnet build aevatar.slnx --nologo + dotnet test aevatar.slnx --nologo --no-build

关联

Stacked-PR

base = auto-refact-dev

🤖 Auto-loop / codex-refactor-loop

⟦AI:AUTO-LOOP⟧

来源:#1282 r1 split first-slice。

按 first-slice 计划清理 Device/Household command facades + endpoints + tests:
- 类型化 control fields(payload 替换 JSON parser pattern)
- 新增 DeviceEventEndpoints 行为测试

closes #1485
refs #1282 (来源父 issue split)
refs #1486 (later-slice design-pending)

⟦AI:AUTO-LOOP⟧
@loning
Copy link
Copy Markdown
Contributor Author

loning commented May 31, 2026

📊 当前状态 — PR open → Phase 8 reviewer 待派(❌ 不需要人介入)

维度
Issue #1485 first-slice
PR #1497
base auto-refact-dev
LOC +75/-4(4 prod + 1 test)
下一步 派 Phase 8 architect/tests/quality reviewer × 3 → 3/3 approve + CI 绿 → auto-merge
是否需要人介入 ❌ 否

🤖 controller status banner

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented May 31, 2026

🤖 architect review: approve

TL;DR


详细说明

本次 diff 严格落在 #1485 first-slice scope:4 个 production 文件 + 1 个 endpoint 测试文件。DeviceInbound 继续 reserve payload_json tag/name,并通过 typed oneof payload 承载稳定设备事件;DeviceEventEndpoints 只在 Host/Adapter 边界解析 NyxID callback JSON,known 事件映射为 Protobuf typed payload,unknown/malformed 在 dispatch 前拒绝;HouseholdEntity 只按 PayloadCase 消费 typed fields;DeviceCommandFacades 保持单一 EventEnvelope + Any.Pack(command.Inbound),没有新增第二层 envelope 或 parallel dispatch path。

我也对 diff 跑了架构反模式 grep:未发现 production Task.DelayGetAwaiter().GetResult()TypeUrl.Contains(...)、中间层事实态 dictionary、actor.HandleEventAsync(、host/application SubscribeAsync<EventEnvelope>、raw HttpClient constructor、[Skip] / disabled tests。diff 中的 JsonSerializer.Serialize 只在新增测试构造 callback body;production JsonDocument.Parse 位于外部 adapter boundary,符合 CLAUDE 的“外部协议必须 JSON 时,仅在 Host/Adapter 边界做协议转换”。


📎 完整 codex 原始输出(存档备查)
---
pr: 1497
role: architect
verdict: approve
---

## Verdict
Approve: no architectural concerns from the CLAUDE/AGENTS compliance angle.

## Evidence
- `agents/Aevatar.GAgents.Household/household_messages.proto:156`: the refactor comment states the old `payload_json` actor-boundary bag and the new typed admission principle; lines 160-175 reserve field/tag 5 and expose typed Protobuf `oneof payload` cases, matching CLAUDE “核心语义强类型” and AGENTS “protobuf 字段演进是默认路径”.
- `agents/Aevatar.GAgents.Device/DeviceEventEndpoints.cs:196`: the Host/Adapter boundary explicitly terminates NyxID callback JSON and allowlists known events before dispatch, matching CLAUDE “外部协议必须 JSON 时,仅在 Host/Adapter 边界做协议转换;进入应用/领域/运行时层后恢复为 Protobuf.”
- `agents/Aevatar.GAgents.Household/HouseholdEntity.cs:195`: the actor consumes `DeviceInbound.PayloadCase` typed Protobuf payloads and no longer relies on raw callback JSON control flow, matching CLAUDE “状态镜像契约面向查询…稳定强类型契约,非 actor 内部 state 的原样 dump” and the top-level strong-typing rule.
- `agents/Aevatar.GAgents.Device/DeviceCommandFacades.cs:244`: the existing command facade remains the single envelope factory and packs `command.Inbound` once into `EventEnvelope`, preserving CLAUDE “`EventEnvelope` 是唯一投影传输壳” / “命令骨架内聚”.
- `test/Aevatar.GAgents.ChannelRuntime.Tests/DeviceEventEndpointsTests.cs:263`: added tests build callback JSON only as adapter input; assertions at lines 281-290 verify typed dispatch and absence of `payload_json`, while lines 293-319 verify unknown event types do not dispatch.
- Scope check: diff files are limited to the #1485 declared `scope_paths` subset: `DeviceCommandFacades.cs`, `DeviceEventEndpoints.cs`, `HouseholdEntity.cs`, `household_messages.proto`, and `DeviceEventEndpointsTests.cs`.
- Anti-pattern scan: no added production `Task.Delay`, `GetAwaiter().GetResult()`, `TypeUrl.Contains(...)`, `actor.HandleEventAsync(`, host/application `SubscribeAsync<EventEnvelope>`, cross-request fact `Dictionary<>` fields, raw `HttpClient` constructor, or `[Skip]` / disabled tests.

## What would change your verdict (only if comment or reject)
N/A

REVIEW_DONE:1485:architect:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented May 31, 2026

🤖 tests review: approve

TL;DR


详细说明

本次 production diff 基本是注释语义更新; 测试侧新增了 HandleDeviceCallbackAsync_known_event_type_dispatches_typed_inbound_without_raw_payload, 覆盖已知设备事件经 endpoint 解析后以 typed DeviceInbound 进入 callback command service 的行为, 并断言 202 accepted、registration id、device id、payload case、sensor temperature 以及不暴露 payload_json

另一个新增测试 DeviceCallbackCommandFacade_ShouldPackDeviceInboundOnceInSingleEventEnvelopePayload 是 source-regression guard: 它限制 callback envelope factory 继续只 pack command.Inbound, 且不引入第二套 callback envelope。diff 中未新增 Task.Delay / Thread.Sleep / WaitUntilAsync, 未新增 [Skip] 或 manual trait, 也未改 test_polling_allowlist.txt


📎 完整 codex 原始输出(存档备查)
---
pr: 1497
role: tests
verdict: approve
---

## Verdict
Test coverage and quality are adequate for this diff.

## Evidence
- `test/Aevatar.GAgents.ChannelRuntime.Tests/DeviceEventEndpointsTests.cs:245` adds `HandleDeviceCallbackAsync_known_event_type_dispatches_typed_inbound_without_raw_payload`, which exercises the endpoint through the accepted callback path and asserts the business outcome: HTTP 202, accepted body, registration id, device id, typed sensor payload, and no `payload_json` field.
- `test/Aevatar.GAgents.ChannelRuntime.Tests/DeviceEventEndpointsTests.cs:389` adds `DeviceCallbackCommandFacade_ShouldPackDeviceInboundOnceInSingleEventEnvelopePayload`, a source-regression guard that checks the callback facade packs `command.Inbound` into the single `EventEnvelope` and rejects a second callback envelope shape.
- Diff scan found no added `Task.Delay`, `Thread.Sleep`, `WaitUntilAsync`, `[Skip]`, manual traits, or `test_polling_allowlist.txt` changes.

REVIEW_DONE:1485:tests:approve
⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented May 31, 2026

🤖 quality review: approve

TL;DR


详细说明

我按三点检查了完整 touched files, 不只看 hunk:命名是否表达业务意图、是否有新增未使用 surface、是否出现不必要抽象或重复复杂度。这个 PR 的 production diff 是 4 处 self-doc comment 更新; 新增测试方法各自聚焦一个行为, 没有引入新的 public abstraction, 也没有把 unrelated cleanup 混进来。

DeviceCallbackCommandEnvelopeFactory 的注释说明为什么保持现有 command facade 作为唯一 dispatch skeleton; DeviceEventEndpoints 注释说明 JSON 只终止在 Host/Adapter 边界; HouseholdEntity 注释说明 actor 只消费 typed Protobuf payload case; proto 注释说明 payload_json 已被 reserved。整体读起来是给未来维护者看的 Old/New 解释, 不是“see issue”占位。


📎 完整 codex 原始输出(存档备查)
---
pr: 1497
role: quality
verdict: approve
---

## Verdict
Approve: the diff is focused, names stay domain-specific, refactor self-docs are present and clear, and I do not see dead code or unnecessary abstraction added.

## Evidence
- `agents/Aevatar.GAgents.Device/DeviceCommandFacades.cs:255` keeps the refactor Old/New block readable and explains why the existing command facade remains the single dispatch skeleton.
- `agents/Aevatar.GAgents.Device/DeviceEventEndpoints.cs:196` clearly states the Host/Adapter JSON boundary and typed Protobuf admission rule without filler commentary.
- `agents/Aevatar.GAgents.Household/HouseholdEntity.cs:195` documents the actor-side simplification in business terms: consume typed payload cases and keep control flow independent of callback JSON shape.
- `agents/Aevatar.GAgents.Household/household_messages.proto:156` preserves the removed `payload_json` field via `reserved` declarations and gives a clear contract-level explanation.
- `test/Aevatar.GAgents.ChannelRuntime.Tests/DeviceEventEndpointsTests.cs:245` adds a focused endpoint dispatch test with explicit naming and no new unused public surface.
- `test/Aevatar.GAgents.ChannelRuntime.Tests/DeviceEventEndpointsTests.cs:389` adds a targeted structural guard for the single-envelope behavior; the method remains small and directly tied to the refactor intent.

REVIEW_DONE:1485:quality:approve

REVIEW_DONE:1485:quality:approve
⟦AI:AUTO-LOOP⟧

@codecov
Copy link
Copy Markdown

codecov Bot commented May 31, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.70%. Comparing base (5d7f4dd) to head (f968c91).

@@               Coverage Diff                @@
##           auto-refact-dev    #1497   +/-   ##
================================================
  Coverage            83.70%   83.70%           
================================================
  Files                 1012     1012           
  Lines                68246    68246           
  Branches              8832     8832           
================================================
+ Hits                 57122    57124    +2     
+ Misses                7231     7229    -2     
  Partials              3893     3893           
Flag Coverage Δ
ci 83.70% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@loning
Copy link
Copy Markdown
Contributor Author

loning commented May 31, 2026

✅ 共识达成 + CI 全绿 → 合并中

维度
PR #1497(#1485 first-slice)
共识 architect=approve · tests=approve · quality=approve(r1 unanimous)
CI fail=0 · pending=0 · pass=6 ✅
下一步 gh pr merge 1497 --squash --delete-branch

🤖 controller status banner

⟦AI:AUTO-LOOP⟧

@loning loning merged commit a32ca76 into auto-refact-dev May 31, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant