Skip to content

fix(turn): validate host candidates without losing constraints - #6962

Open
loopx-agent wants to merge 2 commits into
mainfrom
codex/turn-result-preservation-20261021
Open

loopx-agent wants to merge 2 commits into
mainfrom
codex/turn-result-preservation-20261021

Conversation

@loopx-agent

@loopx-agent loopx-agent commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Goal And Delivered Outcome

Host adapters rewrote malformed model results before the Turn executor validated them. A 1,417-character next action lost its final approval restriction when clipped to 1,199 characters, then passed validation. JSON objects and booleans could also become accepted instructions through string coercion or sparse-field defaults. Both failures committed in native File/SQLite reproductions.

The shared DSH/optional Ark adapter now preserves complete text and its JSON type. The existing executor rejects over-limit or non-string text before task validation, durable writeback, quota spend and scheduler ACK. This includes false, zero and empty containers. Valid strings, boundary lengths, legacy null/omitted optional text and sparse adapter defaults remain compatible. Generated diagnostics retain their bounds.

修复结果在校验前被截短、强转或默认值掩盖的问题:原始文本与类型现在到达既有校验器,畸形候选不能再作为有效进展结算。

  • Basis: governed Turn typed result validation and M7.4 requirement-preserving host convergence.
  • Intended base: main. Implementation baseline: 13813cfb7d83c393c9e0912161fe9c2a05542272; CI also tested integration with 01a81c1706957a256e3ffa8a78df6c7e8d6baab2 below.

Author Declaration

  • Written by: Codex, OpenAI GPT-6 model agent.
  • Implemented against: docs/reference/protocols/loopx-turn-v0.md (Typed Result) and codex_cli_result_schema in loopx/control_plane/turn_driver/codex_cli.py, at the target revision above; paired effect-interpreter RFC M7.4 checkpoint.
Criterion Disposition Implementation / decisive proof
Adapter translates; executor owns bounded typed validation implemented Original values cross host_candidate.py; existing executor validates their string type and length
Material result validates before settlement implemented Real File/SQLite CLI and DSH subprocess refuse malformed text before validator/writeback/spend/ACK
Failure, recovery and valid replay retain effect identity implemented Failed replay never reinvokes host; corrected fresh Turn and committed replay spend once
Preserve valid/legacy behavior implemented At/over-boundary Unicode, raw generic results, material/stop kinds, null absence, sparse candidates and memory isolation
Complete M7.4 adoption and total-cost qualification deferred Original convergence streams remain open; no installed adoption or model-benefit claim

Scope And Continuation

This complete, reversible correction reuses the existing result validator and IO adapter. The bounded refactoring pass keeps sparse-field aliases only for absent fields, so invalid falsy values cannot vanish. No new capability, field, configuration, validator, permission or state owner. Result validation stays in its existing owner; the adapter introduces no decision policy. Transport/output limits remain unchanged. Refusal cannot undo work a host already performed.

The parent convergence work and independent input-context proposals #6950, #6957 and #6959 remain open. This PR does not retire Python seams, change rollout defaults or claim the whole program is complete.

Validation

  • Tested source: 052ef1179ea49dca2eb84a7e15ad42c2dba7cfaf.
  • Focused source/wheel qualification: finished with synthetic and public fixtures. Full CI remains incomplete and blocked as detailed below.
Check Result Evidence / limitation
Host/executor/native/memory passed pytest -q tests/test_dsh_goal_mode.py tests/control_plane/test_host_result_semantics.py tests/test_loopx_turn_executor.py tests/control_plane/test_reward_memory_host_isolation.py: 349 passed
Native semantic rejection/recovery passed Six File/SQLite CLI→DSH subprocess cases cover over-limit text, object and false, refusal before downstream effects, failed replay and a corrected fresh Turn settling once
Before/after passed Same four new object/false native cases fail on published 5e6265967: both providers commit malformed results. Earlier overflow failure on immutable b9e60c59f remains preserved
Optional Ark passed 30 package tests; two real SDK/httpx MockTransport probes retain dictionary/false types in candidate and provider receipt, then native validator refuses them; provider fixtures cleaned up; no live model calls
Disposable wheel passed Both changed modules match source hashes; six native File/SQLite + DSH cases pass from the isolated installed wheel
Static / public boundary passed Ruff on four Python paths, declared mypy 17 targets, control-plane typecheck, paired RFC check, scoped vocabulary advisory and seven-path public scan
Native premerge passed commands / held overall 6 direct + 11 selected checks pass; overall quality stays held by the required frontend failure
Required frontend contract failed Registered Goal display-name assertion, exit 7, on immutable base and current head; UI/test source unchanged. Required check remains a hold

