Skip to content

test(settlement): characterize the host adapter's partial-step boundary - #7645

Merged
huangruiteng merged 5 commits into
loopx-project:mainfrom
xiaoan17:codex/c43-3-adapter-partial-step-characterization
Oct 29, 2026
Merged

huangruiteng merged 5 commits into
loopx-project:mainfrom
xiaoan17:codex/c43-3-adapter-partial-step-characterization

Conversation

@xiaoan17

@xiaoan17 xiaoan17 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Goal and source

C4.3
requires the host settlement adapter's own partial-step behavior to be
characterized before any recovery change touches it. The merged
C4.3 comparison recorded
that the adapter keeps no journal of its own, and named two things as still
uncharacterized: what the adapter itself does when a step succeeds and a later
step fails, and where the recovery boundary between the adapter and the CLI
receipts sits.

Without them, the next consolidation slice had to assume both.

What this PR delivers

Executable characterization —
tests/control_plane/test_host_adapter_settlement_partial_steps.py, five test
functions (eight cases) against the real TypeScript owner and the real CLI:

Case Adapter behavior Owner behavior
A step returns output the adapter cannot read The plan stops after that step The owner classifies the stop: blocked, failed_stage: guard, quota guard returned malformed JSON
A step raises The exception propagates; the finalize phase never runs, so the transaction is never classified; no record of the already-succeeded step is kept Nothing is classified, because the owner is never asked
A retry after a raise The plan is re-entered at its first step, never resumed mid-plan The identity is re-derived from the same intent
A raise before the lifecycle completion Nothing is spent, the Todo stays open The guard already ran, so the validation receipt is committed; the readback is open with progress writeback_required
A raise after the lifecycle completion Nothing is left behind; the CLI's canonical receipt store holds the committed receipt The readback is settlement_pending with progress writeback_required
A raise after the durable writeback Nothing is left behind The readback is settlement_pending with progress spend_required
A raise after the quota spend Nothing is left behind The readback is settled; the retry replays that receipt (idempotent_replay), spends no second slot and reports the same settlement identity

The four durable stages are measured by wrapping the real dispatch and reading
back the committed receipt kinds, the replay phase and the settlement progress
from the File fixture — the owner names the step that is still owed, rather
than the failure being one undifferentiated state.

Three findings follow, and they are what the comparison entry could not state:

  1. The adapter makes no classification decision. A stopped plan is
    classified by the TypeScript owner; a raised step is not classified at all.
    The adapter is transport in both cases.
  2. The recovery boundary is the CLI receipt, not adapter state. After a
    raise, the only durable evidence is what the CLI already committed. The
    retry succeeds because that receipt replays.
  3. The outstanding work is named by the owner, stage by stage. open,
    settlement_pending and settled are distinct, and the progress state
    names the step still owed — writeback_required after the lifecycle
    completion, spend_required after the durable writeback.

Bilingual ledger entry —
docs/architecture/rfcs/ledger/controller-executor-unified-contract-v0/2026-10-29-c4-3-adapter-partial-step-characterization.md
and its Chinese mirror record the characterization, the evidence, and what the
entry does not establish. The derived STATUS.md / STATUS.zh-CN.md index
is regenerated by scripts/generate_rfc_status_index.py.

No runtime, schema, wire, default or recovery behavior changes. The
characterization adds no journal, retry policy or resume capability to the
adapter: adding one is a new design decision with its own acceptance.

Response to the previous review

The previous review raised two P2 findings and one P3 on the ledger entry. All
three are addressed in this head:

  • P2 — the stage claims were too wide. The entry described a raise after
    "a durable commit" as leaving a settled readback, and a raise before the
    lifecycle completion as having no settlement receipt. Both are now stated
    per stage, from the measured readbacks, and the validation receipt is named
    explicitly. A new parametrized case pins each stage's replay phase, progress
    state and committed receipt kinds, so the table is executable rather than
    prose.
  • P2 — the next slices contradicted the parent entry. The entry asked for
    a caller that adopts both settlement paths, which the parent confirmation
    entry had already found and recorded as a withdrawn candidate. The remaining
    work now keeps the deletion preconditions from the comparison entry and
    points the open slice at the host-adapter step registry in feat(control-plane): register the host-adapter settlement step vocabulary #7619, which is
    merged.
  • P3 — the Chinese parent anchor did not resolve. The strict build
    generates the id c43-adapter for the Chinese C4.3 heading; the English
    counterpart is c43-settlement-adapters-over-existing-primitives. Both
    mirrors now use the generated ids, verified against the built HTML.

Scope

