Skip to content

fix(delivery): unify typed claim diagnostics before writeback - #4136

Merged
huangruiteng merged 3 commits into
mainfrom
codex/delivery-followthrough-policy
Sep 9, 2026
Merged

huangruiteng merged 3 commits into
mainfrom
codex/delivery-followthrough-policy

Conversation

@huangruiteng

@huangruiteng huangruiteng commented Sep 9, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Follow-up to merged refactor(delivery): unify history-to-obligation rules in TypeScript #4134: one typed delivery-claim diagnosis serves historical projection and pre-write checks in refresh-state and the reserved-run writer.
  • Reject contradictory new declarations before effects; retain historical records with explicit conflict diagnostics instead of silently treating them as progress.
  • Remove duplicated refresh preprocessing. Validate individual inputs in their established order, check the normalized combination, then serialize state-dependent admission and writeback under the resolved runtime lock.

Issue Or Task

Owner-requested delivery semantics refinement, stage 1 of 2. Stage 2 (#4137) reconciles historical supervision with current canonical waiting/work state. This PR does not remove the outcome floor.

Observable Behavior

New writes reject progress/preparation-only, primary-outcome/blocker and primary-outcome/explicit-follow-through contradictions. Historical conflicts become unknown plus diagnostics without rewriting records or receipts. State-only refresh, valid partial progress, valid blocker writebacks and existing settlement fences remain supported.

Malformed input now precedes registry errors and lock creation, including dry runs. This is intentional; independent field-error precedence is preserved. No new agent-authored declaration, evidence-truth validator or capability is introduced.

Validation

  • Tested revision: f66310806321b4c762565c144ba446ebe9a9350c (runtime unchanged from f23f24294)
  • Run state: finished
  • Input classes: synthetic
Check kind Result Public-safe evidence / limitation
static passed TS typecheck, diff check and unchanged maintainability ratchet
unit passed Final-head 21 focused Python regression/ratchet tests; overlapping-input precedence counterexamples fail before the fix and pass afterward
integration passed Full TS suite: 878 passed, 1 skipped (optional PostgreSQL integration)
real_entrypoint passed 258 Python tests in 541 s on the identical runtime source: disposable real refresh/history and settlement CLI, refresh/replan gates, writer boundaries and concurrent usage booking
real_backend not_applicable No AuthorityStore/provider transaction or promotion change; real PostgreSQL suite not run

Counts overlap and are not additive. No live Goal or registry was modified. AST comparison verifies that every state-dependent admission/writeback statement remains unchanged inside the explicit lock. The initial hosted mutation job stopped at an indentation-dependent CAS locator; the final test-only commit removes that incidental dependency. The CAS control passes and its deliberate regression is killed by an assertion. Final hosted CI is tracked separately from these completed local checks; pending jobs are not reported as passing.

Technical Direction

  • Base: main; refactor(delivery): unify history-to-obligation rules in TypeScript #4134 has merged.
  • Existing TS work-item delivery semantics owner; Python remains transport and persistence adapter.
  • Bounded refactor: delete the redundant decorator rather than create another preprocessing framework. The large refresh diff is mechanical indentation; inspect with whitespace ignored. No maintainability ceiling was raised.
  • No canonical Todo schema, provider mutation, writer-fence or settled-receipt changes.

Boundary Checklist

  • Public-safe synthetic fixtures and aggregate validation only.
  • Single-purpose change with DCO sign-offs; no unrelated local artifacts.
  • Historical data remains readable and immutable; contradictions fail before writes.

@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Additional regression qualification completed on d19df6b: 160 Python tests passed across delivery claim/history/semantics, real refresh-state/history CLI, refresh/replan gates and quota settlement CLI (471 s). Separate focused post-edit run: 85 passed. Counts overlap and are not additive. The real CLI negative case covers both normal and dry-run rejection without filesystem mutations. No live Goal, provider routing or settled receipt was modified. No self-merge requested.

Base automatically changed from codex/typed-delivery-history-projection to main September 9, 2026 07:49

@huangruiteng huangruiteng 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.

Request changes conclusion (author-owned PR; GitHub blocks formal self-review)

Exact head: d19df6bf7aec06fee820bab34f2580699288df30

动机

这个 PR 要解决的问题成立:新写入不能同时声称“主要成果”和“阻塞/仍需 follow-through”,而历史上已经存在的矛盾记录也不能被静默解释成进展。基线把 outcome、turn kind、typed observation 分散在写入和历史读取路径里,长期会制造错误的进展统计与后续义务。把组合规则放到 TypeScript 的 delivery outcome owner,再由 Python 只做 transport/effect adapter,比补一段提示或复制 Python 判定更可靠。

改动思路

主方向是对的:diagnoseDeliveryClaim 产出三个 typed conflict;新写入经 work_item.delivery_claim.validate 在 effect 前拒绝,旧记录由 projectDeliveryHistory 降为 unknown 并暴露 delivery_claim_conflicts,不改写历史。正向路径中,primary_goal_outcome + typed blocked observation 会在 registry/artifact 写入前失败;合法 partial progress、blocker writeback 与 state-only refresh 仍可执行。

但 refresh 集成位置破坏了既有输入校验顺序。新 decorator 先调用 normalize_progress_observation,而基线是在 refresh_state_run 内先校验 delivery_outcome。当 outcome 和 observation 同时非法时,基线先报告 unsupported outcome,本 head 却先报告 observation schema。这不是本 PR 披露的“矛盾组合修正”,会让自动化得到不同 remediation。

具体改动

关键代码讲解

  1. delivery_outcome.ts:29 的 diagnoseDeliveryClaim 是正确的单一规则 owner:只看显式 enum/typed observation,不解析 prose,也不验证证据真伪。
  2. delivery_history.py:75 的 require_consistent_delivery_claim 把 Python run facts 压缩后交给 TS,shape mismatch 与 invalid claim 都 fail closed;history.py 的 reserved-run writer 和 refresh 路径都已接入。
  3. delivery_history.ts 对历史矛盾返回 unknown、空 follow-through 和 conflict codes,status.py 将诊断保留到紧凑 readback,历史数据不被改写。
  4. state_refresh.py:127 是当前阻塞点:raw kwargs 中的 observation 被提前 normalization,形成第二个 preprocessing order;同一新增代码还使 state_refresh.py 越过 repository maintainability ratchet 的 module metric budget。

最小修复是把 claim consistency check 放到既有 delivery outcome / progress observation 归一化之后、任何 registry/effect 之前,复用已归一化值;再加一个“两项同时非法”的 precedence 回归。不要通过放宽 ratchet 来隐藏这次增长,优先把 admission seam 放回最近的 bounded owner。

对主干的风险

我在 base b8837d84790c568772c26a956316f5307851cb0e 与本 head 上跑了同一个真实 refresh_state_run 反例:unsupported_outcome + bad progress_observation。base 返回 delivery outcome 允许值错误,本 head 返回 progress observation schema 错误,证明存在可观测语义漂移。另一个独立阻塞是 required maintainability smoke 明确报告 module_metric_budget:loopx/state_refresh.py,与远端 test-shard (2) / pytest / merge-gate 红灯一致。

其余验证为绿:75 个 focused Python tests、8 个 Node delivery-history tests、TypeScript typecheck 均通过。它们证明主规则和 no-write 路径,但没有覆盖重叠非法输入的 rejection precedence,因此不能抵消上述反例。PR 还落后当前 main,需要修复后 rebase 并在新 exact head 重跑。

我的整体评价

整体架构与问题规模相称,typed conflict 作为派生诊断、TS 单一决策 owner、历史只读兼容都值得保留;不需要扩大成新 capability 或持久 ledger。当前不能批准的原因不是风格,而是两个可复现的交付门禁:公开错误优先级发生未披露变化,以及 required maintainability ratchet 失败。修复这两点并补回归后,我会按完整 PR 而不是只看最后一个 commit 复审。

English verdict: REQUEST_CHANGES at exact head d19df6b — preserve refresh validation precedence and resolve the required state_refresh.py maintainability-ratchet failure; 75 Python tests, 8 Node tests, and TS typecheck pass, but the base/head counterexample and required CI gate fail.

@huangruiteng
huangruiteng force-pushed the codex/delivery-followthrough-policy branch from d19df6b to f23f242 Compare September 9, 2026 09:00
Signed-off-by: huangruiteng <huangrt01@163.com>
@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Review resolution and design judgment

The two findings at d19df6bf7 were valid, but preserving every historical accident is not the objective. The intended admission order is: validate individual inputs, diagnose their normalized combination, then perform state-dependent admission and effects. Among independent input errors, the established deterministic order is retained because changing it supplies no new correctness benefit.

The refresh decorator introduced a second preprocessing order. It has been removed, not expanded into another admission framework. The original field normalizers run once; their results feed the existing TypeScript claim diagnosis. An explicit runtime lock surrounds the unchanged state-dependent admission/writeback body. This also removes a second registry read and makes the lock use the exact resolved runtime path used by the writer.

Observable behavior disclosure: malformed input now precedes registry access/errors and lock creation, including dry runs. This is intentional: invalid requests should not touch storage. Valid requests retain state-dependent admission and persistence serialization. The new contradiction checks remain enforced write admission, not optional guidance; historical contradictions remain visible diagnostics without rewriting receipts. This does not waive Todo/replan/settlement obligations or alter the small-delivery floor.

Scope and review lenses

  • Typed rules and repository reuse: the existing TS delivery-outcome owner remains the sole combination-rule owner; Python transports normalized facts. No prose classifier, new persisted declaration, or new capability/provider.
  • Neutrality and authority: diagnostic names and errors are goal-neutral. This does not grant execution, claim, provider, or evidence-truth authority.
  • Proportionality: removed the duplicate wrapper rather than introducing a speculative normalization framework. The apparent large refresh diff is indentation; AST comparison confirms that every state-dependent statement inside the lock is unchanged. Ignoring whitespace, this refinement changes 13 lines in and 35 lines out of the runtime module. No maintainability ceiling was raised.
  • Default-off: not applicable; this is an explicitly disclosed core authoring/readback correction. State-only writes and valid partial-progress/blocker paths remain supported.

Validation

Exact head: f66310806321b4c762565c144ba446ebe9a9350c; base main remains 582b6572b.

  • 258 Python tests passed (541 s) on f23f24294: delivery diagnostics/semantics, actual refresh/history CLI, refresh/replan admission, writer boundaries, concurrent usage booking, settlement CLI, agent-lane actions and maintainability ratchet.
  • Full TS suite: 878 passed, 1 optional PostgreSQL integration skipped; TS typecheck and diff check passed. PostgreSQL authority is not changed and no PG-conformance claim is made.
  • Final-head focused Python/ratchet rerun: 21 passed. Counts overlap, not additive. Runtime source is identical to f23f24294; the final commit only repairs the mutation locator.
  • The first mutation CI run stopped at the CAS locator after the wrapper removal changed indentation. Replaced the indentation-sensitive block locator with the unique guard condition, preserving the deliberate stale-write bug. The real concurrency oracle passes on control and kills the CAS mutant by assertion. All 11 remaining cases that the stopped job had not reached were run locally: 11 controls pass and 11 mutants are killed by assertions. No import/setup failures are counted as kills.
  • Final hosted sign-off, dependency, basic checks, frontend build, installed and Windows checks pass. Full test shards, desktop build and stage2c reruns are still in progress at this decision; they are not reported as passed. The preceding runtime-identical head's e2e/installed/Windows checks passed. The known failure was the now-fixed locator, not a waived surviving mutant.

Public/private scan is clean. No live Goal, registry, lease, provider route or settled receipt was changed. No manual product hold remains for this bounded correction. The runtime entrypoint, historical compatibility, input priority, no-write paths, concurrency and mutation coverage form the risk-based premerge qualification; this is not a claim that all hosted CI has completed.

Decision: approved for owner-authorized admin self-merge of this exact head. Both original findings are resolved without a budget exemption or a second authority boundary.

@huangruiteng
huangruiteng merged commit ddd2920 into main Sep 9, 2026
14 checks passed
@huangruiteng
huangruiteng deleted the codex/delivery-followthrough-policy branch September 9, 2026 09:14
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