The exact-scope quality receipt records fail for that frontend assertion; baseline attribution does not waive it. PostgreSQL storage is unchanged. No installed App/Lark, live model or full-cost qualification is claimed.

CI Failure Attribution

The same source head 052ef1179ea49dca2eb84a7e15ad42c2dba7cfaf ran as checkout ac41b0b858a9dbdba55e21d1ebb91fa063096ad7, integrated with target 01a81c1706957a256e3ffa8a78df6c7e8d6baab2.

Failed qualification Verified cause / boundary
Release browser qualification and Chat browser shards 1, 2, 3 All stop at the registered Goal display-name source assertion, exit 7. The complete dashboard source tree is identical at target, PR head and CI checkout; the target and head reproduce that assertion locally.
Native Windows qualification Two process-cleanup tests compare 0.10000000000002274 <= 0.1; this step reports 2 failed, 34 passed, 27 skipped. Both test and runtime blobs match target, head and CI checkout. The same two failures reproduce at target/head with a controlled monotonic clock of 1000. This local probe uses mocked process handles; subsequent Windows steps were skipped.

Ark contracts on Python 3.11/3.13, real-server PostgreSQL authority, all three TypeScript shards, dashboard browser shards and dashboard acceptance report success. Python test shards remain pending at this readback. These results do not waive either failure or establish complete CI success. The earlier source quality receipt remains a failed record at baseline 13813cfb7; it is not current merge readiness for the newer target. No source change or CI restart was needed for this attribution, and no merge was performed.

Frontend / Visual Evidence

UI impact: none. Existing CLI result-validation errors carry the refusal; no new capability journey or viewport. Screenshots and preview: N/A.

Boundary Checklist

  • Scoped bug fix, tests, result contract and paired checkpoint update.
  • Public-safe synthetic fixtures and aggregate evidence; private artifacts excluded.
  • Existing English/Chinese RFC pair changed together.
  • DCO sign-off on both contribution commits.
  • No merge, installation or release performed; required frontend failure retained.

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 loopx-agent changed the title fix(turn): reject overlong results without losing constraints fix(turn): validate host candidates without losing constraints Oct 20, 2026

@loopx-agent loopx-agent 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.

Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max

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

动机

通过 DSH、可选 Ark 宿主或通用 CLI 提交任务结果、需要保留操作限制及原始文本类型的 Agent 与操作者。

旧路径会把带末尾限制的 1417 字符行动截为 1199 字符后接受,也会把对象、布尔值变成文本或默认行动后提交。当前提交保留完整文字及 JSON 类型,由原有 Core 校验器拒绝超限或非字符串候选,避免将改变含义的结果记为有效进展。

同输入真实 DSH/SDK 对照保留了末尾限制与对象、false 等原类型;File/SQLite 在任务校验、写回、扣额和 ACK 前拒绝这些结果,失败重放不再执行,修正后的新 Turn 仍可提交一次。

本次资格覆盖确定性的候选传递、类型校验和原生拒绝恢复;不证明真实模型服务、共享默认 CLI 升级、App 安装态采用或完整父里程碑完成。

后续任务可能依赖一个已丢失原操作限制、或由错误类型转换出来的“有效结果”。只看结果种类、字符串长度或提交标记,不能证明原义保留。这次以原文本和类型为依据,先拒绝畸形候选,再验证按正常规则恢复的路径,构成可独立验证的有用修复。

M7.4 的整体上下文迁移、真实模型决策与完整成本资格仍开放;既有前端必跑项失败保留独立质量限制。

改动思路

适配器保留原始候选,复用现有 Core 校验器检查字符串类型和上限,能保持单一裁决责任;独立的截短、强转或假值默认策略会在校验前改写含义,整体提高预算也不能修复类型错误。

本 PR 的合理边界是既有结果适配器与 Core 文本校验的传递和拒绝恢复;它不修改准入、任务证据资格、配额、提交权限或自动重试策略。

宿主提供候选,Core 负责字符串类型、上限和 material 结果资格。适配器不应先把对象变成一句文字,也不应把 false 当作缺失后补成“继续”。当前实现只对真正的字符串保留原有去首尾空白操作;非字符串原值进入同一个校验器。没有提高任何预算,也没有增加人工确认或另一套校验规则。