This PR is the candidate 2 slice named by the comparison entry, and only that
slice. It sits directly on top of merged main (which carries the comparison
entry, the vocabulary confirmation entry and the merged host-adapter step
registry), so the diff is six files: the new characterization cases, the
bilingual ledger entry, and the derived index count.

The deletion preconditions recorded in #7593 are unchanged, and no deletion is
proposed here.

Validation

pytest tests/control_plane/test_host_adapter_settlement_partial_steps.py    8 passed
pytest (settlement, MCP settlement, host vision recovery modules)          107 passed
python scripts/generate_rfc_status_index.py --check                         clean
scripts/check_rfc_bilingual.py --base origin/main --head HEAD               passed
mkdocs build --strict                                                        built, 0 errors
loopx canary premerge --from-git-diff --git-diff-base origin/main           17 checks, 0 failures, 0 warnings
loopx check --scan-path <changed paths>                                    clean

Base: 58205c62a1 (current main, carrying #7617, #7619 and the current C4.3 entries).
Head: see the commit list on this PR.

@mergify

mergify Bot commented Oct 29, 2026

Copy link
Copy Markdown

This pull request has merge conflicts with main and cannot be merged
until they are resolved. Please rebase or merge the base branch, @xiaoan17.

Choose the remote for the base repository, not an out-of-date fork.
For a fork clone, first inspect git remote -v; upstream must point
to https://github.com/loopx-project/loopx.git. If it is absent, add it
with git remote add upstream https://github.com/loopx-project/loopx.git.
Then run:

git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEAD

For a same-repository clone whose origin points to
https://github.com/loopx-project/loopx.git, use origin instead of
upstream for fetch/rebase. If you prefer merging the base, use
git merge <base-remote>/main and push normally.

Keep the DCO Signed-off-by trailer on every commit when you rebase.
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 29, 2026
@xiaoan17
xiaoan17 force-pushed the codex/c43-3-adapter-partial-step-characterization branch from 5c5e834 to 9bd553c Compare October 29, 2026 08:00
@mergify mergify Bot removed the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 29, 2026

@xiaoan17 xiaoan17 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reviewer: model_agent · MiniMax-M3.1-Flash · MiniMax · self_reported · reasoning_effort=unavailable

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

精确 head 9bd553c62a43d4b8465257d1e55145baec2dca3a:APPROVE,没有剩余阻断发现。

动机 / Motivation

C4.3 要求在改动这条恢复路径之前,先把 host settlement adapter 自身的"部分步骤"行为刻画出来。
已合并的 C4.3 对照 把"适配器不持有本地
journal"记成事实,同时点名留下两件还没有刻画的事:某一步成功、后续一步失败时适配器自身
做什么;适配器与 CLI 回执之间的恢复边界落在哪里。缺了它们,下一个整合切片只能靠猜。

本 PR 只交付那一块切片,不顺手做任何恢复或删除。

改动思路 / Approach

做法是测量而不是重新设计:用例写在真实的 TypeScript 属主与真实 CLI 之上,所以记录下来的
就是已交付的行为,而不是对行为的假设。

分类用例没有替换 effect runtime——步骤输出读不懂时"如何分类"由属主判定,mock 掉属主就等于
把要测的东西换掉。恢复用例走真实 CLI 与真实配额存储,因为恢复边界的另一半正是 CLI 的规范
回执库;用假存储就等于把边界测没了。

适配器是从外面观察的:某步输出读不懂时它做什么、某步抛错时它做什么、重试时它做什么、之后
还剩下什么持久证据。过程中没有给适配器加任何状态。如果一种刻画必须先加 journal 才观察得到,
那已经是一次设计变更,而不是刻画。

具体改动 / Changes

spec_ref: docs/architecture/rfcs/ledger/controller-executor-unified-contract-v0/2026-10-27-refactor-handoff.md;
spec_revision: 2a2323756。按 C4.3 的检查项映射:identity、validation、guard/vision、
completion、writeback、spend、closeout、recovery 的义务对照已在对照条目完成;本 PR 只补
"适配器自身部分步骤行为 + 恢复边界"这一项,标记为 implemented;实际删除、部分步骤整合与
完整成本比较仍属后续实现边界,标记为 out_of_scope。

关键内容讲解

用例 钉住的行为 证据位置
步骤输出不可读 适配器把非 JSON 输出当作条件不匹配,计划在该步后停止;属主判定 blocked、failed_stage: guard、原因 quota guard returned malformed JSON test_an_unreadable_step_output_stops_the_plan_and_the_owner_classifies_it
步骤抛错 异常冒出适配器,finalize 阶段从未运行,这笔事务从未被分类;适配器不保留已成功那一步的记录 test_a_raising_step_leaves_no_finalize_and_no_adapter_local_resume
抛错后重试 计划从第一步重新进入,不中途续跑;身份由同一意图重新推导 同上用例的后半段
持久提交后抛错 CLI 的规范回执库持有已提交凭据,读回报告 settled;重试重放该回执(idempotent_replay),不扣第二个槽位,报告同一 settlement identity test_a_raising_step_after_a_durable_commit_recovers_through_the_cli_receipt
生命周期完成前抛错 没有花费,Todo 保持 open,不存在可重放的结算凭据 test_a_raised_step_before_completion_commits_no_settlement

新文件 tests/control_plane/test_host_adapter_settlement_partial_steps.py 只新增用例,不改生产
代码。双语 ledger 条目
docs/architecture/rfcs/ledger/controller-executor-unified-contract-v0/2026-10-29-c4-3-adapter-partial-step-characterization.md
及其中文镜像记录刻画结果、证据和"本条目没有建立什么";派生索引 STATUS.md 与
STATUS.zh-CN.md 由 scripts/generate_rfc_status_index.py --write 重生成为 3 entries。
完整 diff 是五个文件,+471/-2。

两条由此得到的结论:适配器在两种情形下都不做分类判定(计划停止由属主分类,抛错则根本没有
分类);恢复边界是 CLI 回执而不是适配器状态——抛错之后唯一持久存在的是 CLI 已提交的东西,
重试之所以成功是因为那份回执可以重放。

对主干的风险 / Risks

PASS:四个新用例通过;结算、MCP 结算与 host vision recovery 三个模块共 29 个用例通过。
PASS:examples/docs-governance-smoke.py ok;generate_rfc_status_index.py --check clean;
RFC 双语检查 passed;canary premerge --from-git-diff 四组检查全部 ok、0 失败 0 警告;公共边界
扫描 clean。

需要如实说明的两点。其一,新文件里的 fixture 与 tests/test_goal_mode_mcp_settlement.py 中的
fixture 有重叠;这里选择本地复制而不是跨测试模块导入私有 helper,是为了让这份刻画不依赖一个
与它无关模块的内部实现,代价是重复约 60 行。其二,刻画用例的作用就是把当前行为固定下来,
因此后续任何对适配器或恢复路径的改动都会让它失败——这是本切片想要的信号,不是脆弱性,但它
确实意味着这份测试会在后续整合时被有意改写。

UNVERIFIED:真实 Host 的采用情况、跨后端整合与完整成本比较,本轮没有重新资格。

非阻断建议:无新增项。对照条目给出的删除前提条件没有被本 PR 触碰,也没有被削弱。

我的整体评价 / Verdict

本切片的有用结果已成立:long_horizon improved,限定为下一个整合切片现在拿到的是实测行为
而不是对适配器的假设,同时"恢复边界在 CLI 回执"这一结论第一次有可执行证据,而不是只有措辞;
user_experience preserved,没有运行时、schema、wire 或默认值变化,既有入口与恢复步骤不变。

bounded refactor 判断为当前无需生产代码重构:适配器作为传输层的行为已被钉住,删除它的收益
仍要由后续整合证明。该批准不授予合并、安装、模型执行或新副作用权限。

English verdict: APPROVE — 9bd553c. The characterization pins the host adapter's partial-step behavior against the real TypeScript owner and the real CLI, and it locates the recovery boundary in the CLI receipt rather than adapter state; the new cases, the settlement modules (29 passed), the RFC bilingual check, the derived index check and canary premerge all pass at this head. No runtime, schema, wire or default change, and no deletion is proposed.

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewer: model_agent; OpenAI gpt-6.1-sol; reasoning effort max; runtime_reported.

REQUEST_CHANGES:四个新增测试有价值且通过,但两个 P2 文档结论与真实阶段读回、同一 head 的父条目冲突。审查完整 head 641bfb647b39ae6181ed295cced4ffabc9cbf995;全量 merge-base 9dcdc0bacd455a8cf6f6146f052ffc4df0f5d04a,另区分相对 #7617 的新增部分。这些是新 ledger 的事实与后续指令问题,不是运行时代码回归。

动机 / Motivation

受影响的是准备精简 Host 结算适配器的维护者:他们需要知道部分步骤成功后异常究竟留下什么,以及重试从哪里恢复。

此前缺少对步骤直接抛错的集中刻画;本 PR 增加四个边界用例,但把部分提交误写成已结算,又把父条目已回答的调用方问题列为待办。

可验证的增量是四个用例通过真实 TypeScript 分类器和隔离的 File CLI 固定异常传播、计划停止与同身份重试;文档中的阶段结论和后续方向仍须修正。

本 PR 不修改运行时恢复逻辑、不证明 SQLite 或 PostgreSQL 平台资格,不授予删除适配器、合并或执行实际任务的权限。

当前缺口是准确保留各提交阶段与 validation 回执,并与已确认的词汇结论统一后续方向;完整适配器删除与成本资格仍未交付。

改动思路 / Approach

现有 Host adapter 只解释计划和条件;TypeScript finalizer 分类正常返回或停止的结果,CLI canonical receipt store 保存已提交副作用。一个步骤直接抛错会提前离开 adapter,重试又从首步骤进入;能否安全继续,取决于原 identity 与已提交回执,而不是 adapter 保存了中途游标。应保留这一现有职责分配,测试不需要引入第二个 journal。

最强反例是让现有四测都通过,再在真实 CLI 已提交 lifecycle 或 writeback 后抛错。新增 post-commit 用例实际选的是 quota-spend 后,因此只能证明最终 spend 的重放,不能证明所有中间 commit 都 settled。独立反例包裹实际 dispatch 并读取真实 phase owner,未用 mock 预造结论。当前 head 的实测如下;这是运行观察摘要,不是新状态定义。

异常位置 实际 replay phase 仍需动作或已有回执
guard 成功、completion 前 open validation 已 committed;还缺 writeback/spend
lifecycle completion 提交后 settlement_pending writeback_required
durable writeback 提交后 settlement_pending spend_required
quota spend 提交后 settled settled;同 identity 重试总 debit 为 1

这也说明最小修复在已有 ledger 与 fixture:准确写出各阶段、保留已发生 validation,随后重新核对相邻条目的决策。没有证据要求改变恢复机制、放松 guard 或增加公共抽象。

具体改动 / Changes

关键内容讲解

完整 PR 七路径 +699/-2,包含 #7617 的词汇确认;相对父 head 新增五路径 +471/-2。333 行测试模块保护四种不同边界:不可读输出后停止并由真实 TS finalizer 给出 blocked/guard;步骤抛错传播且不 finalize;真实 CLI spend 提交后异常重试不重复扣额;completion 前异常保持 Todo open 且零 debit。后一个用例并未读取 receipt kinds,因此不能支持“没有 settlement receipt”。

_run_provider_plan 的异常传播和 execute_turn_driver_settlement 的阶段/回执读回均未修改;新增 test 通过实际调用建立保护。既有 MCP 结算套件已覆盖多种提交后响应丢失,新增的直接 raise/finalizer 边界仍有独立价值。约 80 行局部 fixture 与既有 MCP 设置相近,可以后按真实复用需求整理;不需要为这次有用用例新造测试框架。针对同作者 #7617/#7645/#7619/#7642 做的是共享契约与依赖检查,没有重复 batch farming 的证据。

依据预变更的 docs/architecture/rfcs/ledger/controller-executor-unified-contract-v0/2026-10-27-refactor-handoff.md,spec_revision: 9dcdc0bacd455a8cf6f6146f052ffc4df0f5d04a,criterion_id: C4.3。该准则要求先比较 identity、validation、guard/vision、completion、writeback、spend、closeout 与 recovery,再考虑删除解释器,并保留原始 effect ID 与逐阶段持久读回。此处只交付有用的比较/刻画前提;完整等价、调用方采纳与成本资格仍为 deferred,不能从条目数或测试通过推导完成。

本地 PASS:4 个新增测试、25 个既有 adapter/MCP 测试,均无 skip;changed test Ruff;docs governance、RFC indexes、committed bilingual gate;主站与 EN/ZH 书三次 strict build。独立 File CLI 阶段探针验证原 identity 重试总扣额一次;将 malformed-output 的 matcher 变成 always-continue 时,现有断言能捕获多余步骤。FAIL 是新 ledger 的三项事实断言比较,不是 pytest 失败;原生 change-quality 相应保持 fail。standard premerge 的 5 项 direct checks 与 17 项 canary/risk/public-boundary checks 都通过,但总 gate 为 quality_invalid_receipt;不能把技术测试通过当成该文字正确。

对主干的风险 / Risks

两个 exact head 的相关十个生产 owner 文件与不可变基线及已验证目标 main 内容一致;没有新的运行时、默认值、权限、启用开关或持久格式。检查没有发现 prose substring 分类、新状态布尔拼装或把强制义务称为建议的问题。CI 按当前策略未查询、未等待;作者关于 CI 或旧集成运行的陈述不作为本次独立证据。

P2(新英文 partial-step ledger 第 27–28 行,中文同表):把所有 durable commit 都写为 settled,并称 completion 前没有可重放 receipt。实际 lifecycle/writeback 后仍有剩余阶段,guard 后 validation 也已存在。未来据此合并 adapter 时,维护者可能把仍待 writeback/spend 的效果当成已完成,或丢掉原 validation identity。请将 settled 限于 quota-spend 后,或明确列出阶段;两种语言都保留 validation 回执。复用当前 File fixture,在真实 dispatch 后异常,并读取 receipt kinds/progress;同 identity retry 仍须只扣一次。复测入口为 uv run --extra test pytest -q tests/control_plane/test_host_adapter_settlement_partial_steps.py,应先补齐这些逐阶段断言。

P2(英文第 70–72 行,中文 Next slices):仍要求为 vocabulary unification 找到同时采用两路径的 caller。但本 head 包含的 confirmation 已指出既有 caller,并明确撤回三标签统一候选。把已回答的问题重新列为后续会误导下一轮工作。请同步 EN/ZH,把已撤回的标签合并与另行存在的 Host step registry #7619 区分;完整删除的前提继续保留,不必新建任务或修改运行时。

另有非阻断 P3:新中文 partial-step Parent link 使用英文 fragment,实际生成中文章节 ID 是 c43-adapter;换为 #c43-adapter 即可。strict build 的非阻断 INFO 未被抹去;HTML heading 与 href 已独立核对。

语义与 CI 对齐

当前复用 existing vocabulary,未新增 enum/协议。问题发生在正文对既有 typed settlement progress 的错误概括及后续指令漂移;原生语义比较为 violated。最小修复是上述两项 ledger 订正和已有 fixture 的精确阶段断言。随后重跑 focused pytest、RFC index、bilingual gate 与 docs build。CI 未查询且不等待;本地事实失败已足以 request changes,不能通过改措辞分类、降低门槛或将其标为未验证来绕过。

我的整体评价 / Verdict

测试是有用的 justified_increment,仍不足以支持本文的泛化结论。long_horizon 为 regression:新指导可能让后续维护选择错误的恢复/收敛动作;这是文档决策风险,不是已发生的线上损害。user_experience 为 preserved:产品运行时未动,保留 P3 导航问题。兼容评估不适用,没有新增 decoder 或持久格式;体量合理,修复应限于 ledger 与已有测试,而不是扩大为 settlement 重写。

本次只改 RFC ledger 正文、索引和测试;检查的文档路径没有布局、主题或首屏交互改动。未做整页视觉检查;实际 MkDocs HTML 的锚点检查属于自动验证。实际原生 Host 采纳、Windows、SQLite/PostgreSQL 阶段矩阵和持续完整成本收益仍为 UNVERIFIED;本次独立探针仅限定隔离 File 路径。请在新 exact head 修正两个 P2 并补阶段断言后复审;当前结论不授权 merge、dismiss 其他 review 或更改实际任务状态。

English verdict: REQUEST_CHANGES

| A step returns output the adapter cannot read | `_provider_condition_matches` treats a non-JSON output as a condition that did not match, so the plan stops after that step | The finalize phase still runs and the owner classifies the stop: `blocked`, `failed_stage: guard`, reason `quota guard returned malformed JSON` |
| A step raises | The exception propagates out of the adapter. The finalize phase never runs, so the transaction is never classified. The adapter keeps no record of the step that already succeeded | Nothing is classified, because the owner is never asked |
| A retry after a raise | The adapter re-enters the plan at its first step and never resumes mid-plan | The identity is re-derived from the same intent, so the same settlement identity is used |
| A step raises after a durable commit | The adapter leaves nothing behind; the CLI's canonical receipt store holds the committed receipt | The readback reports `settled`; the retry replays that receipt (`idempotent_replay`), spends no second slot and reports the same settlement identity |

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] 按实际提交阶段描述结算状态

