Skip to content

fix(control-plane): bind delivery claims to typed evidence - #3094

Open
bucheyu wants to merge 3 commits into
huangruiteng:mainfrom
bucheyu:codex/outcome-evidence-governance
Open

fix(control-plane): bind delivery claims to typed evidence#3094
bucheyu wants to merge 3 commits into
huangruiteng:mainfrom
bucheyu:codex/outcome-evidence-governance

Conversation

@bucheyu

@bucheyu bucheyu commented Aug 11, 2026

Copy link
Copy Markdown

A caller-provided delivery outcome could previously elevate planning or checkpoint work into accountable progress. This change bounds progress claims to typed advancement Todos, material delivery scale, or compact evidence already present in the run. During outcome follow-through, the work lane now skips surface-only planning Todos and selects an executable product advancement; when none exists it reports one precise blocker instead of recommending another preparation layer.\n\nThis does not add a service, command, replay evaluator, or persistent gate. It is a semantic read-model correction in the existing delivery/work-lane path.\n\nValidation:\n- premerge canary: 18 selected, 18 passed, 0 failures\n- focused delivery outcome, turn-kind, work-lane, status, and heartbeat smokes passed\n- mypy passed\n- maintainability ratchet: 9 passed\n- public/private boundary scan passed

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

PR #3094 评审(head cc30c68b84

详细中文评审

动机

调用方提交的 delivery_outcome 此前可以把 planning/checkpoint 类工作提升为 accountable progress。本 PR 把 progress 声明约束到“typed advancement Todo + material delivery scale + run 中已存在的 compact evidence”,歧义声明投影为 outcome_gap;outcome follow-through 时工作 lane 跳过 surface-only planning Todo、优先可执行的产品 advancement,没有时要求一个精确的 missing-product blocker 而不是再叠一层 planning/binding。

改动思路

在 delivery signals 读模型处收口 outcome 判定(delivery_signals.py / delivery_outcome.py),outcome_followthrough.py 负责选择可执行 advancement,work_lane.py/work_lane_context.py 更新选择与 blocker 生成;state_refresh.pystatus.pyshould_run_packet.pyagent_lane_recommendation.py 消费同一读模型;docs 与 8 个 smoke 同步契约。

具体改动

  • 核心符号:delivery_outcome_for_run(按 typed evidence 判定 outcome)、outcome_followthrough.select_next_advancement(跳过 surface-only)、work_lane blocker 生成(精确 missing-product)。
  • 18 个文件:docs 1、examples smoke 8、control_plane 7、status/refresh/quota 3。
  • 新增/更新 smoke 用例:planning_checkpoint + outcome_progress → surface_only;ambiguous → outcome_gap;typed advancement + non-surface action kind → outcome_progress

对主干的风险

行为变更影响 quota/status/refresh 投影与 lane 选择,但均收敛到同一读模型且有 smoke 锁定;歧义不再被“调用方声明”抬高。CI 尚未上报,需以终态确认。

我的整体评价

把“谁有权声称 progress”从调用方自由声明收紧为 typed evidence 判定,方向正确、边界清晰、测试与文档同步。达到合并条件,结论 APPROVE。


Review: APPROVE

Head: cc30c68b84

Verdict: APPROVE — delivery progress claims are now bounded to typed advancement todos, material delivery scale, or compact in-run evidence; planning/checkpoint claims stay surface_only and ambiguous claims project as outcome_gap, with work-lane followthrough preferring a real executable advancement or a precise blocker. Local validation: 4 key policy smokes pass, 64 related control-plane/turn tests pass, py_compile and 8-file boundary scan clean; CI checks not yet reported at review time.

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

详细中文评审 — PR #3094(exact head cc30c68b84780d333faf9a09bb0a3b277ed16c78

动机

此前 delivery_outcome 是一个调用方可直接提交的枚举:只要显式传 outcome_progress / primary_goal_outcome,quota/status/refresh 就会把它当作可结算的 accountable 进度。于是 planning、brief、dispatch、binding、checkpoint、protocol、state-refresh 这类“控制面准备”也可以被记录成 outcome progress,agent 可以靠自报的枚举把没产出的工作推成“有进度”,长期任务会陷入重复的准备层而不是真正的产品推进。这个 PR 把“delivery_outcome 是 claim,不是 override”落到三个层面:读模型(status/quota 投影)、选择模型(work lane 优先选非 surface 的 advancement todo)、写模型(refresh-state 对 turn-scoped accountable claim 做 evidence bound,越界即 fail closed)。