同一输入 改动前 当前行为
行动长1417字符,末尾含限制 裁成1199字符,仍接受 全文到达校验器,超限拒绝
行动为对象或false 强转成文本或补默认值后可提交 保留原JSON类型,字符串校验拒绝
字段恰到上限、合法字符串 正常接受 结果保持一致
null/省略的可选文本、稀疏字段 既有缺省处理 原处理保留
失败身份重放/合法修正的新请求 原有身份规则 失败不重执行;新请求可正常提交一次

表格来自当前 head 的同输入真实宿主和原生事务观察,不代表真实模型已经理解或遵循限制。结果拒绝不能撤销宿主之前已经执行的工作,也不赋予自动重试或新执行权。用户继续使用现有 CLI 错误读回和原请求恢复方式;没有新增能力、设置或首屏,受影响的既有宿主/CLI 旅程已通过真实本地后端验证。

具体改动

对应 head 052ef11,实际共同基线 13813cf。完整7个文件、+221/-36:生产2个文件+25/-24,测试2个文件+155/-12,文档3个文件+41。没有新模块、schema 版本、枚举、CLI 参数、存储或状态裁决 owner。既有 Python 适配与校验 seam 保留,未引入第二个领域决策实现。

关键代码讲解

  1. _complete_material_fields 只在 key 缺失时补别名。非空对象、false、零和空容器都可能是“提供了错误类型”,因此不能用 truthiness 把它们解释为缺失。完整源字段仍保留,即便另一个缺省别名有 fallback,Core 也会拒绝原来的畸形字段。
  2. build_result 对真正的字符串只做原有 .strip(),完整保留后续文字;非字符串保留原值和类型,包括假值。vision_unchanged_reason 同样处理。null/省略仍保持旧缺省行为,生成的诊断和无模型候选的有界停止分支保持原有行为。“完整”不意味着原字符串首尾空格逐字节不变。
  3. _bounded_public_text 是现有 Core 校验 owner;现在先拒绝非 null 的非字符串,再继续原来的 required、长度和 public-safe 校验。这样通用 CLI 即使直接绕过共享适配器,也不能把对象、布尔值、数字或容器强转后提交。五字段上限仍分别是120、400、1200、1200、240字符,原始宿主输出仍受12000字节限制。
  4. 既有 _host_result_stage 的顺序与身份协议没有改变。结果合同失败发生在任务校验、Goal/Todo 写回、扣额和 ACK 前。89行原生用例以超限、对象、false 三种输入分别跑 File/SQLite,并继续验证失败重放、修正后新请求和已提交重放,而不是只断言某个错误标记存在。

独立规范使用改动前 loopx-turn-v0.md,spec_revision=13813cfb7d83c393c9e0912161fe9c2a05542272,并读取同提交的 codex_cli.py 和 effect-interpreter RFC。新协议段落和 checkpoint 是被审查内容,不能自证正确:

  • Typed Result:本次实现并验证完整、原类型候选由 Core 在事务提交前判断,既有上限、字段资格及下游顺序保留。
  • Adapter Requirements:本次实现并验证 DSH/SDK 实际消费者和原生拒绝恢复;适配器不能自验证、修改规范状态、自行扣额或决定重试。
  • codex_cli_result_schema:原定义已要求这些字段为有固定长度限制的 string。显式类型拒绝由原 Core owner 承担,null 的既有兼容处理保留,错误假值不能藏进默认行动。
  • Reconcile execution/context requirements across heartbeat and TurnEnvelope:保留既有 M7.4 收敛范围,本次结果正确性切片不宣称全部上下文需求统一。
  • Adopt one typed projection in real host renderers:当前源码、隔离 wheel、实际 DSH 和可选 SDK 路径获验证;完整安装态 App/heartbeat、重入、late-result 等仍由既有 stream 承接。
  • Qualify the context shape and migration default:仍开放。没有真实模型、长期收益或完整成本实验,没有调高预算或修改迁移默认值。

对主干的风险

当前 exact head 的464项聚焦测试通过,无跳过,覆盖 DSH、原生语义、通用 executor、driver 和记忆/宿主边界。五字段在 material/wait 下分别检查恰到上限和超一字符;90组非字符串输入同时走适配结果与直接通用结果校验,包含 true、false、数字、零、空及非空容器。10组 null 控制及稀疏字段继续验证原缺省兼容。

