Skip to content

refactor(presentation): share operation review semantics in TypeScript - #4364

Merged
huangruiteng merged 1 commit into
mainfrom
codex/operation-execute-ts-transaction
Sep 14, 2026
Merged

huangruiteng merged 1 commit into
mainfrom
codex/operation-execute-ts-transaction

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

摘要 / Summary

  • 在 feat(lark): add human-confirmed Goal Channel operations #4275 已交付的 human-confirmed Goal Channel operation 链路之上,把 Dashboard 与 Lark 重复的 operation review 展示语义收敛到共享纯 TypeScript reducer:operation_review_frame_v0。
  • On top of feat(lark): add human-confirmed Goal Channel operations #4275's human-confirmed Goal Channel operation flow, consolidate duplicated Dashboard/Lark operation-review presentation semantics in one pure TypeScript reducer: operation_review_frame_v0.
  • Dashboard 直接消费 reducer;Lark 每次卡片渲染通过 managed TypeScript runtime 读取一次同源 frame,之后只负责 Card 2.0 markup 与 transport。
  • Dashboard imports the reducer directly. Each Lark card render reads one shared frame through the managed TypeScript runtime, then owns only Card 2.0 markup and transport.
  • Durable lifecycle、authority、唯一 claim、outcome 与 delivery receipt 仍由 Python Chat action store 持有;本 PR 不移动 effect authority。
  • Durable lifecycle, authority, the unique claim, outcome, and delivery receipt remain owned by the Python Chat action store; this PR moves no effect authority.

动机 / Motivation

#4275 让 Dashboard 和 Lark 成为同一 operation review seam 的两个真实消费者,但两端仍各自解释 lifecycle、projection、result kind 与 delivery verification。继续复制会让“群卡显示待确认、Dashboard 显示另一状态”成为新的漂移点。仓库的 TypeScript control-plane RFC 趋势适合承载这类 provider-neutral、无副作用的 read model;它不适合接管每次 durable transition。

#4275 made Dashboard and Lark two real consumers of the same operation-review seam, but both still interpreted lifecycle, projection, result kind, and delivery verification independently. Continued duplication would allow group cards and Dashboard to disagree. The repository's TypeScript control-plane direction is a good fit for this provider-neutral, effect-free read model, but not for every durable transition.

我验证过把整个 operation lifecycle 跨到 managed TS runtime 的方案;五次 transition 会增加约 279ms(约 49%),所以本 PR 保留 Python canonical writer,只在卡片/界面渲染时支付一次共享 compiler 成本。

I also evaluated moving the entire operation lifecycle through the managed TS runtime. Five transitions added roughly 279ms (about 49%), so this revision keeps the canonical Python writer and pays the shared compiler cost only when rendering a card or UI model.

用户入口 / User entry points

  • Dashboard:直接使用共享 frame 显示 operation state、bounded fields、confirmation boundary、expiry 和 result-delivery readback。
  • Lark:confirmation 与 result card 从同一 frame 取得精确 operation ID/digest、interaction mode、result kind 与 content;provider escaping/markup/transport 仍在 adapter。
  • CLI / managed Turn:没有新增入口或第二份状态;继续使用 feat(lark): add human-confirmed Goal Channel operations #4275 的 canonical prepare/deliver/callback contracts,因此无需伴随 CLI 改造。

边界 / Boundaries

  • operation_review_frame_v0 是内部 presentation read model,不是新的 wire authority。
  • Identity drift、malformed projection、unknown lifecycle 会 fail closed,不生成 operation frame。
  • 当前 finance consumer 仍是 simulation-only;群内按钮不会授予 live order、签名、转账或 provider credential 权限。
  • RFC 与 Lark capability 文档中英文同步;packaged Dashboard 由合并后的源码重建并保留上一代资产。

验证 / Validation

Exact base: be42a4ceeaed73e06a7996cd13fe493212af79ac

Exact head: 3be30294069f8a62060365298163e615e89fcc7c

  • npm run typecheck:control-plane
  • node --test --experimental-strip-types tests/control_plane_ts/action_review_plan.test.ts tests/control_plane_ts/effect_runtime_handlers.test.ts — 14 passed
  • .venv/bin/pytest -q tests/extensions/test_lark_goal_channel_operation.py — 10 passed
  • Ruff format/check on the changed Lark adapter and tests
  • Dashboard npm run smoke:action-review-plan and production/chat npm run build
  • Clean wheel build contains both shared TS sources and exactly the two retained chat bundle generations; installing that wheel in a fresh Python 3.13 venv and invoking presentation.action_review_plan.compile passed
  • Warm managed-runtime render probe: 40 calls, median 8.442ms, p95 10.228ms, max 11.592ms
  • Standard risk-based premerge: 18/18 selected checks passed, zero warnings, public-boundary scan clean, self_merge_allowed=true

No live Lark message or real financial order was sent by this refactor validation. Deployment plus one authenticated simulation-card interaction remains the product acceptance step; real trading remains separately authorized.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

动机

#4275 已经把 human-confirmed operation 的 canonical lifecycle、claim、outcome 与 receipt 接到 Dashboard 和 Lark,但两端仍各自解释同一份 lifecycle、projection、simulation 与 result-delivery 字段。每次扩展 outcome 或 readback 规则都需要修改两个 renderer,最坏会让群卡与 Dashboard 对同一个 operation 给出不同提示。