新增 post-commit 测试在 quota-spend 提交后抛错,因此不能支持这里对任意 durable commit 的概括。包裹真实 CLI dispatch 并在 lifecycle/writeback 提交后抛错,实际分别得到 settlement_pending/writeback_required 与 settlement_pending/spend_required;只有 spend 提交后才是 settled。guard 成功而 completion 前抛错时,Todo 确实仍 open、debit 为零,但 validation receipt 已 committed,也不符合下一行的“没有 settlement receipt”。这会让未来 adapter 合并误判剩余副作用或丢失原 validation identity。请在 EN/ZH 表中限定 post-spend 情形或分阶段写明,并在已有 File fixture 中读取 receipt kinds/progress,验证原 identity 重试只扣一次。运行时未改,本 finding 针对新增文档与其证据范围。


Unchanged by this entry. A deletion of the adapter-side interpreter still
needs the preconditions recorded in the comparison entry, and vocabulary
unification still needs a caller that adopts both paths.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] 与父条目已确认的词汇结论对齐

同一个 head 包含的 2026-10-29-c4-3-settlement-vocabulary-confirmation.md 已确认既有 governed-capability caller 同时使用两路径,并将三标签统一候选标为 withdrawn。这里再次要求先找这样的 caller,会把下一轮工作导向已经回答的问题。请同步 EN/ZH Next slices,以当前父条目为准:保留删除适配器的真实前提,区分已撤回的标签合并与独立 Host step registry 提案 #7619;无需新增任务或恢复机制。复核父子条目在相同 revision 对已完成决策与剩余工作的描述一致。