改动思路

核心是一个纯函数 evidence_bounded_delivery_outcome(run, claimed):claimed 本身是 surface_only/outcome_gap 直接放行;run 被判定为 surface-only(turn kind、action_kind、classification 命中 denylist)则压成 surface_only;有 typed 材料证据(advancement_task + 非 surface action_kind、material batch scale、compact benchmark/case/product 证据)则保留 claim;否则压成 outcome_gap。这套 read model 不重放 artifact、不新增门禁,只约束“什么算数”。下游三处消费同一函数:delivery_outcome_for_run(status 投影)、build_outcome_followthrough_hint(follow-through 判定)、refresh_state_run(写回前的 fail-closed 校验)。选择层新增 first_outcome_advancement_itemoutcome_followthrough_required 过滤:有 follow-through 需求时跳过 planning 类 todo;一个都没有时 work lane 返回 report_product_advancement_blocker,要求 agent 写一个精确的“缺产品推进 todo”blocker 并停止,而不是再叠一层 planning。

具体改动

18 个文件 +540/-49:9 个运行时(delivery_outcome.pydelivery_signals.pyoutcome_followthrough.pywork_lane.pywork_lane_context.pyagent_lane_recommendation.pyshould_run_packet.pystate_refresh.pystatus.py)、8 个 smoke、1 个文档。

关键代码讲解

  1. evidence_bounded_delivery_outcome(delivery_outcome.py):唯一的事实来源。先放行 surface_only/outcome_gap,再查 delivery_run_is_surface_only,再查 delivery_run_has_material_evidence,最后落 OUTCOME_GAP。任何显式 claim 都不能绕过它。
  2. delivery_run_is_surface_only / delivery_run_has_material_evidence:前者是子串 denylistplanningcheckpointprotocolstate_refresh 等),后者承认三类材料证据:typed advancement_task + 任意 action_kind、material batch scale(implementation/multi_surface/test_only)、compact evidence keys。注意顺序:surface-only 判定先于 evidence 判定,所以 planning_checkpoint 即使有 action_kind 也不会被当成材料。
  3. build_work_lane_contract 新分支(work_lane.py):outcome_followthrough 且没有可执行产品 advancement todo(outcome_advancement_missing 或根本没有 agent todo)时,obligation 变成 report_product_advancement_blockermust_attempt_work=True,action 明确写“写一个精确 blocker 然后停止;不要再加 planning/binding/checkpoint/preparation 层”。
  4. first_outcome_advancement_item(work_lane_context.py)+ build_agent_lane_next_action(..., outcome_followthrough_required=True)(agent_lane_recommendation.py):follow-through 场景下,可执行候选只保留 advancement_task 且 action_kind 非 surface 的项;selected_action_with_agent_lane 在 follow-through 时不再用 source 白名单限制,避免过滤后的选择被丢弃。
  5. refresh_state_run 写回门(state_refresh.py):通过 selected_todo_delivery_fields 把结算 todo 的 todo_task_class/todo_action_kind/todo_status 投影进 run,再用 evidence_bounded_delivery_outcome 重算;turn-scoped 或 --delivery-workspace-path 场景下,若重算结果不是 accountable,直接 ValueError fail closed——planning/surface-only claim 无法再进入结算和 quota spend。

正向路径

最新 run 是 surface_only(如 planning_checkpoint)→ quota 构造 follow-through hint → first_outcome_advancement_item 跳过 planning todo、选中 todo_deliver_player_story(P1)→ build_agent_lane_next_action 返回该 todo → agent 执行真实产品推进 → refresh-state 用 settlement todo 字段 + classification 重算为 outcome_progress,记录 typed todo 字段并正常结算。

负向路径