本 PR 把这部分无副作用的展示规则收敛到共享 TypeScript read model,同时不移动 Python 的 durable writer/authority。固定 synthetic proposal 在基线 be42a4cee 与当前 head 生成的完整 Lark Card 2.0 JSON 完全相同,SHA-256 都是 1934c6ee53564dd2fcfcb67d91cc72381646b6eb70978c40ed6526bc5aea9b99。

Motivation: retire two presentation rule owners without changing the canonical operation or its authenticated group interaction.

改动思路

实现复用了原 Dashboard 的纯 compileActionReviewPlan seam,并在 loopx/control_plane/presentation/action_review_plan.ts 扩展内部 operation_review_frame_v0。它只从 canonical proposal 派生 confirmation、pending、result 三类 frame,并强制 operation ID 与 proposal ID 一致、projection 字段完整。Dashboard 直接导入;Lark 每次 card render 只通过 managed TS runtime 请求一次 frame,随后仍由 Python adapter 完成 Card 2.0 escaping、send/patch/readback。

我也验证过把 durable operation transition 整体移到 TS runtime 的替代方案;五次 transition 增加约 279ms(约 49%),因此撤回该方向。当前方案只在 Lark 渲染付出 warm median 8.442ms、p95 10.228ms,生命周期、callback provenance、唯一 claim、executor、outcome 和 result-delivery receipt 全部保留在既有 Python owner。

Approach: share only the provider-neutral pure read model; retain canonical state and effects in their existing owners.

具体改动

关键代码讲解

  • compileOperationReviewFrame(loopx/control_plane/presentation/action_review_plan.ts:104)验证 exact identity、typed lifecycle 和 bounded content,再生成 discriminated union;未知 lifecycle、ID drift 或 malformed field 都返回 undefined。
  • compileActionReviewPlan(同文件 :168)保留原 gated/stale/applied/applying/failed precedence,并只附加可选 operationFrame;operation completion 仍要求 canonical result_delivery。
  • _operation_review_frame(loopx/extensions/lark/goal_channel_operation.py:86)成为薄 bridge;confirmation/result builder 各调用一次共享 runtime,校验 frame schema/operation ID 后才渲染 provider markup。
  • workspaceProposal(apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx:546)从共享 frame 读取 title、fields、lifecycle、expiry 和 delivery verification,不再重新解析 raw operation projection。

旧 Dashboard-local reducer/types 已删除;managed handler、control-plane tsconfig、wheel package-data、双语 RFC、Lark README、Node/Python/Dashboard tests 与 packaged chat assets 同步更新。生成资产在 rebase 到 #4337 后从合并源码重建,并仅保留当前和上一代 JS bundle。

Implementation: one shared compiler now serves both shipped consumers; no parallel writer, queue, CLI, callback route, or provider state was added.

对主干的风险

最大风险是共享 compiler 改变 digest-bearing 按钮 payload、把未知 outcome 误标成完成,或让 malformed proposal 在一端继续展示。对此我用同一 fixture 做了基线/head 完整 card digest 对比;新增 negative tests 对 operation ID drift 和空 projection field 敏感;Lark tests 还断言每个 builder 只调用一次共享 frame。未来若 canonical outcome 新增种类,需要显式扩展 typed resultKind,不能从 summary 文本猜测。

验证:TypeScript typecheck 与 14 个 Node tests 通过;Lark 10 个 pytest 与 Ruff 通过;Dashboard action-review smoke 及 production/chat build 通过;clean wheel 包含 handler 与 presentation TS 源、两代受控 bundle,在全新 Python 3.13 venv 安装后真实调用 handler 通过;标准 premerge 18/18、零 warning、public-boundary clean、self_merge_allowed=true。没有发送 live Lark 消息或真实金融订单,部署后的认证 simulation-card 点击仍是产品验收,不是本 review 的合并证据。

Risk: remote required checks remain mandatory before merge, and live provider acceptance remains deliberately separate from code approval.

我的整体评价

当前 exact head 4364@3be30294069f8a62060365298163e615e89fcc7c 未发现 blocking finding。它符合 TS 重构趋势,但边界克制:TypeScript 只拥有可复用的纯展示语义,Python 继续拥有 durable state、authority、provider transport 与 receipt。相对保留两套 renderer 或把 transition 全部跨 runtime,这个切片在一致性、性能和维护成本之间更合理。

结构化 review result 已通过 capability consistency check(approval_consistent=true,无 blockers)。本结论只批准该 exact head;若 head 变化必须重新审查,合并前还要等待 GitHub required checks 全绿并运行即时 merge-readiness。

Overall assessment: the change is proportionate, domain-neutral, fail-closed, and bound to active Dashboard/Lark callers without broadening operation authority.

English verdict: APPROVE — no blocking findings on exact head 3be30294069f8a62060365298163e615e89fcc7c; merge remains subject to all required checks and immediate exact-head readiness verification.

@huangruiteng
huangruiteng merged commit a371a30 into main Sep 14, 2026
31 checks passed
@huangruiteng
huangruiteng deleted the codex/operation-execute-ts-transaction branch September 14, 2026 04:11
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.

1 participant