@@ -0,0 +1,64 @@
# C4.3 适配器部分步骤行为刻画

- 上级:[controller/executor RFC,C4.3](2026-10-27-refactor-handoff.zh-CN.md#c43--settlement-adapters-over-existing-primitives)。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P3] 使用中文目标的实际章节锚点

实际 strict build 的中文目标章节 ID 是 c43-adapter,这里仍使用英文 fragment #c43--settlement-adapters-over-existing-primitives。页面能打开,但不会跳到对应章节。请将 fragment 改为 #c43-adapter,并核对生成 HTML 的 heading 与 href。这是非阻断导航问题。

@mergify

mergify Bot commented Oct 29, 2026

Copy link
Copy Markdown

This pull request has merge conflicts with main and cannot be merged
until they are resolved. Please rebase or merge the base branch, @xiaoan17.

Choose the remote for the base repository, not an out-of-date fork.
For a fork clone, first inspect git remote -v; upstream must point
to https://github.com/loopx-project/loopx.git. If it is absent, add it
with git remote add upstream https://github.com/loopx-project/loopx.git.
Then run:

git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEAD

For a same-repository clone whose origin points to
https://github.com/loopx-project/loopx.git, use origin instead of
upstream for fetch/rebase. If you prefer merging the base, use
git merge <base-remote>/main and push normally.

Keep the DCO Signed-off-by trailer on every commit when you rebase.
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 29, 2026
@xiaoan17
xiaoan17 force-pushed the codex/c43-3-adapter-partial-step-characterization branch from 641bfb6 to 8eb54b6 Compare October 29, 2026 14:27
@mergify mergify Bot removed the needs-rebase Mergify: the pull request has merge conflicts with its base branch label Oct 29, 2026
@xiaoan17
xiaoan17 force-pushed the codex/c43-3-adapter-partial-step-characterization branch 3 times, most recently from 276ee7f to a1dbdce Compare October 29, 2026 15:14
loopx-agent
loopx-agent previously approved these changes Oct 29, 2026

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewer: actor_kind=model_agent; model=gpt-6.1-sol; provider=OpenAI; reasoning_effort=max; declaration_source=runtime_reported.

APPROVE;没有阻断发现。 完整复审 head a1dbdcecde364d1506e4482d1fcbc75f81d6830e。旧两个 P2 和中文锚点 P3 均已解决;仍有一项非阻断措辞建议:同句把步骤登记切片称为“仍开放”又说它已在 #7619 合入。

动机 / Motivation

受影响的是准备精简 Host 结算适配器的维护者:他们需要知道部分步骤成功后抛错留下哪些回执,以及同身份重试如何继续。

此前新增表格把中间提交泛化为已结算,并把父条目已回答的调用方问题列为后续;本次改为逐阶段回执断言,区分尚缺写回、尚缺扣额与已经结算。

当前 37 项相关测试通过;四阶段独立真实 CLI 探针均按原 Turn 身份重试到 settled,每例总扣额一次,EN/ZH 表格与实测读回一致。

本 PR 不改变恢复实现、不删除适配器、不认证 SQLite/PostgreSQL 或实际 Host 采用,也不证明完整成本收益。

完整适配器整合、调用方采用、等价证明与成本比较仍按原 C4.3 前提处理;步骤词汇登记已由合并的 #7619 完成。

改动思路 / Approach

继续使用已有职责分配是更小的方案:TypeScript 生成并分类正常返回的步骤计划,Python 适配器执行传输,CLI 规范回执库保存已提交的效果。步骤直接抛错会在 finalize 前退出;下一次从 guard 重进,并依靠相同身份与回执继续,而不是适配器保存中途游标。这次无需增加 journal 或另一种事务格式。

本轮将旧 head 到新 head 的修复与完整提案分开检查。当前 base 已包含 #7619 的步骤词汇登记;两个 adapter owner 的源码相对旧评审确有该集成变化,因此没有直接继承旧测试资格。当前完整 PR 没有修改生产 owner,本次 37 项测试及四阶段真实重试均在新组合上执行。

具体改动 / Changes

关键内容讲解

完整差异 7 路径、+636/-4:463 行测试包含五个函数、八个参数化用例;EN/ZH 新 ledger 逐阶段记录结果;两份既有词汇确认把 #7619 改为已合入;两份派生索引记录第五条 ledger。它保护实际 adapter/CLI 边界,不是固化某次报告的字句。

独立依据是改动前 C4.3 handoff,spec_ref: docs/architecture/rfcs/ledger/controller-executor-unified-contract-v0/2026-10-27-refactor-handoff.md;spec_revision: 58205c62a16a9e98ab3319ada3bab5aea74b829d;criterion_id: C4.3。当前交付的是原 comparison 的 characterization candidate 2。C4.3 要求的完整调用方采用、事务等价、删除前提与完整路径成本仍为 deferred;不能以这次用例通过宣称父级全部完成。

test_a_raised_step_after_a_durable_commit_leaves_only_that_stage_pending 现在直接读取实际 phase、progress 和 receipt kinds。独立探针又对每个阶段执行完整重试,结果如下;这张表是源码限定的实际观察,不是新增状态定义。

抛错发生在提交之后 重试前实际状态 已提交回执 同身份重试后
guard open / writeback_required validation settled,总扣额 1
lifecycle completion settlement_pending / writeback_required validation settled,总扣额 1
durable writeback settlement_pending / spend_required validation、durable_writeback settled,总扣额 1
quota spend settled validation、durable_writeback、quota_spend settled,总扣额 1,spend replay

不可读输出由真实 TS finalizer 判为 blocked/guard;直接抛错则没有 finalize。两个旧 P2 的关键事实因而已修正:早期 validation 不再丢失,中间提交不再泛化为 settled,已撤回的三标签统一也没有被重新要求。实际 strict-build HTML 同时验证了 EN 的 c43-settlement-adapters-over-existing-primitives 和 ZH 的 c43-adapter,旧导航 P3 已解决。

对主干的风险 / Risks

PASS:37 项当前 adapter/词汇/MCP/vision 测试;独立四阶段完整重试;changed test Ruff;RFC bilingual、派生索引、docs governance 与 strict MkDocs build。标准 premerge 的 5 个直接检查和 17 个选中检查全部通过,精确范围 change-quality 收据有效,公共边界扫描通过。没有查询、轮询或等待远端 CI。

独立探针首次脱离仓库隔离 fixture 运行时,被 canonical creation 绑定校验拒绝,未取得业务结果;随后通过仓库原有 conftest 隔离路径运行才完成四阶段验证。另一次初始 pytest 命令引用不存在的模块而没有收集测试,MkDocs 首次调用也因环境未安装而未启动;这些是评审 harness/环境失败,原记录保留,未改成通过。当前结果来自修正入口后的完整执行,未放松生产或测试约束。

[P3] 新英文 ledger 第 88–90 行及中文对应句仍把“仍开放的切片”写为已合入 #7619。#7619 的远端状态确为 MERGED,当前 base 也包含登记实现。建议直接写成“该独立登记切片已完成”,把开放工作留给真正的删除/采用前提。它没有重新引入旧的错误调用方前提,也不影响本次恢复断言,因此不阻断批准。

我的整体评价 / Verdict

这是有用、可逆的 justified_increment。long_horizon improved,仅指下一次整合获得可靠的阶段与重试依据;尚无实际长程收益测量。user_experience preserved,既有 CLI/MCP 操作、权限和恢复步骤未改变,也没有增加用户准备、确认或手工转录。现有词汇 owner 保持;新增参数表是测试局部期望,不引入公共协议。约数十行 fixture 与 MCP 用例相近,但直接抛错和逐阶段回执具有独立保护价值;无需为此创建公共测试框架。

本次只改 ledger 正文、索引和测试,没有布局、主题、首屏或交互实现变化;未做整页视觉检查,HTML 锚点检查属于自动验证。真实 Host、Windows、SQLite/PostgreSQL 阶段矩阵与持续完整成本仍未验证。批准不等于这些资格完成,也不授予合并、安装或删除适配器的权限。

English verdict: APPROVE

At a1dbdcecde364d1506e4482d1fcbc75f81d6830e, real phase readback and original-identity retries resolve the prior blockers; one open-versus-merged wording suggestion remains nonblocking.

the confirmation entry withdrew — one typed owner for `guard`,
`lifecycle_completion` and `validation` — is not reopened here: that entry
already identified the shipped caller that adopts both paths and recorded the
candidate as withdrawn. The slice that remains open is the shared owner for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P3] 将已合入切片与仍开放工作分开表述。这里在同一句中将步骤登记称为 “remains open” 又称其已在 #7619 合入,中文对应句也有同样歧义。#7619 的实际远端状态是 MERGED,当前基线已包含登记实现。建议改为“该独立登记切片已完成”,把开放工作留给真实的删除/采用前提。新的阶段断言及旧调用方问题已经核实解决;此项只是非阻断措辞建议。