调用方提交 delivery_outcome=outcome_progress + classification=runner_contract_v0_delivered,无 todo/scale/evidence 字段 → evidence_bounded 压成 surface_only → turn-scoped refresh-stateValueError(不能 settle planning/surface-only claim),quota spend 不会发生。若队列里只剩 planning todo,work lane 变成 report_product_advancement_blocker,recommended_action 直接要求写 blocker 并停止——不会再产生新的 planning 层。

对主干的风险

  • 子串 denylist 是启发式action_kind/classification 是项目自定义的,policy/protocol/plan_/dispatch 这类子串可能误伤未来真实产品 action(例如 policy_engineprotocol_compiler)。当前 denylist 刻意保守、smoke 也覆盖了正反例,但这是长期维护面:建议后续把 action-kind 判定收敛到精确匹配/allowlist 注册表,或至少加一个“歧义 action kind”负例。
  • 行为收紧的影响面refresh-state 现在会拒绝以前能通过的 turn-scoped accountable claim。这是本次意图,但会改变既有自动化行为;错误信息已可操作,但建议在 ValueError 里带上 bound 后的 outcome 和命中的 action_kind/classification,方便快速定位是哪类 claim 被拒。
  • 验证面:PR 没有新增 pytest,只靠 8 个 smoke;当前 PR 无 CI checks(merge state UNSTABLE)。我在 exact head cc30c68b 的独立 worktree 里跑了全部 8 个受影响 smoke,全部通过;public boundary 10 个文件 clean。合并前仍建议补跑一次仓库 canary/CI。

我的整体评价

改动方向正确且克制:把“claim vs evidence”的边界做成了单一 read model,三个下游(投影、选择、写回)共用同一函数,没有引入 artifact replay gate 或新框架。fail-closed 行为是明显改进——planning/surface-only 不再能假装成 outcome progress。代码量适中(+540/-49),smoke 覆盖了正向、负向和选择优先级。剩余风险集中在子串启发式的长期误判和 CI 缺失,都是非阻塞的 P2 项。结论:APPROVE(无 blocking findings)。