将当前6项原生断言原样运行于不可变共同基线,均在“应拒绝、实际退出0并提交畸形结果”的语义断言失败;不是环境或 fixture 无法启动。当前相同断言通过,任务校验标记未产生、规范 Todo 状态未写、未扣额/ACK;失败身份重放不再执行。修正后新请求可以提交一次,已提交重放不重复调用或扣额。

独立固定同一签名公开 fixture、同一 SDK 实现和依赖,基线/head 各执行144组真实 DSH 子进程与真实 AsyncArk 接口/httpx MockTransport 调用。两消费者每组结果一致,全部144组完整 prompt 字节一致;29组正常、null、旧分支及既有拒绝结果完全相同。115组畸形输入发生公开说明的变化:13组超限、90组非字符串、12组稀疏错误假值,原先裁剪/强转/默认后接受,当前保留全文及原类型后拒绝。SDK 会话和 Agent 清理也确认完成。这是合成 provider 响应,不是活模型或规范捕获授权。

当前 head 另行构建 wheel、正常安装 Core 与可选 SDK 到新隔离环境。6项原生 File/SQLite、30项 SDK 全包测试通过;两个改动生产模块的字节与 source 一致,父进程和6个实际 DSH 子进程均证明来自 wheel 安装路径。私有 native 探针只记录子进程导入位置,原断言 AST 未变,没有源码覆盖安装包。此前旧 head 的运行保留在旧 revision,不冒充当前 head 的资格。

standard canary 的6项直接、2项 catalog、8项风险和1项公私边界检查通过,exit0,包含双语 RFC 和语义检查。但必跑前端命令 node apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-contract.test.mjs 在真实共同基线与当前 head 均 exit7:完整 stderr 仅换 checkout 根路径后相同,仍是 line378 的 “Personal workspace prefers the registered Goal display name”。测试与它读取的 dashboard-page.tsx 字节相同,因果路径不经过此次结果适配/校验。因此可独立归因为既存问题,同时保留质量/合并限制,不能称为通过。未获取、轮询或等待 GitHub CI。

语义与 CI 对齐

本次复用既有结果词表、字段及 typed string 合同,没有新的语义分类器。它不按“审批”等子串判断意义,而是完整传递任意领域候选。类型与长度都是强制校验义务,新文档没有把它们降为建议。默认行为确有变化:所有使用该 Core 文本校验的宿主都拒绝非字符串,DSH/SDK 不再裁剪后接受;有效字符串、null 和既有缺省语义通过独立对照保留。没有可选关闭开关,也不从“默认关闭”推断隔离。

有界整理已经应用:删除破坏性的重复传输策略,复用既有校验器,并将别名补齐明确为缺失 key。两个生产文件合计净增1行,没有新增版本分支、缓存、DSL 或迁移层;更广泛的类型迁移不应混入该修复。兄弟输入上下文/证据分类变化和父里程碑继续各自验收。

我的整体评价

APPROVE,当前 exact head 无阻塞发现。 本次 justified_increment 有明确故障、同基线语义反例、真实消费者和拒绝后的有用恢复,整体范围相称。long_horizon=preserved 指原要求与责任链保留,不代表长期效果已证明;user_experience=improved 的证据是减少静默改写,维持既有失败读回和合法恢复,未增加用户负担。

M7.4 的整体上下文迁移、真实模型决策与完整成本资格仍开放;既有前端必跑项失败保留独立质量限制。

当前切片可以独立评审,父范围不凭确定性测试被宣布完成。author-owned COMMENTED 仅承载批准结论,不是正式自批准、dismissal、合并或共享安装授权;独立前端质量红项与当前 merge readiness 必须分别读回。

English verdict: APPROVE at 052ef1179ea49dca2eb84a7e15ad42c2dba7cfaf. Full candidate text and JSON types now reach the existing Core validator; malformed falsy fields cannot disappear into defaults, and raw generic results receive the same type check. The 464 focused cases, 6 immutable-base semantic failures, 144 matched actual DSH/SDK cases per revision and a separately installed wheel support this bounded repair and useful recovery. Retain the unrelated frontend quality hold and unqualified parent/installed-host/model/whole-cost acceptance. No merge or shared upgrade authority is inferred.

This branch has not been deployed

No deployments
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