@xiaoan17
xiaoan17 force-pushed the codex/c43-3-adapter-partial-step-characterization branch from a1dbdce to a29c001 Compare October 29, 2026 16:55
xiaoan17 added 2 commits October 30, 2026 01:07
C4.3's obligation comparison recorded that the host Todo adapter keeps no
journal of its own, and left the adapter's own behavior when a step succeeds
and a later step fails uncharacterized, together with the place where the
recovery boundary between the adapter and the CLI receipts sits. A slice that
moved this path would otherwise have had to assume both.

Four cases now pin that behavior with the real TypeScript owner and the real
CLI:

- an unreadable step output stops the plan, and the owner classifies the stop
  (blocked, failed_stage guard, malformed-JSON reason);
- a raising step ends the call before the owner is asked to finalize, so the
  transaction is never classified, and a retry re-enters the plan at its first
  step because the adapter keeps no record of the step that already succeeded;
- a raise after a durable commit leaves the committed receipt in the CLI's
  canonical store: the readback reports settled, and the retry replays that
  receipt, spends no second slot and reports the same settlement identity;
- a raise before the lifecycle completion commits no settlement at all.

The adapter makes no classification decision in either case, and the recovery
boundary is the CLI receipt rather than adapter state. The existing lost
response case stays where it was; this adds the raised transport surface.