English Verdict

  • Head: cc30c68b84780d333faf9a09bb0a3b277ed16c78 (unchanged since packet)
  • Verdict: APPROVE
  • Key finding: delivery_outcome is now bounded by typed Todo/metadata/compact evidence through one shared read model (evidence_bounded_delivery_outcome), with fail-closed refresh-state for turn-scoped accountable claims and a report_product_advancement_blocker work-lane obligation when only preparation Todos remain.
  • Validation: all 8 affected smokes pass on the exact head in an isolated worktree; public-boundary scan clean (10 files); diff fully read. No CI checks are present on the PR (merge state UNSTABLE), and two non-blocking P2 items remain (substring denylist heuristics; richer fail-closed error text).
  • Residual risk: heuristic action-kind/classification matching may misclassify future product kinds; recommend exact-match registry or an ambiguity negative fixture later.

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Request changes — 综合评审结论(exact head cc30c68b84780d333faf9a09bb0a3b277ed16c78

在完整阅读 diff 并逐条验证 8 个受影响 smoke 之后,结合仓库刚合入的 review lens(typed_state_rule / domain_neutrality / behavior_change_disclosure / guidance_vs_obligation,见 #3123),以下为 blocking 级修改要求。此评审取代之前的 APPROVE。

1. 状态分类规则需要 typed 化(typed_state_rule)

delivery_action_kind_is_surface_only / delivery_run_is_surface_only 使用 hint in action_kind / hint in classification 的子串匹配,没有词边界:policyprotocolpreparedispatch 等常见词会误伤未来真实 action_kind(例如 policy_engineprotocol_compilerprepare_release_assets);漏网方向(未收录的 surface 写法)会让本 PR 想堵的问题原样复现。

要求:

  • 把 surface/产品语义收敛为 typed 契约:todo 显式声明 delivery_surface=product|surface_only(或等价 enum/schema),读模型从数据声明读取,不再从字符串猜测;
  • 若保留字符串判定,至少改为 token/精确后缀匹配,并补充歧义 action_kind 的正反例 fixture(如 policy_engine 不应判 surface、planning_checkpoint 应判 surface)。

2. 通用控制面需要领域中立(domain_neutrality)

report_product_advancement_blocker 及 action 文案 "missing executable product advancement Todo" 是产品中心语言。LoopX 的目标类型包括 benchmark、research、docs、content-ops,其真实工作可能就是 protocol/policy/checkpoint/governance——而这些词恰好在 denylist 里,存在自相矛盾的误判路径。

要求:

  • 改为目标无关措辞,例如 "missing runnable advancement Todo matching the claimed outcome";
  • 提供目标级逃生阀,确保 benchmark/docs/governance 目标不会被强制要求写"产品推进 blocker"。

3. 默认行为变化必须披露(behavior_change_disclosure)

该 PR 把 "connected read-only progress run stays runnable" 改为 "reports product blocker"(smoke 改名可见),但 PR 描述与文档没有显式声明这一默认行为变化及其影响的 lane。

要求:

  • 在 PR 描述/docs 中写明 old default -> new default 与受影响 lane;
  • 明确这是 hard obligation(must_attempt_work=True),不是纯 guidance,并说明 enforcement consequence(quota 会持续选中,直到 blocker 写回或出现真实推进)。

4. 合入前请补真实场景验证

当前 PR 无 CI checks,验证全部来自 fixture smoke;但本改动会改变真实 heartbeat/quota/work-lane 的默认行为。请至少跑通以下真实场景并给出可复核证据:

  • 一个真实"surface-only planning claim"的 goal:claim 被 bound 成 surface_only,follow-through 正确触发,且不会错误结算/花 quota;
  • 一个维护型 / state-refresh lane:不会被误判为缺"产品推进"而被迫写 blocker;
  • 一个 benchmark 或 governance 类 goal(action_kind/classification 含 protocol/policy/checkpoint):不会被误判成 surface-only;
  • 至少一条真实 quota should-run + refresh-state 的完整 packet 证据(含 bounded outcome、reason_codes 与 work-lane obligation)。

补充:合入前请在 exact head 上跑一次 canary/CI(当前 PR 没有 status checks),并保留 change-quality receipt。

完成上述修改与验证后可重新请求 review;届时我再 approve。


English verdict: REQUEST_CHANGES @ head cc30c68b84780d333faf9a09bb0a3b277ed16c78 — key asks: replace substring denylist classification with a typed contract (or exact/token matching plus ambiguity fixtures), make work-lane obligations goal-agnostic, disclose the default behavior change and its enforcement semantics, and validate against real goals/lanes (surface-only claim, maintenance lane, benchmark/governance goal) with packet evidence before merge.

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

详细中文评审(重审确认)

精确评审头: 3094@cc30c68b84780d333faf9a09bb0a3b277ed16c78

动机

按全队列重审要求复核本 PR(delivery claims 绑定 typed evidence,18 个文件)。exact head 自 08-12 08:15Z 的 CHANGES_REQUESTED 后未更新,阻断项仍待作者修复。

改动思路

PR 把 delivery_outcome 的 progress 声明约束到 typed advancement Todo + material delivery scale,方向正确(此前曾两次 APPROVE);随后 owner 按新评审 lens 提出综合修改要求。

具体改动(关键内容讲解)

  • 阻断项(08:15Z 综合 CR):owner 依据 typed_state_rule / domain_neutrality / behavior_change_disclosure lens 提出要求(完整结论见该评审),当前 head 未体现修复。
  • head 未变:自 CR 后无新 commit,阻断项未解决。

对主干的风险

delivery/outcome 语义是 settlement 与状态投影的核心契约;若按旧语义合并,会把 planning/checkpoint 类工作错误结算为 accountable progress。风险高。

我的整体评价

REQUEST_CHANGES(确认既有结论)。 修复要求:按 08:15Z 综合 CR 逐项修改(typed evidence 绑定、domain neutrality、行为变更披露),修复后需 exact-head 复审。


English Verdict

REQUEST_CHANGES — exact head cc30c68b84780d333faf9a09bb0a3b277ed16c78.

Confirms the existing comprehensive CHANGES_REQUESTED from 08:15Z (typed_state_rule / domain_neutrality / behavior_change_disclosure findings). No new commits since; blockers remain. Re-review after the author updates the head.

@huangruiteng

Copy link
Copy Markdown
Owner

结论:有价值,但需要 rebase 并收缩到唯一剩余 delta(REQUEST_CHANGES)

评审目标 head:cc30c68b84780d333faf9a09bb0a3b277ed16c78(自 08-12 08:15Z 综合 CR 后未更新;当前对 main 为 CONFLICTING)

价值判断

我把 exact head 与当前 main(32b153c1)逐文件对比后,结论是:这个 PR 想解决的问题在 main 上已经被后续演进覆盖了大半,但还留着一个 main 没有的写模型缺口

已经被 main 覆盖的部分(不要再重复实现):

  1. 读模型约束:main 的 delivery_signals.delivery_outcome_for_run 已用 execution-profile 配置的 outcome_markers / surface_only_hints 判定 outcome,替代了本 PR 硬编码的全局子串 denylist——这正是 08-15Z 综合 CR 第 1 条"收敛为 typed/配置化契约"的方向(虽然仍是子串匹配,但已配置化、按 profile 归主)。
  2. follow-through 义务:main 的 outcome_followthrough.build_outcome_followthrough_hint 已产出目标无关的 advance_primary_outcome_or_write_blockeraccepted_resolution_kinds(PRODUCT_PATH_EXECUTION / COMPACT_EVIDENCE / BLOCKER_WRITEBACK),对应 CR 第 2 条"领域中立措辞"。
  3. work-lane 选择:main 的 work_lane.py / work_lane_context.py 已有 follow-through 优先选择与 monitor/blocker 义务体系。
  4. replan 写回降级:main 的 state_refresh.py 在 autonomous-replan 分支里已有 repair_delta_kinds_have_accountable_progress 不足时把 outcome_progress/primary_goal_outcome 降为 outcome_gap 的 gate。

仍然只有本 PR 提供的价值(真正的剩余 delta):

  • 通用写模型 fail-closed gatestate_refresh.py 里的 selected_todo_delivery_fields + evidence_bounded_delivery_outcome 重算——对 turn-scoped 的 accountable claim,在写回前用"typed advancement todo / material batch scale / compact evidence"重新判定,不是 accountable 就直接 ValueError 拒绝,杜绝 planning/checkpoint 用显式 delivery_outcome=outcome_progress 完成结算和 spend。main 目前只在 autonomous-replan 分支做降级,普通 turn-scoped 结算路径对显式 claim 仍是"原样放行"(delivery_outcome_for_run 对显式值直接返回),所以这个缺口依然真实存在。

真正合适的评审建议

REQUEST_CHANGES,但不是要求重写整个方案,而是要求 rebase + 收缩到上述唯一 delta:

  1. rebase 到最新 main 并解决冲突(当前 head 无法合并);
  2. 删除已被 main 取代的部分:delivery_run_is_surface_only / delivery_action_kind_is_surface_only / delivery_run_has_material_evidence 的硬编码 hint 表,以及产品中心的 blocker 文案——这些语义 main 已有更好的实现;
  3. 只保留并打磨写模型 gate:selected_todo_delivery_fields + evidence_bounded_delivery_outcome(显式 claim 必须由 typed todo/scale/evidence 支撑),fail-closed 错误信息带上 bound 后 outcome 与命中的 action_kind/classification;
  4. 为该 gate 补聚焦 pytest(正例:真实 advancement + material evidence 放行;反例:planning/checkpoint claim 被拒、不写状态不 spend),并附一条真实 quota should-run + refresh-state 的 packet 证据;
  5. exact head 跑 canary/CI(当前 PR 无 checks)后再请求复审。

如果作者只提交这个收缩后的 delta,价值仍然成立且合入面会小很多;如果整 PR 原样合入,会与 main 的读模型/义务语义重复甚至冲突,不建议。


English Verdict (comment)

  • Head: cc30c68b84780d333faf9a09bb0a3b277ed16c78 (unchanged; CONFLICTING against current main)
  • Verdict: REQUEST_CHANGES — rebase and shrink to the one remaining delta.
  • Value: The PR's goal (delivery outcome is a claim, not an override) is mostly superseded by current main: delivery_signals.delivery_outcome_for_run (profile-configured outcome floor), outcome_followthrough.build_outcome_followthrough_hint (goal-neutral advance_primary_outcome_or_write_blocker), and the replan writeback downgrade gate already cover the read model, follow-through wording, and part of the write path. The unique residual value is the general turn-scoped write-model gate: recompute evidence_bounded_delivery_outcome from the selected Todo + run fields and fail closed (ValueError, no state/no spend) when an explicit accountable claim lacks typed advancement/material evidence. Main only downgrades explicit claims in the autonomous-replan branch today.
  • Ask: rebase; delete the superseded hardcoded denylist and product-centric blocker wording; keep only the selected_todo_delivery_fields + evidence_bounded_delivery_outcome gate with actionable error text; add focused positive/negative pytest plus one real quota should-run + refresh-state packet; run canary/CI on the exact head.

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

PR #3094 补充评审(supplementary findings)

精确评审头: 3094@cc30c68b84780d333faf9a09bb0a3b277ed16c78

本补充不改变既有 REQUEST_CHANGES 结论(review 4914393146 / 4916695908,head 自 08-12 后未更新,阻断项仍待修复)。以下两条是本轮 fresh validation 新增的 P2 级发现,供作者与合并者在既有修改要求之外一并处理。

补充发现 1(P2):test_only batch scale 单独即可构成 material evidence

delivery_run_has_material_evidence()delivery_batch_scale == "test_only" 直接判为 material evidence。实测:

  • delivery_run_has_material_evidence({"delivery_batch_scale": "test_only"})True
  • evidence_bounded_delivery_outcome({"delivery_batch_scale": "test_only"}, "outcome_progress")DeliveryOutcome.OUTCOME_PROGRESS

也就是说,一个没有 typed advancement Todo、也没有 benchmark/case/product compact evidence 的纯测试运行,只要调用方声明 --delivery-batch-scale test_only,progress claim 就会被放行。这削弱了「progress 声明绑定到 typed advancement Todo 或 compact evidence」的语义;如果 test-only 是刻意视为 material 的 scale,请在 docs/PR 描述中写明理由,否则建议要求 test_only 同时具备 advancement Todo 或 compact evidence 之一。

最小修复:把 test_only 从 material scale 集合中移除,或要求 advancement_task + action_kind 并存;并补一个 {"delivery_batch_scale":"test_only"} 的负例 smoke。

补充发现 2(P2):refresh-state 对 surface-only settlement 的新硬失败未在 CLI help/docs 披露

refresh_state_run() 新增两处硬 ValueError

  • turn-scoped settlement(settlement_identity)且 bounded outcome 不在 ACCOUNTABLE_DELIVERY_OUTCOMES 时,整个 refresh 失败并提示「complete a typed product advancement Todo or write an unbound outcome gap/blocker」;
  • --delivery-workspace-path 同样要求 accountable outcome。

这是合理的 fail-closed,但 CLI help 与操作文档没有说明这个新失败模式。现有自动化若在 surface-only 写回时仍带 --todo-id / --delivery-workspace-path,会从「可降级写回」变成硬失败。建议在 refresh-state --helpdocs/operations/long-task-cadence-policy.md 补充 old default -> new default 与错误处理指引(写 unbound blocker 或去掉 workspace/settlement 参数)。

Fresh validation(exact head)

场景 命令 结果
全量 control-plane pytest tests/control_plane 1028 passed / 0 failed(含 M6 maintainability ratchet)
受影响的 8 个 smoke delivery-outcome-enum / delivery-turn-kind-enum / outcome-followthrough-policy / delivery-signals-readmodel / long-task-cadence-policy / work-lane-contract / heartbeat-quota-flow / status-markdown 全部通过
聚焦探针 test_only scale / 子串误判 复现补充发现 1 与既有 typed_state_rule 结论

English verdict: No change to the existing REQUEST_CHANGES for 3094@cc30c68b84780d333faf9a09bb0a3b277ed16c78. This is a supplementary COMMENT: two new P2 findings (test_only scale alone passes as material evidence; refresh-state hard-failure for surface-only settlement is undocumented). Fresh validation at the exact head: 1028 control-plane tests pass, 8 touched smokes pass, M6 ratchet green.

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.

2 participants