Repository navigation
fix(release): preserve cycle observations and stable recovery fixtures - #6572
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; runtime_reported; reasoning_effort=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval). Exact head eddc99dacf4174d57ae274bcb697b629ddf69c59, base 9fc858cbd8ee6d0268a4af11ed0f86e84ae6f755.
动机
依靠主线回归检查升级安全的维护者,以及需要读回本地时长观测的用户。一次完整扫描中,quota 已成功结算但附带时长观测没有闭合;探测 fixture 的 PID 先于心跳发布,正常清理可抢先终止它;20,000 条恢复历史逐笔持久提交也在竞争负载下超过测试时限。短暂本地统计锁竞争后仍能记录原 cycle;探测就绪意味着心跳已经存在;恢复检查保留完整 20,000 条合法历史及第 20,001 条拒绝,同时减少 fixture 的重复持久提交。本 PR 只关闭这三个已展示的观测/fixture 边界,不改变业务结算、探测 deadline 或历史容量,不宣称统计零丢失、持续运行或 release 已发布。
改动思路
依据 docs/reference/usage-ping.md 已有非阻塞、可丢失、受 consent/generation 约束的统计合同,结合原测试独立定义的历史容量与进程清理约束评审;同时应用 docs/development/testing-and-quality.md 的预算决策。最强反对理由是延长等待掩盖统计丢失、批量 fixture 绕过真实规则。这里不增大测试 poll、probe deadline 或20k容量:只让原 detached cycle 有界等待自身统计锁,并对合法完整 SQLite 数据做原 owner 全量审计,保留所有原公开拒绝与清理断言。
| 触发 | 原结果 | 本 head 的边界 |
|---|---|---|
| 本地统计锁占用500ms | 250ms后放弃原 end | 仅后台 cycle 最多等2000ms;普通 observer仍250ms |
| PID先于第一条pulse发布 | 正常cleanup可先杀掉fixture | 先持久写首条pulse,再发布ready PID |
| 完整20k恢复历史准备 | 逐笔持久提交在竞争负载下超时 | 单次合法fixture事务,再完整native审计与原backup/verify |
Each repair stays at its existing owner: typed statistics policy, disposable native authority fixture and test readiness. No new production state, provider or framework is needed. 本 PR 只关闭这三个已展示的观测/fixture 边界,不改变业务结算、探测 deadline 或历史容量,不宣称统计零丢失、持续运行或 release 已发布。
具体改动
bounded-cycle-observer:usage_statistics.observe 只把已存在 cycle 的本地锁等待从250ms改为2000ms,仍在 detached worker 内,不让业务CLI等待。锁内仍读取当前合法状态并检查禁用、notice与同一generation,再记录原key/lane/Turn/time;不是开启统计、扩展会话范围或重放结算。短锁正例、长锁拒绝、排队时withdrawal/合法新generation三个TS场景使用真实文件锁;禁用后无send、无cycle文件。普通统计、网络失败无重试、收件方与可见披露规则不变,既有指南明确说明新边界和持续竞争仍未知。
complete-history-fixture:原恢复用例保留20,000合法历史及20,001溢出。fixture 在真实SQLite单一事务中,用已导出的 commitDigest、authorityStateDelta/Digest 和 checkpoint规则生成同一原projection的完整历史,再用 verifyAuthorityHistory 验证每条链与checkpoint,并独立读回head。随后仍走实际archive、CLI inert verify和历史容量拒绝;公开错误、无destination、无残留temporary断言保留。没有给生产store添加batch API、复制codec或改变数据库durability;只减少合成准备的重复持久事务。相同容量完整用例的观测为27.668秒与3.725秒,不外推成一般产品性能结论。
truthful-probe-readiness:原持久子进程fixture先写首条pulse,再写PID作为ready信号。生产 _run_probe、超时/输出限制与进程回收逻辑未改,原六组参数、每组两次的PID停止和pulse不再变化断言完整保留。控制ready后的5秒间隔,旧顺序两次都不能满足pulse存在,新顺序两次均通过,实际拥有的子进程全部停止。这解释了fixture为何可被正确cleanup抢先终止,不把missing pulse误判成生产清理失败。
共5个路径、109行增加/11行删除,只有一个生产条件预算和两行说明;其余是测试与6行既有指南。三个DCO提交可分别回退,未增加设置、协议、状态迁移或前端/Lark用户步骤。
对主干的风险
精确head上109项Python完整模块/两种原CLI布局,顺序执行和8worker分别通过;6个TS完整模块67项通过,均0失败/错误/跳过。包含真实Python/Node/SQLite、原quota should-run→refresh→spend→replay、held HTTP response与disable路径,也保留原有unit mocks的边界。统计counterfactual使用相同500ms真实锁,base来自准确不可变Git archive:旧end缺失,新end保留;persistent lock仍拒绝。初次新fixture的非法UUID/类型错误已修正,原失败结果保留。
Ruff、TS typecheck、advisory后全树semantic检查、严格CQR和premerge的4项direct+14项选中检查通过,无失败、跳过、warning或manual hold;未查询PR CI。旧7ed完整扫描的3失败、23565通过、531跳过、656通过subtests保持原记录;不把当前109项回归称为重新跑完全部扫描。历史单次cycle丢失不能仅凭保留文件唯一还原原因;当前短锁缺口已独立复现并覆盖,同一原CLI流程及完整隐私/失败边界在顺序和并发下均通过。
我的整体评价
APPROVE。这是三个有独立证据、共用发布回归修复目的的可逆切片:原owner负责原规则,fixture不再把重复setup或未完成ready当作产品缺陷。无新权限、模型执行、benchmark评分/提交、业务retry或额度;长程工作与用户操作路径保持,观测修复不等于可用性或持续运行认证。相关有界整理已通过既有typed owner、codec和首条pulse顺序完成,无需新抽象;2000ms只承担后台有界成本。本 PR 只关闭这三个已展示的观测/fixture 边界,不改变业务结算、探测 deadline 或历史容量,不宣称统计零丢失、持续运行或 release 已发布。
English verdict: APPROVE - exact head eddc99dacf4174d57ae274bcb697b629ddf69c59. Bounded detached cycle contention, truthful probe readiness and a full valid SQLite history fixture repair the demonstrated release gaps. 109 Python cases pass sequentially and with eight workers; 67 TypeScript cases and 4 direct + 14 selected premerge checks pass without skips. Original failure evidence remains; history/probe limits, consent, business authority and lossiness are preserved. Final-source/model/channel release qualification remains separate.
The release sweep exposed a lost local quota-cycle observation, a race between a probe's ready PID and first heartbeat, and a recovery fixture that timed out while performing thousands of separate durable setup commits. Preserve the original observation in brief contention and make both fixtures exercise their existing safety checks reliably.
The existing TypeScript observer allows cycle markers a bounded two-second local lock wait in its detached worker; ordinary observers retain 250 ms, and consent/generation are rechecked under the lock. Business commands never wait. The probe fixture writes its first heartbeat before publishing readiness. The real SQLite fixture stages the same 20,000/20,001 valid rows in one transaction using exported owner digest/delta/checkpoint encoders, audits the complete native history, then performs the existing backup, inert readback and overflow-refusal checks. History limits, probe deadlines, quota rules and network retry policy are unchanged.
Validation at this exact head:
Related simplification: reuse the existing typed observer, mutation lock, SQLite encoders and native audit instead of a second state owner or new test framework. Initial characterization and test-shape/type failures remain recorded. These repairs grant no new model, network, benchmark, scoring or submission authority; release source and publication-channel qualification remain separate. Telemetry remains bounded and lossy.