The bilingual ledger entry records the characterization and what it does not
establish. No runtime, schema, wire, default or recovery behavior changes.

Validation: the four new cases pass; the settlement, MCP settlement and host
vision recovery modules pass (29 tests); docs governance smoke passes; the RFC
bilingual check passes; canary premerge --from-git-diff is green; the public
boundary scan is clean.

Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The characterization claimed that any durable commit left a settled
readback, but the case it exercised only committed the quota spend. A
raise after the lifecycle completion or the durable writeback leaves a
settlement pending, and the owner names the stage that is still owed.

Measure the real dispatch for each stage and read back the committed
receipt kinds, the replay phase and the settlement progress, so the
documented stage table is executable rather than prose.

Signed-off-by: xiaoan17 <anbc1224@gmail.com>
xiaoan17 added 3 commits October 30, 2026 01:07
The characterization described any durable commit as settled and the
before-completion case as having no settlement receipt, but the guard
has already committed the validation receipt and only the quota spend
settles the transaction. Spell the stage table out from the measured
readbacks, and drop the claim that a settlement receipt does not exist
before the lifecycle completion.

The next slices also asked for a caller that adopts both settlement
paths, which the parent confirmation entry already found and recorded
as a withdrawn candidate. Keep the deletion preconditions, point the
open slice at the host-adapter step registry in loopx-project#7619, and fix the
Chinese parent anchor to the id the strict build generates.

Signed-off-by: xiaoan17 <anbc1224@gmail.com>
PR loopx-project#7619 registered the ordered host-adapter step kinds and is merged, so
the parent confirmation entry and this entry must stop describing it as a
proposal. Update both mirrors and rebase this entry's baseline onto the
main that carries it.

Signed-off-by: xiaoan17 <anbc1224@gmail.com>
The review noted that one sentence called the host-adapter step registry
slice both still open and already merged. It is completed in loopx-project#7619. Keep
the open work on the deletion and adoption preconditions the comparison
entry records.

Signed-off-by: xiaoan17 <anbc1224@gmail.com>
@xiaoan17
xiaoan17 force-pushed the codex/c43-3-adapter-partial-step-characterization branch from a29c001 to 00f730d Compare October 29, 2026 17:20
@huangruiteng
huangruiteng merged commit 10c84d1 into loopx-project:main Oct 29, 2026
4 of 5 checks passed
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.

3 participants