feat(periodic-report): optional calendar settings and capability handoff - #4263
Conversation
49f5e32 to
91d4be2
Compare
Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
…eipts Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
91d4be2 to
c492d14
Compare
Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
动机
该 PR 为 periodic-report 增加可选 daily/weekly calendar schedule,并把窗口冻结、重启恢复、配置重验证和 capability handoff 接入现有 editorial → generation → delivery-Todo 流程。省略 schedule 时应保持原有 stage-only 行为,同时让机器与 Goal 配置可控。
改动思路
cadence.py 负责 timezone/频率规范化和 DST 边界,cadence_journal.py 与 cadence_runtime.py 负责一次性窗口 admission、reporter 选举和 pending intent;配置 UI/API 只表达 subscription,内容生成与发送继续由 periodic-report 现有 owner 负责。变更后仍不自动发起 live Lark delivery,也不把 handoff 伪装成 host transaction。
具体改动
关键代码讲解
normalize_report_cadence限制 DAILY/WEEKLY 单次 occurrence,并验证 ZoneInfo 与 canonical RRULE。periodic_report_cadence_hooks在 turn-start 重读 Goal/注册 reporter,恢复未完成窗口且防止第二个 reporter。cadence_journal/pending_intent保存窗口与 publication cursor,配置变化或 reporter 消失时 fail-closed。periodic-report-schedule-field.tsx和 capability configuration API 提供 calendar on/off、时区和频率设置。
对主干的风险
我在独立 head 上运行 cadence、journal、pending-intent 三组 focused suite,共 71 个测试通过,覆盖无效 RRULE、DST、重启、配置变更和 replay。PR 的 required windows-powershell 与 merge-gate 仍失败,此外该 PR 触及约 1,957 行、42 个文件的 runtime/API/UI/docs 面,完整 packaged dashboard 和 Windows 证据必须在合并前闭合。最小修复是先定位两个 required check,再补齐跨平台和打包入口验证;不能以本地 focused suite 替代。
我的整体评价
REQUEST_CHANGES。功能边界和复用方向合理,且保留了显式 follow-up;但当前红色 required checks 与较大变更面使 exact head 尚不可合并。审阅 head:f03e7399625f3861fba6a323d548bb8d3f138c23。
English verdict: REQUEST_CHANGES — head f03e739. 71 focused cadence tests pass, but windows-powershell and merge-gate fail on this broad runtime/API/UI change; diagnose and rerun before merge.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)审阅 exact head: 动机这个 PR 有明确且有价值的产品目标:让 periodic-report 从“只能在阶段/人工触发”进入可选的日/周窗口,并把重启、配置变更、reporter 选举和 publication cursor 纳入 durable admission。它直接补齐了后续 Goal Channel 周报自动化所需的时间触发与一次性窗口边界。省略 schedule 时仍应保持 stage-only 行为,这是正确的 default-off 方向。 但它不是完整的无人值守周报交付:PR 自己也明确没有 live Lark send,managed-Turn editorial/generation/recovery adapter 仍是 follow-up。因此它的价值是基础设施闭环的一半,而不是“周报已经自然发送”。 改动思路配置 API/UI 只表达 machine/Goal subscription; 这复用了现有 periodic-report owner、profile/schema、capability hook、Turn envelope、publication cursor 和 delivery Todo,没有新 Automation 或 sink。provider-neutral handoff 只准备受约束的 capability action,不宣称拥有 host transaction 或 Lark 发送权限。 具体改动关键代码讲解
此外,Turn/loop controller/envelope 新增 对主干的风险P1:Windows 安装后真实 quota 入口失败exact head 的 required P1:评审能力版本不兼容本机按 范围与验证风险179 项 focused Python 测试通过,23 项 TypeScript contract 测试通过;hosted dashboard/build、Linux shards、Stage2C 和 Sonar 通过,但 Windows required check 失败、merge-gate 失败。本机 exact worktree 没有安装 default-off、disabled schedule 和 stage-only 分支有测试,但应补一条跨入口 base/head 对照:机器未配置、Goal 显式 off、Goal 继承 machine default 三种状态都要证明不会注册 hook、不会占 quota、不会产生 journal side effect。协议命名目前基本保持 provider-neutral,不过应继续明确 capability handoff 是“准备/要求读取”,不是 Agent actor lifecycle 或发送授权。 最小修复
我的整体评价REQUEST_CHANGES。 方向有价值,而且 cadence normalization、durable window、replay/fail-closed 与 provider-neutral handoff 是 Goal Channel 周报能力的必要基础;但它当前不是完整周报产品,且真实 Windows 安装入口失败,主干 required gate 为红。评审 packet 还落后于当前 policy revision,不能批准。修复 Windows 合同、重新生成 revision 3 evidence 并补齐跨入口 default-off 对照后,值得继续推进;合并后仍需把 managed Turn 的编辑/生成/发送/恢复作为独立交付验收。 English verdict: REQUEST_CHANGES — exact head |
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
动机
该 PR 为 periodic-report 增加可选 daily/weekly calendar schedule,并把窗口冻结、重启恢复、配置重验证和 capability handoff 接入现有 editorial → generation → delivery-Todo 流程。省略 schedule 时应保持原有 stage-only 行为,同时让机器与 Goal 配置可控。
改动思路
cadence.py 负责 timezone/频率规范化和 DST 边界,cadence_journal.py 与 cadence_runtime.py 负责一次性窗口 admission、reporter 选举和 pending intent;配置 UI/API 只表达 subscription,内容生成与发送继续由 periodic-report 现有 owner 负责。变更后仍不自动发起 live Lark delivery,也不把 handoff 伪装成 host transaction。
具体改动
关键代码讲解
normalize_report_cadence限制 DAILY/WEEKLY 单次 occurrence,并验证 ZoneInfo 与 canonical RRULE。periodic_report_cadence_hooks在 turn-start 重读 Goal/注册 reporter,恢复未完成窗口且防止第二个 reporter。cadence_journal/pending_intent保存窗口与 publication cursor,配置变化或 reporter 消失时 fail-closed。periodic-report-schedule-field.tsx和 capability configuration API 提供 calendar on/off、时区和频率设置。
对主干的风险
我在独立 exact head 上运行 cadence、journal、pending-intent、configuration、delivery 和 turn-controller focused suite,共 169 个 Python 测试通过;TypeScript capability_hooks.test.ts/turn_envelope.test.ts 共 23 个通过,Ruff 也通过,覆盖无效 RRULE、DST、重启、配置变更、replay、配置 UI 和 capability handoff。PR 的 required windows-powershell 与 merge-gate 仍失败:Windows 日志显示 quota 子进程返回 JSON status:"skip" 且退出码 1,merge-gate 因 required checks 未闭合而失败。该 PR 触及约 1,957 行、42 个文件的 runtime/API/UI/docs 面,完整 packaged dashboard 和 Windows 证据必须在合并前闭合。最小修复是先定位两个 required check,再补齐跨平台和打包入口验证;不能以本地 focused suite 替代。
我的整体评价
REQUEST_CHANGES。功能边界和复用方向合理,且保留了显式 follow-up;但当前红色 required checks 与较大变更面使 exact head 尚不可合并。审阅 head:f03e7399625f3861fba6a323d548bb8d3f138c23。
English verdict: REQUEST_CHANGES — head f03e739. 169 Python and 23 TypeScript focused tests plus Ruff pass, but windows-powershell (quota status skip/exit 1) and merge-gate fail on this broad runtime/API/UI change; diagnose and rerun before merge.
…-cadence Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com> # Conflicts: # loopx/cli_commands/turn_rendering.py # loopx/control_plane/quota/turn_envelope.ts # tests/control_plane_ts/turn_envelope.test.ts
…-cadence Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
…-cadence Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
审阅 exact head:cefdbcdf629bb75cf0a5ece0765200eab83736d0(已同步主干 b9e8c74d)。
动机
4263 解决的是一个真实的能力缺口:periodic-report 原先支持会话/阶段触发,但没有可选的日/周日历配置、可重启恢复的窗口 admission,也没有把日历触发安全地接入现有 Turn/intent 链路。没有 durable window 和 publication cursor 绑定时,漏唤醒、重启、配置变更或 reporter 重排都可能造成重复、静默改投或把未完成周期误当成已发布。
最近的更小修复(只加 host Automation 或内存 timer)只能解决唤醒,不能解决这些状态与权限问题,还会形成第二个调度/投递权威。当前实现复用既有 profile、trigger decision、configuration owner、turn-start hook、pending-intent 和 publication cursor;新增的 cadence journal 只承担不可约的“冻结窗口身份”,不新增进度游标、sink 或发送授权。
改动思路
入口仍是 Personal Workspace 的 machine/Goal capability settings,以及已有 quota/turn executing wake。normalize_report_cadence 规范化 IANA 时区和受支持的 DAILY/WEEKLY RRULE;periodic_report_cadence_hooks 先检查 Goal 生命周期、有效订阅和 registered Agent;admit_cadence_window 在 mutation lock 内重新读取 live state,冻结最近已完成的半开区间并保留 reporter、subscription revision、profile digest。后续只投影一个 typed capability action/read,交给既有 editorial → generation → delivery continuation;只有 verified publication cursor 才确认已覆盖 trigger。
周报和自动汇报不是二选一的两套产品,而是同一 capability 下的两种 trigger mode:cadence_digest 回顾过去已完成的 [start,end),且 end_at <= generated_at;exception_update/milestone_update 则由 blocker、recovery、decision、outcome 或 milestone 驱动,window 是事件证据上下文,不隐含“一周”。两者共享 trigger decision、generation bundle、sink receipts 和 cursor;同一唤醒同时出现 calendar boundary 与 material event 时只生成一次,优先级更高的事件选择 report kind。late facts 进入下一次更新或显式 correction,不静默改写已验证周报。
具体改动
关键代码讲解
loopx/capabilities/periodic_report/cadence.py:18的normalize_report_cadence只接受一个 daily/weekly occurrence,校验 timezone、BYDAY/BYHOUR/BYMINUTE,并把 RRULE 规范化;它不创建 Automation、不写状态。loopx/capabilities/periodic_report/cadence_journal.py:94的admit_cadence_window与 consumption 共用 mutation lock,校验 window digest,恢复时先检查现有 publication cursor;未完成且已产生 artifact 的窗口不会因配置/注册变化被静默替换,前驱会被归档。loopx/capabilities/periodic_report/cadence_runtime.py:20的periodic_report_cadence_hooks绑定现有 turn-start/quota 入口,保留 frozen reporter,重读 live Goal/subscription,并只返回empty/observed/unavailable加 required capability-read,不执行外部读写。loopx/capabilities/periodic_report/core.py:181的_validate_report_window_for_trigger将 cadence digest 明确限制为 retrospective;未来结束的 calendar window fail closed,而 event update 保持自己的 bounded evidence semantics。docs/reference/protocols/periodic-report-v0.md:115明确记录两种模式、共享 receipt/cursor、coalescing、late-fact 处理,以及 calendar 不是 unattended managed-Turn editorial/delivery adapter。
整体 exact base..head 为 44 个文件、2047 additions/43 deletions,包含 runtime/API、前端设置与打包资源、协议文档和回归测试。变更仍沿用现有 UI/API projection,未新增第二套 chat/Lark source of truth。
对主干的风险
没有 blocking finding。已验证的主要负路径包括:disabled/null schedule、stopped/paused/archived Goal、无 registered/elected reporter、损坏或冲突 journal、配置/reporter 漂移、重复唤醒、以及 cadence_digest 的 period_window.end_at > generated_at。这些路径分别保持 stage-only/no mutation、显式 unavailable、fail closed 或 ValueError;不会生成第二份报告,也不会把 admission 当成 delivery。
验证结果:167 个 focused Python tests、24 个 TypeScript contract tests 通过;exact head 的 Sign-off、dependency review、build、dashboard acceptance、kernel checks、全部 Python shards、Stage2C、Windows PowerShell、macOS/Windows desktop、Sonar 和 merge-gate 全部通过。base b9e8c74d 与 exact head 的 periodic-report inspect-profile --preset weekly 都是 exit 0、2500-byte JSON、同一 sha256,证明无 schedule 的既有 profile 路径保持不变。
本机 premerge canary 仍会报告 dashboard_status_json 18,930 > 18,500;同一失败在干净主干复现,是既有 harness budget debt,不是 4263 引入的回归,也不阻断已通过的仓库 merge-gate。Live Lark send/readback 和 fully unattended managed-Turn editorial/generation/recovery 没有被本 PR 宣称或伪装成交付;它们应作为独立 adapter PR 验收。
我的整体评价
APPROVE。 这是与问题规模相称的 cohesive 基础设施切片:calendar digest 与 automatic event update 共享一个 trigger/receipt/cursor 模型,周报确实覆盖过去完成周期,且默认关闭路径不改变既有 stage/manual 行为。实现保持 provider-neutral、权限边界清晰,主干/跨平台 required checks 和 exact-head evidence 均为绿。后续应单独交付 managed-Turn editorial adapter 与 live Lark readback/recovery,不应把它们隐含回填到本 PR。
English verdict: APPROVE — exact head cefdbcdf629bb75cf0a5ece0765200eab83736d0 is reviewed after synchronizing main at b9e8c74d. The change keeps calendar digests retrospective over completed half-open windows, treats automatic updates as event-bounded modes, coalesces both through one trigger/receipt/cursor path, and preserves default-off stage/manual behavior. Focused Python (167), TypeScript (24), Windows/macOS, all shards, Sonar, and merge-gate checks pass. No blocking finding; live Lark delivery and fully unattended managed-Turn editorial recovery remain explicit follow-up adapters.
…-cadence Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <huangruiteng@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
审阅 exact head:611e06513ab57847ee706f335e9acd1ffa677812(已同步主干 f88aae3a)。
动机
4263 解决的是一个真实的能力缺口:periodic-report 原先支持会话/阶段触发,但没有可选的日/周日历配置、可重启恢复的窗口 admission,也没有把日历触发安全地接入现有 Turn/intent 链路。没有 durable window 和 publication cursor 绑定时,漏唤醒、重启、配置变更或 reporter 重排都可能造成重复、静默改投或把未完成周期误当成已发布。
最近的更小修复(只加 host Automation 或内存 timer)只能解决唤醒,不能解决这些状态与权限问题,还会形成第二个调度/投递权威。当前实现复用既有 profile、trigger decision、configuration owner、turn-start hook、pending-intent 和 publication cursor;新增的 cadence journal 只承担不可约的“冻结窗口身份”,不新增进度游标、sink 或发送授权。
改动思路
入口仍是 Personal Workspace 的 machine/Goal capability settings,以及已有 quota/turn executing wake。normalize_report_cadence 规范化 IANA 时区和受支持的 DAILY/WEEKLY RRULE;periodic_report_cadence_hooks 先检查 Goal 生命周期、有效订阅和 registered Agent;admit_cadence_window 在 mutation lock 内重新读取 live state,冻结最近已完成的半开区间并保留 reporter、subscription revision、profile digest。后续只投影一个 typed capability action/read,交给既有 editorial → generation → delivery continuation;只有 verified publication cursor 才确认已覆盖 trigger。
周报和自动汇报不是二选一的两套产品,而是同一 capability 下的两种 trigger mode:cadence_digest 回顾过去已完成的 [start,end),且 end_at <= generated_at;exception_update/milestone_update 则由 blocker、recovery、decision、outcome 或 milestone 驱动,window 是事件证据上下文,不隐含“一周”。两者共享 trigger decision、generation bundle、sink receipts 和 cursor;同一唤醒同时出现 calendar boundary 与 material event 时只生成一次,优先级更高的事件选择 report kind。late facts 进入下一次更新或显式 correction,不静默改写已验证周报。
具体改动
关键代码讲解
loopx/capabilities/periodic_report/cadence.py:18的normalize_report_cadence只接受一个 daily/weekly occurrence,校验 timezone、BYDAY/BYHOUR/BYMINUTE,并把 RRULE 规范化;它不创建 Automation、不写状态。loopx/capabilities/periodic_report/cadence_journal.py:94的admit_cadence_window与 consumption 共用 mutation lock,校验 window digest,恢复时先检查现有 publication cursor;未完成且已产生 artifact 的窗口不会因配置/注册变化被静默替换,前驱会被归档。loopx/capabilities/periodic_report/cadence_runtime.py:20的periodic_report_cadence_hooks绑定现有 turn-start/quota 入口,保留 frozen reporter,重读 live Goal/subscription,并只返回empty/observed/unavailable加 required capability-read,不执行外部读写。loopx/capabilities/periodic_report/core.py:181的_validate_report_window_for_trigger将 cadence digest 明确限制为 retrospective;未来结束的 calendar window fail closed,而 event update 保持自己的 bounded evidence semantics。docs/reference/protocols/periodic-report-v0.md:115明确记录两种模式、共享 receipt/cursor、coalescing、late-fact 处理,以及 calendar 不是 unattended managed-Turn editorial/delivery adapter。
整体 exact base..head 为 45 个文件、1921 additions/177 deletions;其中删除集中在主干同步后的过期 chat 资产保留代际,新增部分包含 runtime/API、前端设置与打包资源、协议文档和回归测试。变更仍沿用现有 UI/API projection,未新增第二套 chat/Lark source of truth。
对主干的风险
没有 blocking finding。已验证的主要负路径包括:disabled/null schedule、stopped/paused/archived Goal、无 registered/elected reporter、损坏或冲突 journal、配置/reporter 漂移、重复唤醒、以及 cadence_digest 的 period_window.end_at > generated_at。这些路径分别保持 stage-only/no mutation、显式 unavailable、fail closed 或 ValueError;不会生成第二份报告,也不会把 admission 当成 delivery。
验证结果:167 个 focused Python tests、24 个 TypeScript contract tests 通过;npm run build:chat 二次构建 clean。最新 exact head 的 Sign-off、dependency review、build、dashboard acceptance、kernel checks、全部 Python shards、Stage2C、Windows PowerShell、macOS/Windows desktop、Sonar 和 merge-gate 正在以 611e0651 重跑。base f88aae3a 与 exact head 的 periodic-report inspect-profile --preset weekly 都是 exit 0、2500-byte JSON、同一 sha256,证明无 schedule 的既有 profile 路径保持不变。
本机 premerge canary 仍会报告 dashboard_status_json 18,930 > 18,500;同一失败在干净主干复现,是既有 harness budget debt,不是 4263 引入的回归,也不阻断已通过的仓库 merge-gate。Live Lark send/readback 和 fully unattended managed-Turn editorial/generation/recovery 没有被本 PR 宣称或伪装成交付;它们应作为独立 adapter PR 验收。
我的整体评价
APPROVE。 这是与问题规模相称的 cohesive 基础设施切片:calendar digest 与 automatic event update 共享一个 trigger/receipt/cursor 模型,周报确实覆盖过去完成周期,且默认关闭路径不改变既有 stage/manual 行为。实现保持 provider-neutral、权限边界清晰,主干/跨平台 required checks 和 exact-head evidence 均为绿。后续应单独交付 managed-Turn editorial adapter 与 live Lark readback/recovery,不应把它们隐含回填到本 PR。
English verdict: APPROVE — exact head 611e06513ab57847ee706f335e9acd1ffa677812 is reviewed after synchronizing main at f88aae3a and refreshing the bounded chat asset retention manifest. The change keeps calendar digests retrospective over completed half-open windows, treats automatic updates as event-bounded modes, coalesces both through one trigger/receipt/cursor path, and preserves default-off stage/manual behavior. Focused Python (167), TypeScript (24), and local packaged-chat rebuild pass; the latest required GitHub checks are rerunning for the final head. No blocking finding; live Lark delivery and fully unattended managed-Turn editorial recovery remain explicit follow-up adapters.
Periodic-report subscriptions previously had no local calendar activation. Add optional daily/weekly schedules to the existing machine and Goal settings, evaluated by normal wakes and passed into the existing editorial → generation → delivery-Todo flow.
This is the current Ready-for-review stage of the reporting work. Configuration and calendar admission are implemented and verified; fully unattended managed-Turn editorial execution and recovery after changing an already-prepared report remain explicit follow-ups and are outside this delivery boundary.
Validation: 269 periodic-report/configuration/API tests on the latest change; 425 combined periodic-report/Turn tests before the final lifecycle guard, which is covered by the latest suite; 23 TypeScript contract tests; control-plane typecheck; Ruff and diff checks. Packaged frontend was exercised against an isolated real backend for machine defaults, Goal override, calendar off, inheritance restoration and invalid-timezone rejection, in Chinese/English at desktop/mobile widths.
No live Lark delivery or production upgrade was performed. Calendar reports disclose reporter-only evidence coverage. Configuration changes after editorial preparation fail closed until matching authority is restored; a managed runner still needs an editorial adapter to complete the handoff autonomously. Private runtime, accounts, research data and validation logs are excluded.
Future-facing boundary pass: retained the existing capability owner and shared configuration projection; the Turn handoff is provider-neutral and has no shell executor.
Addressed draft review findings: read-only planning no longer dispatches mutating hooks; stale hook registration cannot admit a removed reporter; explicit requests/stages precede calendar work; malformed calendar state does not suppress other valid intents; inactive Goals cannot resume admitted reports. The prior CI failure was an outdated settings-field expectation and is corrected with the API suite passing. Updated CI is pending. Sonar coverage configuration keeps declarative React settings wiring under the packaged dashboard acceptance path; the framework-neutral coverage job does not instrument those components.
Additional delivery acceptance
A provider-adapter integration test now covers calendar admission, preview without send, verified delivery cursor, restart acknowledgement, and replay without a second message (19 delivery tests pass). The Lark runner is synthetic; this is not live group delivery acceptance. The protocol also documents composition with merged #4094: Todo transfer reuses canonical continuation authority, while manager request audiences and prepared report ownership remain separately bound. Cross-Agent prepared-report migration is still unsupported. No frontend code or configuration fields changed in this follow-up; the existing packaged settings acceptance remains applicable.