diff --git a/docs/architecture/rfcs/monorepo-distribution-split-v0.md b/docs/architecture/rfcs/monorepo-distribution-split-v0.md index 9df8bf596f..20c31945ce 100644 --- a/docs/architecture/rfcs/monorepo-distribution-split-v0.md +++ b/docs/architecture/rfcs/monorepo-distribution-split-v0.md @@ -2984,3 +2984,291 @@ cost and adoption remain unqualified. Preserve I3 for at least one minor release, M1/#8011, full R0/V10/R1, D2/D5/D6/D3, context/model/split-install, PostgreSQL host/wheel and every frozen failure. The original task remains open; this checkpoint does not authorize merge or declare the minimal kernel complete. + + +### 2026-11-08 — Canonical source scalar-comparison refinement + +The existing `todo.read` owner now uses exact equality for unchanged primitive +fields after its complete canonical-field digest and JSON clone. Containers and +altered scalar values keep the full canonical digest comparison; missing fields, +source-lane additions, scalar-fact protections and stale-reference rejection +remain with their current owners. No source allowlist, provider cache, protocol, +configuration or competing decision owner is introduced. + +A fresh synthetic complete-CLI caller trace on `main@aee777008` confirms the +existing two-role native transaction is adopted. Quota before/after projections +belong to different budget decisions, so their repeated read recipes do not +justify an authority cache. The bounded refactoring stays in the existing +canonical source comparison instead of collapsing those decisions. + +Final `read_transaction.ts` SHA-256 `ac0ae4311e4fe5c385ec75b3569cd8ebbe98328189e2885b5ecdcccb11c476b3` +passes 61 Python and 56 TypeScript cases plus real isolated PostgreSQL16.15 +store391/service11, zero skips in these qualified runs. The immutable original +passes the selected native PostgreSQL source-protection case; a mutation that +treats all primitives as unchanged fails it. Parent replacement, deletion and +restoration, changed notes/scopes/counts and provider-state readback remain covered. +Four complete 101-Todo source/wheel × File/SQLite CLI lifecycles preserve sum45, +original completion time, four receipts, one debit, restart and refusal/replay; +each owns and observes two normal native process exits. The isolated wheel's +runtime source bytes match the checkout. Validation uses macOS arm64, +CPython3.13.5 and Node22.22.3. Earlier toolchain/setup failures and a service-env +skip remain preparation evidence, distinct from the qualified runs. + +This removes redundant scalar digest work; it is not a matched-cost or full +marginal-cost/adoption result. Frozen cost, attribution and normal-bytecode +campaigns remain unchanged. Preserve the original complete transaction and all +I3/minor-release, M1/#8011, full R0/V10/R1, D2/D5/D6/D3, +context/model/split-install, PostgreSQL host/wheel and historical failure gaps. +Exact-head review, required CI/readiness and maintainer merge authority remain +separate gates; no installed-host upgrade or Goal completion is claimed. + + +### 2026-11-09 — Reuse validated complete source-basis bytes + +The existing Python Todo compatibility transport now retains its validated +canonical field bytes as the complete source basis. It previously encoded each +field twice, once for the basis and once for digest validation. The basis is +only decoded as JSON; mapping insertion order is not a source difference. Full +digest mismatch fallback, scalar-fact protection, request-scope provenance and +source/revision/lease/refusal/replay guards remain. No decoder, cache, provider, +configuration, protocol or competing decision owner is added. + +On the same real isolated SQLite field observation, the immutable original +encodes two fields four times and the candidate twice; both retain complete +values and empty source differences. The original passes two mapping-order and +scalar-protection characterization cases; the candidate passes all nine canonical +source cases across File/SQLite. Final `summary_item.py` SHA-256 `a8ca890eee547929060ac326fc8b85ca9c14a8fd5ec850deb2fe3e6586628513` +matches the isolated wheel. Four complete 101-Todo source/wheel × File/SQLite +CLI lifecycles preserve sum45, original completion time, four receipts, one debit, +restart and refusal/replay, with two normal native exits per lifecycle. +Validation uses macOS arm64, CPython3.13.5 and Node22.22.3. + +This is an encoding mechanism refinement, not matched-cost or full marginal-cost +and adoption qualification. Frozen cost, attribution and normal-bytecode +campaigns remain unchanged. PostgreSQL host factory absence is already recorded; +its store/service checks do not qualify a source/wheel host journey. Retain every +original acceptance and I3/minor-release, M1/#8011, full R0/V10/R1, D2/D5/D6/D3, +context/model/split-install, installed-host, full-cost/adoption and historical +failure gap. Exact-head review, CI/readiness and maintainer merge authority remain +separate gates. + +### 2026-11-09 — Combined report and canonical-source caller qualification + +The original #8360 proposal now combines report construction isolation with +the scalar comparison from #8372 and complete validated source-basis reuse from +#8374 over target main `aee777008`. Runtime qualification uses +`8b4df2fac966933e200ba15bb36b2f7afb9a194a` and preserves the original proposal's +ancestry. The same existing report and typed Todo owners retain configuration +validation, complete canonical reads, source/revision/lease protection and +receipt/refusal/replay semantics; no decoder, authority cache or provider is added. + +Four fresh 101-Todo source/wheel × File/SQLite complete CLI lifecycles retain +the original fixture/artifact fingerprints, scopes and completion time, four +receipts, one debit and two observed normal native exits each. All 1,921 present +tracked wheel entries match source bytes; seventeen existing source-only, +documentation and media omissions remain. On Node 22.22.3 and CPython 3.13.5, +the control-plane typecheck and 105 adjacent TypeScript cases pass. Real isolated +PostgreSQL 16.15 store/service checks pass (391/11, zero skips), and the owned +server is stopped afterward. + +The isolated wheel's packaged browser passes `typed-actions`, +`conversation-activity` and `conversation-history-recovery` with synthetic +upstream data. The original exact interruption assertion and completion/Turn +isolation remain. Extended report caller checks return 70 passes and one failure: +the calendar capability-action test expects a missing `turn_envelope`. The same +test fails identically on immutable target main `aee777008`; this is retained +as an unresolved validation gap, not relabeled as passing. Initial relative +interpreter, installed-package provenance and missing-browser preparation +failures are retained separately from the qualified runs. + +This combined boundary qualifies integration correctness, not whole-path or +full marginal-cost/adoption benefit. Frozen cost, attribution, normal-bytecode +campaigns, every original acceptance gap and historical failure remain intact. +#8372/#8374 remain separate open proposals pending reconciliation; combination +is not merge. Exact-head review, CI/readiness and explicit maintainer merge +authority remain required. The original task stays open. + +### 2026-11-09 — Reconcile merged loading and the remaining source proposal + +Before publication, #8360 was observed merged as `e37a1d691`; #8011 is also in +target main `520a1ab47`. The remaining source refinements now continue through +the original #8372 proposal, preserving its `cbda59c6e` ancestry and incorporating +#8374's complete-basis change. The merged report proposal is not recreated. + +Fresh runtime qualification at `4e72980bee91c7bbfcedb2eb481b8573113340b3` over +that main passes 82 focused Python cases, 105 TypeScript cases, typecheck, +real isolated PostgreSQL store/service (391/11), four complete 101-Todo +source/wheel × File/SQLite lifecycles and the three packaged browser scenarios. +Wheel ownership remains 1,921 matching entries and seventeen existing omissions. +The standard premerge at that runtime revision passes six direct and nineteen +selected checks. The expanded report family remains 70 passed/one failed; +immutable `520a1ab47` reproduces the same `turn_envelope` assertion failure. +That unresolved packet-contract qualification remains a hold alongside exact-head +review, required CI/readiness and maintainer merge authority. Initial collection, +environment and interrupted interim runs retain their original limits. + +This reconciles shipped loading with the remaining reviewed source boundary; +it does not close the original task, installed-host, PostgreSQL host/wheel, +full-cost/adoption or any other retained acceptance. No frozen campaign is rerun +or relabeled, and this lane performs no main merge. + +### 2026-11-09 — Reconcile the M0 ratchet after the merged status move + +The exact #8372 qualification head's CI fails its kernel-static prerequisite: +merged #8011 moved `chat_status_api.py` into `chat/status_api.py`, reducing the +root from 128 modules to 127, while the fixture still pins 128. The downstream +Stage 2C, checks and aggregate pytest jobs reject their skipped/failed inputs; +those results do not establish new runtime failures or passes. + +The existing M0 fixture now records measured main `520a1ab47` and lowers its pin +to 127. Its schema, entrypoint allowlist, exact-count rule and over-budget +rejection remain intact. The same seven kernel-static checks pass on CPython +3.13 and 3.11. In the same isolated source tree, an added unapproved 128th root +module still fails; removing only that synthetic module restores the pass. +The original CI and local 127-versus-128 failures remain retained evidence. + +This repairs the validation handoff for an already merged module relocation; +it neither moves another runtime owner nor changes a production limit. Pages, +the separate report packet-contract gap, full CI/review/readiness and every +original installed-host, PostgreSQL host/wheel, full-cost/adoption and frozen +qualification remain separate. The complete original task stays open. + + +### 2026-11-09 — Complete-source report caller qualification + +The M0 pin repair passes CI, together with the real PostgreSQL, typed kernel, +TypeScript, browser and Stage 2C checks at the recorded proposal head. Integration +now includes target main `1cba745f5` while retaining the original proposal ancestry. +The report calendar CLI smoke still fails on that integrated source because it +reads the retired `turn_envelope` carrier. Its `None` replan assertion also +belongs to the old projected adapter: the complete source retains competing +advice while the typed controller owns final capability precedence. + +The smoke now gives the single `work_contract` directly to the existing controller. +Across plan, dry-run and executing generic/Codex CLI calls, it checks the same +owned next command, idle host, absent premature report artifacts and unchanged +effect flags. A changed command with the original source binding is rejected. +Dropping the next command from the real CLI result makes the independent smoke +assertion fail. No runtime decoder, compatibility adapter or authority owner is added. + +The source and isolated-wheel report families each pass all 71 cases; 101 +adjacent Python cases and the control-plane typecheck pass. All inventoried +present tracked wheel entries match the source bytes. +This closes the stale caller-test gap without claiming new execution semantics, +full-cost/adoption benefit or installed-host qualification. Initial reader-choice +and missing-bundle preparation failures remain separate evidence. Pages retains +its known out-of-scope broken link; exact-head CI, review/readiness, maintainer +merge authority and every original acceptance/frozen campaign remain open. + + +### 2026-11-09 — Complete CLI qualification across native context integration + +The retained follow-through plan now runs through complete 101-Todo CLI +lifecycles, rather than stopping at report cases. Source and isolated wheel × +File/default-SQLite pass at proposal `bb65769cc`. The next target-main snapshot +`3b16b8491` adds native preparation/navigation changes; the combined runtime +`9baeafd8a` passes the same four complete lifecycles with a newly rebuilt wheel. + +Every case retains the original immutable synthetic fixture and independently +verified sum-45 artifact, complete source/lease/refusal/replay/recovery checks, +four committed receipt kinds, one debit, unchanged completion time and two +observed normal native exits. The existing scalar/source-basis owner bytes +remain unchanged. All inventoried present tracked wheel entries match this +runtime source. Seven progressive-context contract cases and its typecheck pass. +The stale frontend bundle's initial wheel-build refusal remains separate from +the rebuilt package's qualification. + +This is integration correctness for the recorded source/package snapshots. +It does not rerun or relabel the frozen cost, attribution or normal-bytecode +campaigns, qualify current browser/installed-host or PostgreSQL host/wheel +behavior, or establish full marginal-cost/adoption benefit. Current exact-head +CI, review/readiness, maintainer merge authority and the existing out-of-scope +Pages hold remain separate. The original task and all original acceptance stay open. + +### 2026-11-09 — Minimum supported Python CLI qualification + +CPython 3.11.15 now qualifies the complete 101-Todo source/isolated-wheel × +File/default-SQLite lifecycle at `15c937821`, extending the earlier 3.13 +qualification. Target main `a3b589610` subsequently changes context reading and +settlement guidance; integration `220275f6a` repeats the four complete paths +against that new input and a newly built wheel. Both groups preserve the same +immutable fixture and independently verified sum45 artifact, original completion +time, full source/lease/refusal/replay/recovery behavior, four committed receipts, +one debit and two observed normal native exits per case. + +The earlier source and wheel each pass nine canonical-source cases; the current +integration separately checks the merged report CLI caller in both distributions. +Loaded wheel modules retain package provenance. Inventoried tracked entries +present directly in the new wheel match source bytes; inventory counts are not +used as a benefit comparison. Merge reconciliation retains the upstream module +baseline and unchanged 127-module limit, explicit transaction-detail delivery, +capability precedence and the original source-binding negative assertion. + +The private verifier's initial Python syntax failure and stale-bundle build +refusal remain preparation failures, distinct from runtime qualification. The +previous-head synthetic 200-item lens-switch CI budget failure remains a hold; +these CLI checks do not qualify browser performance. No frozen cost, attribution +or normal-bytecode campaign is rerun or relabeled. I3/minor-release, M1/#8011, +full R0/V10/R1, D2/D5/D6/D3, context/model/split-install, PostgreSQL host/wheel, +installed-host, full-cost/adoption and all historical gaps remain open. Exact-head +review, required CI/readiness and maintainer merge authority still apply. + +### 2026-11-09 — Current-main required-Vision refusal qualification + +The proposal incorporates `main@aa475b29f` and its merged #8388 qualification +repair at integration `2dd6c3d97`. The existing qualification adapter preserves +the native `refresh-state` refusal output for required Vision while retaining +its nonzero status and existing feedback bound. A missing stride cannot append +writeback or spend; the caller can inspect the structured refusal, correct the +same draft and then settle once. The typed writer remains the decision owner. + +On macOS arm64 with CPython 3.11.15 and Node 22.22.3, the complete existing +required-Vision family passes 35 cases from source and 35 from an isolated wheel. +The source-pinned `a3b589610` adapter fails the new missing-stride correction +case. An initial comparison accidentally loaded the candidate through pytest's +checkout insertion; that pass is invalid as a baseline result. The corrected +comparison and wheel run verify every loaded LoopX module's package origin. +These are scripted synthetic native-CLI qualification cases, not model results. + +The wheel matches 1,921 directly corresponding tracked ZIP entries, including +the qualification adapter. This count is not compared with historical inventory +methods. `read_transaction.ts` and `summary_item.py` retain the bytes qualified +at `86d08a01c`; the earlier complete 101-Todo File/SQLite source/wheel lifecycle +and PostgreSQL API/store evidence are retained, not rerun or relabeled. Standard +premerge at the integration head passes six direct and nineteen selected checks. +The bounded refactoring pass needs no additional production abstraction here; +the existing writer and feedback boundary already own this behavior. + +The review published for `86d08a01c` remains historical evidence for that head. +The updated proposal still needs current-head CI, review and merge readiness; +this qualification grants no merge authority. Preserve the original transaction, +I3/minor-release, M1/#8011, full R0/V10/R1, D2/D5/D6/D3, +context/model/split-install, PostgreSQL host/wheel, installed-host, complete-cost +and adoption gaps, and all frozen negative results. No kernel completion or +whole-path benefit is claimed. + +### 2026-11-09 — Reuse fresh canonical field digests in quota reconstruction + +The proposal incorporates `main@c44eb156d`. A complete canonical read already +returns a digest for each projected Todo field. Quota reconstruction now uses +that digest from the same fresh in-process read rather than hashing the entire +field again. The existing selector path retains its direct hash comparison. +Complete cloning, immutable provider facts, source revisions, role checks and +caller-change rejection remain in the existing TypeScript owner. The digest is +neither caller-provided authority nor retained across requests; supplied-source +fallback is unchanged. No protocol, configuration or provider is added. + +The current source and isolated wheel each pass 24 complete-source cases; 76 +adjacent planning cases, 23 native read cases and control-plane typing pass. +A swapped user/agent digest is rejected, followed by a successful valid pair. +The same negative case passes on the current-main baseline; removing digest +rejection in an isolated source copy makes both File and SQLite cases fail. +Every loaded LoopX module is checked against its selected source or wheel. +Current-main and candidate source File/SQLite CLI lifecycles, plus candidate +wheel File/SQLite lifecycles, preserve the same 101-Todo fixture and sum45 +artifact, original completion time, refusals/replay/restart, four committed +receipts, one debit and two normal native exits per case. The initially stale +frontend bundle refused packaging; rebuilding through its existing owner makes +the new wheel build pass. These are correctness checks, with no cost comparison +or rerun of frozen campaigns. All earlier acceptance gaps and negative evidence +remain open; the changed head needs fresh review, CI and merge readiness. diff --git a/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md b/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md index bbdd844eb1..489ffc7e05 100644 --- a/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md +++ b/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md @@ -2317,3 +2317,232 @@ tracked 条目逐字节匹配源码,十七项源码专用、文档和媒体遗 保留 I3 至少一个 minor release、M1/#8011、完整 R0/V10/R1、D2/D5/D6/D3、 context/model/split-install、PostgreSQL host/wheel 以及每项冻结失败。 原任务保持开放;本检查点不授权合入,也不宣告最小化内核完成。 + +### 2026-11-08 — Canonical source 标量比较细化 + +现有 `todo.read` owner 在完整 canonical field digest 与 JSON clone 之后,对完全相等的 +原始标量使用精确相等判断。容器和发生变化的标量保留完整 canonical digest 比较; +缺失字段、source lane 新增、标量 fact 保护及过期 reference 拒绝继续由原 owner 负责。 +未引入 source allowlist、provider cache、protocol、配置或竞争的决策 owner。 + +在 `main@aee777008` 上,一次新的合成完整 CLI caller trace 确认现有双 role native +transaction 已被实际采用。Quota before/after projection 属于不同预算决策,重复的 +read recipe 不能据此变成 authority cache。本次有界重构留在现有 canonical source +比较层,保留这两次决策。 + +`read_transaction.ts` 最终 source SHA-256 `ac0ae4311e4fe5c385ec75b3569cd8ebbe98328189e2885b5ecdcccb11c476b3` +通过 Python61、TypeScript56,以及真实隔离 PostgreSQL16.15 store391/service11; +这些已资格验证的运行均无 skip。不可变原版通过所选 native PostgreSQL source 保护用例, +将所有原始标量视为 unchanged 的 mutation 在同一用例失败。父级替换、删除和恢复, +note/scope/count 变化与 provider state 读回继续覆盖。source/wheel × File/SQLite +四次完整 101-Todo CLI lifecycle 保留 sum45、原完成时间、四份 receipt、一次 debit、 +restart、refusal/replay;每次都拥有并观测两条正常 native process exit。隔离 wheel +runtime source bytes 与 checkout 一致。验证环境为 macOS arm64、CPython3.13.5、 +Node22.22.3。更早的工具链/setup 失败与 service-env skip 仍作为独立准备失败保留。 + +本次减少重复标量 digest 工作,不代表 matched-cost、完整边际成本或 adoption 收益。 +冻结的 cost、attribution 与 normal-bytecode campaign 均保持原样。继续保留原完整 +transaction 与 I3/minor-release、M1/#8011、完整 R0/V10/R1、D2/D5/D6/D3、 +context/model/split-install、PostgreSQL host/wheel 及所有历史失败验收缺口。 +exact-head review、必需 CI/readiness 与 maintainer merge authority 仍是独立门; +未宣称 installed-host upgrade 或 Goal 完成。 + + +### 2026-11-09 — 复用已验证的完整 source basis bytes + +现有 Python Todo compatibility transport 将已经通过 canonical field digest +验证的完整字节复用为 source basis;此前每个字段分别为 basis 和 digest 编码一次。 +basis 只作为 JSON 解码,mapping insertion order 不属于 source difference。 +完整 digest mismatch fallback、标量 fact 保护、request-scope provenance 与 +source/revision/lease/refusal/replay guards 均保留;未新增 decoder、cache、provider、 +配置、protocol 或竞争的决策 owner。 + +在同一次真实隔离 SQLite field observation 上,不可变原版对两个字段编码四次, +候选版编码两次;二者保留完整值与空 source differences。原版通过两个 mapping-order +与标量保护 characterization 用例,候选版通过 File/SQLite 全部九个 canonical source +用例。最终 `summary_item.py` SHA-256 `a8ca890eee547929060ac326fc8b85ca9c14a8fd5ec850deb2fe3e6586628513` +与隔离 wheel 一致。source/wheel × File/SQLite 四条完整 101-Todo CLI lifecycle +保留 sum45、原完成时间、四份 receipt、一次 debit、restart 和 refusal/replay, +每条均观测两次正常 native exit。验证环境为 macOS arm64、CPython3.13.5、Node22.22.3。 + +这是编码机制细化,不代表 matched-cost、完整边际成本或 adoption 资格。冻结的 cost、 +attribution 与 normal-bytecode campaign 保持不变。PostgreSQL host factory 缺失 +已有记录,其 store/service 验证不能成为 source/wheel host journey 资格。继续保留 +原完整验收以及 I3/minor-release、M1/#8011、完整 R0/V10/R1、D2/D5/D6/D3、 +context/model/split-install、installed-host、full-cost/adoption 与全部历史失败缺口。 +exact-head review、CI/readiness 和 maintainer merge authority 仍是独立门。 + +### 2026-11-09 — 报告与 canonical-source 完整 caller 组合资格 + +原 #8360 提案在目标 main `aee777008` 上组合报告构造隔离、#8372 的标量比较与 +#8374 的完整已验证 source-basis 复用。运行时代码资格基于 +`8b4df2fac966933e200ba15bb36b2f7afb9a194a`,保留原提案祖先。沿用报告与 typed Todo +owner,保持配置验证、完整 canonical read、source/revision/lease 保护及 +receipt/refusal/replay 语义;未新增 decoder、authority cache 或 provider。 + +source/wheel × File/SQLite 四条新的完整 101-Todo CLI lifecycle 保留原 +fixture/artifact 指纹、scope、完成时间、四份 receipt、一次 debit,以及各两次 +可观察的正常 native exit。wheel 中现存 1,921 个 tracked 条目与源码逐字节一致; +十七项既有 source-only、文档和媒体遗漏保持。Node 22.22.3、CPython 3.13.5 下, +控制面 typecheck 和 105 项相邻 TypeScript 检查通过。真实隔离 PostgreSQL 16.15 +store/service 通过(391/11,零 skip),自有服务随后停止。 + +隔离 wheel 的 packaged 浏览器在合成 upstream 下通过 `typed-actions`、 +`conversation-activity` 和 `conversation-history-recovery`,保留原准确中断断言、 +完成优先及 Turn 隔离。扩展报告 caller 检查得到 70 项通过、一项失败:日历 +capability-action 测试预期的 `turn_envelope` 缺失。不可变目标 main `aee777008` +上的同一用例以同样错误失败;保留为未解决验证缺口,不重标签为通过。初始相对解释器、 +installed-package provenance 与缺少浏览器的准备失败,与已验证运行分别保留。 + +组合边界验证集成正确性,不代表 whole-path、完整边际成本或 adoption 收益。 +冻结 cost、attribution、normal-bytecode campaign、原全部验收缺口和历史失败保持。 +#8372/#8374 暂时仍是开放独立提案,待后续协调;组合不代表已合入。 +exact-head review、CI/readiness 与 maintainer 明确合入授权继续必需;原 Task 保持开放。 + +### 2026-11-09 — 对齐已合入加载与剩余 source 提案 + +发布前观察到 #8360 已以 `e37a1d691` 合入,#8011 也已进入目标 main `520a1ab47`。 +剩余 source 细化沿原 #8372 提案继续,保留 `cbda59c6e` 祖先并纳入 #8374 的 +完整 basis 修改;不重建已经合入的报告提案。 + +在该 main 上,运行时代码 `4e72980bee91c7bbfcedb2eb481b8573113340b3` 的新验证 +通过 Python82、TypeScript105、typecheck、真实隔离 PostgreSQL store/service +(391/11)、source/wheel × File/SQLite 四条完整 101-Todo lifecycle,以及三个 +packaged 浏览器场景。wheel 仍有 1,921 项字节匹配与十七项既有遗漏。 +该 runtime revision 的 standard premerge 通过六项 direct 与十九项 selected 检查。 +扩展报告检查仍为 70 项通过、一项失败,不可变 `520a1ab47` 复现同一个 +`turn_envelope` 断言失败。这项 packet-contract 验证缺口与 exact-head review、 +必需 CI/readiness、maintainer 合入授权共同保持为限制。初始 collection、环境和 +中断的临时运行继续保留各自原始资格限制。 + +本次对齐已交付的加载与剩余待评审 source 边界,不关闭原 Task、installed-host、 +PostgreSQL host/wheel、full-cost/adoption 或任何其他保留验收;不重跑或重标签 +冻结 campaign,本 lane 未执行 main 合入。 + +### 2026-11-09 — 对齐已合入 status 迁移后的 M0 ratchet + +#8372 的准确资格 head 在 CI 的 kernel-static 前置检查失败:已合入 #8011 +将 `chat_status_api.py` 移入 `chat/status_api.py`,顶层模块数从 128 降至 127, +fixture 却仍固定为 128。下游 Stage 2C、checks 与汇总 pytest 因前置被跳过或失败 +而拒绝;这些结果不能证明新的 runtime 失败或通过。 + +现有 M0 fixture 将测量基线记录为 main `520a1ab47`,并把 pin 降至 127。 +schema、入口 allowlist、精确计数规则与超额拒绝保持。相同七项 kernel-static +检查在 CPython 3.13 和 3.11 通过;同一个隔离源码树增加未批准的第 128 个顶层 +模块仍失败,仅移除该合成模块后恢复通过。原 CI 与本地 127/128 失败继续保留。 + +本次修复已经合入的模块迁移的验证交接,不迁移另一个 runtime owner,也不改生产 +上限。Pages、独立 report packet-contract 缺口、完整 CI/review/readiness,以及 +全部原 installed-host、PostgreSQL host/wheel、full-cost/adoption 和冻结资格继续 +分别保留;原完整 Task 保持开放。 + + +### 2026-11-09 — 完整源的报告调用方验证 + +M0 pin 修复已在 CI 通过,同一记录中的提案 head 也通过真实 PostgreSQL、typed +kernel、TypeScript、浏览器和 Stage 2C 检查。组合源码现已接入目标 main +`1cba745f5`,并保留原提案祖先。报告 calendar CLI smoke 在组合源码上仍失败, +因为它直接读取已退役的 `turn_envelope` 字段。replan 必须为 `None` 的断言也属于 +旧 projection adapter:完整源保留竞争建议,最终 capability 优先级由 typed +controller 决定。 + +smoke 现在将单一 `work_contract` 直接交给现有 controller,在 plan、dry-run、 +执行模式的 generic/Codex CLI 调用中验证相同的能力 owner 下一步命令、host +空闲、消费前不生成报告制品以及全部 effect 标记不变。保留原 source binding +却篡改命令会被拒绝;从真实 CLI 输出删除下一步命令会让独立 smoke 断言失败。 +没有新增 runtime decoder、兼容 adapter 或 authority owner。 + +源码和隔离 wheel 的报告调用族分别 71 项全部通过,邻接 Python 101 项及控制面 +typecheck 通过。本轮盘点中存在的 tracked wheel 条目全部与源码字节一致。这关闭旧调用方测试缺口,不宣称新的执行语义、完整成本/adoption +收益或 installed-host 资格。初次 reader 选择和缺 bundle 的准备失败分别保留。 +Pages 仍有已知且在授权范围外的断链;新 exact-head CI、review/readiness、 +maintainer 合入权限、全部原验收与冻结 campaign 仍保持开放。 + + +### 2026-11-09 — native context 组合后的完整 CLI 验证 + +保留的后续计划现在执行完整 101-Todo CLI lifecycle,补齐报告用例之外的真实路径。 +提案 `bb65769cc` 上源码和隔离 wheel × File/default-SQLite 四条路径均通过。 +下一目标 main 快照 `3b16b8491` 加入 native preparation/navigation 改动; +组合 runtime `9baeafd8a` 重新构建 wheel 后,相同四条完整 lifecycle 也通过。 + +每个 case 保留原 immutable 合成 fixture 与独立校验的 sum45 artifact、完整 +source/lease 拒绝、重放和恢复检查、四种 committed receipt、一次 debit、 +不变的完成时间和两个已观察到的正常 native exit。既有 scalar/source-basis +owner 字节不变;本次盘点中存在的 tracked wheel 条目全部匹配该 runtime 源码。 +七项 progressive-context 合同用例与 typecheck 通过。初次旧 frontend bundle +触发的 wheel 构建拒绝,与重新构建后包的验证分别保留。 + +本次是记录中源码/包快照的组合正确性。不重跑或重标签冻结成本、attribution 和 +normal-bytecode campaign,不证明当前 browser/installed-host、PostgreSQL +host/wheel 或完整边际成本/adoption 收益。新 exact-head CI、review/readiness、 +maintainer 合入权限和既有域外 Pages hold 分别保留。原任务及全部原验收保持开放。 + +### 2026-11-09 — 最低支持 Python 版本的完整 CLI 验证 + +CPython 3.11.15 在 `15c937821` 上完成 101-Todo 源码/隔离 wheel × +File/default-SQLite 四条完整 lifecycle,补充此前的 3.13 资格。目标 main +`a3b589610` 随后更新 context reader 与结算指引;组合 `220275f6a` 对这份新输入 +及重新构建的 wheel 再验证相同四条路径。两组均保留相同 immutable fixture、 +独立校验的 sum45 artifact、原完成时间、完整 source/lease 拒绝及重放/恢复行为, +每个 case 四种 committed receipt、一次 debit 和两个已观察到的正常 native exit。 + +前一组合的源码与 wheel 分别通过九项 canonical-source 用例;当前组合另在两个 +distribution 验证合并后的报告 CLI caller。已加载的 wheel 模块保持包来源;新 wheel +中直接存在的已盘点 tracked 条目与源码字节一致,不以盘点数量作收益比较。冲突协调 +保留上游 module baseline、不变的 127 上限、显式 transaction detail、capability +优先级及原 source-binding 篡改负例。 + +私有 verifier 初次 Python 语法失败和旧 bundle 构建拒绝仍属于准备失败,与 runtime +资格分别保留。前一 head 的合成 200 项 lens-switch CI 预算失败仍为 hold;本次 CLI +检查不证明 browser 性能。不重跑或重标签冻结成本、attribution、normal-bytecode +campaign。I3/minor-release、M1/#8011、完整 R0/V10/R1、D2/D5/D6/D3、 +context/model/split-install、PostgreSQL host/wheel、installed-host、完整成本/adoption +及全部历史缺口保持开放。exact-head review、必需 CI/readiness 和 maintainer 合入 +权限仍分别适用。 + +### 2026-11-09 — 最新 main 的必需 Vision 拒绝资格 + +提案接入 `main@aa475b29f` 及其已合入的 #8388 资格修正,集成 head 为 +`2dd6c3d97`。现有资格适配器为必需 Vision 保留原生 `refresh-state` 的拒绝输出, +同时保留非零退出状态和原有反馈大小边界。缺少 stride 时不能追加写回或扣额; +调用方可以读取结构化拒绝、纠正同一份草稿,再结算一次。typed writer 继续拥有决策。 + +在 macOS arm64、CPython 3.11.15 和 Node 22.22.3 上,现有完整必需 Vision 家族 +在源码和隔离 wheel 中各通过 35 项。固定到 `a3b589610` 源码的旧适配器在新增的 +缺 stride 纠正用例中失败。初次对照因 pytest 插入 checkout 路径而意外加载候选, +该通过不能作为基线结果;纠正后的对照及 wheel 运行核验了全部已加载 LoopX 模块的 +包来源。这些是脚本控制的合成原生 CLI 资格用例,不是真实模型结果。 + +wheel 的 1,921 个直接对应已跟踪 ZIP 条目字节匹配,包含资格适配器;不与历史盘点 +方法比较数量。`read_transaction.ts` 和 `summary_item.py` 保留 `86d08a01c` +已验证的字节,先前完整 101-Todo File/SQLite 源码与 wheel 生命周期及 PostgreSQL +API/store 证据继续保留,不重跑或重标签。集成 head 的标准 premerge 通过六项直接 +检查及十九项选中检查。此次有界重构审视无需再添加生产抽象,现有 writer 和反馈 +边界已拥有该行为。 + +针对 `86d08a01c` 发布的 review 仍是该 head 的历史证据;更新后的提案仍需当前 +head 的 CI、review 和 merge readiness,本次资格不授予合入权。原事务、I3/minor-release、 +M1/#8011、完整 R0/V10/R1、D2/D5/D6/D3、context/model/split-install、 +PostgreSQL host/wheel、installed-host、完整成本和 adoption 缺口及全部冻结负面结果 +均保留。不宣称最小内核完成或完整路径收益。 + +### 2026-11-09 — 在 quota 重建中复用新鲜 canonical 字段摘要 + +提案接入 `main@c44eb156d`。完整 canonical 读取已为每个投影后的 Todo 字段 +返回摘要;quota 重建现在复用同一次新鲜进程内读取生成的摘要,避免再次对整个 +字段计算摘要。现有 selector 路径保留直接摘要比较。完整克隆、不可替换的 provider +事实、来源修订、角色检查及调用方改动拒绝仍由原 TypeScript owner 负责。该摘要 +不来自调用方授权,也不跨请求保留;完整 supplied-source fallback 不变。没有新增 +协议、配置或 provider。 + +当前源码与隔离 wheel 各通过 24 项完整来源用例;76 项相邻规划用例、23 项原生 +读取用例及 control-plane 类型检查通过。交换 user/agent 摘要会被拒绝,后续合法 +配对仍成功。同一反例在当前 main 基线上通过;隔离源码副本移除摘要拒绝后,File +和 SQLite 两项均失败。所有已加载 LoopX 模块均核验所选源码或 wheel 来源。 +当前 main 与候选源码的 File/SQLite CLI 生命周期,以及候选 wheel 的 File/SQLite +生命周期,均保留同一 101-Todo 夹具与 sum45 产物、原完成时间、拒绝/重放/重启、 +四类 committed 收据、一次扣额及每项两次正常原生退出。首次打包因 frontend bundle +过期而拒绝;由现有 owner 重建后,新 wheel 构建通过。这些是正确性检查,不进行 +成本对照或重跑冻结实验。全部既有验收缺口与负向证据继续开放;新 head 仍需新鲜 +review、CI 与 merge readiness。 diff --git a/loopx/control_plane/todos/read_transaction.ts b/loopx/control_plane/todos/read_transaction.ts index 9ad1ed6128..35a6edf8b5 100644 --- a/loopx/control_plane/todos/read_transaction.ts +++ b/loopx/control_plane/todos/read_transaction.ts @@ -78,13 +78,13 @@ function validateCanonicalSource(canonical: JsonObject, expected: JsonObject): v /** Full-tree transport, with provider facts immutable. Independent additions and * the acceptance owner's observation do not acquire provider provenance. */ -function resolveCanonicalSource(fields: JsonObject, reference: JsonObject, expectedField?: string): JsonObject { +function resolveCanonicalSource(fields: JsonObject, reference: JsonObject, expectedField?: string, fieldDigests?: JsonObject): JsonObject { if ((reference.field !== "agent_todos" && reference.field !== "user_todos") || expectedField !== undefined && reference.field !== expectedField) { throw new EffectRuntimeRequestError("quota source field must name the consumed Todo role"); } const field = requireJsonObject(fields[reference.field], "quota source field"); - if (canonicalAuthoritySha256(field) !== reference.field_sha256) { + if ((fieldDigests?.[reference.field] ?? canonicalAuthoritySha256(field)) !== reference.field_sha256) { throw new EffectRuntimeRequestError("quota source projection no longer matches the original complete read"); } const record = JSON.parse(JSON.stringify(field)) as JsonObject; @@ -114,8 +114,13 @@ function resolveCanonicalSource(fields: JsonObject, reference: JsonObject, expec delete parent[last]; } else Object.defineProperty(parent, last, {value: change.value, enumerable: true, writable: true, configurable: true}); } + // JSON cloning owns containers while retaining primitive values. Exact + // equality already proves an unchanged primitive; containers and altered + // scalar values retain their full canonical digest comparison. for (const [key, value] of Object.entries(field)) { - if (key !== "goal_acceptance_contract" && (!Object.hasOwn(record, key) || canonicalAuthoritySha256(value) !== canonicalAuthoritySha256(record[key]))) { + const unchangedScalar = value === record[key] && (value === null || typeof value !== "object"); + if (key !== "goal_acceptance_contract" && (!Object.hasOwn(record, key) || + !unchangedScalar && canonicalAuthoritySha256(value) !== canonicalAuthoritySha256(record[key]))) { throw new EffectRuntimeRequestError("canonical Todo facts cannot be replaced by caller source differences"); } } @@ -157,7 +162,11 @@ export async function readCanonicalQuotaProjection(input: JsonObject, dependenci validateCanonicalSource(canonical, expected); reads.set(key, projected); } - const source = {record: resolveCanonicalSource(requireJsonObject(projected.fields, "quota source fields"), reference), + // These digests were produced with these fields by the fresh read above; + // no caller-supplied digest or field survives between requests. + const fieldDigests = requireJsonObject(requireJsonObject(projected.source_projection, + "quota source projection").field_digests, "quota source field digests"); + const source = {record: resolveCanonicalSource(requireJsonObject(projected.fields, "quota source fields"), reference, undefined, fieldDigests), python_values: reference.python_values ?? []}; request = {...request, summary_request: {...summary, source}}; } diff --git a/loopx/control_plane/todos/summary_item.py b/loopx/control_plane/todos/summary_item.py index 758b68c727..c2c9c0020d 100644 --- a/loopx/control_plane/todos/summary_item.py +++ b/loopx/control_plane/todos/summary_item.py @@ -53,15 +53,16 @@ def bind_canonical_todo_sources(result: dict[str, Any], read: dict[str, Any]) -> digest = metadata.get("field_digests", {}).get(field) if not isinstance(value, dict) or not isinstance(digest, str): continue - basis = json.dumps(value, ensure_ascii=False, separators=(",", ":")).encode("utf-8", "backslashreplace") observed = json.dumps(value, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8", "backslashreplace") if sha256(observed).hexdigest() != digest: # A modified response or a numeric JSON spelling mismatch cannot # mint a native reference. Keep the complete supplied source codec. continue + # The basis is decoded as JSON; mapping insertion order is not a + # source difference. Retain the complete bytes already validated here. fields[field] = _CanonicalTodoSummary(value, read={key: value for key, value in metadata.get("replay_read", read).items() if key != "return_projection"}, expected=metadata["source"], field=field, digest=digest, - basis=basis, request_identity=identity, + basis=observed, request_identity=identity, evaluations=(result.get("field_evaluations") or {}).get(field), source_row_fields=tuple(metadata.get("source_row_fields", []))) diff --git a/tests/capabilities/test_periodic_report_pending_intent.py b/tests/capabilities/test_periodic_report_pending_intent.py index 37095986d1..ebb89132b2 100644 --- a/tests/capabilities/test_periodic_report_pending_intent.py +++ b/tests/capabilities/test_periodic_report_pending_intent.py @@ -65,6 +65,8 @@ def _enable_calendar(registry): def test_calendar_actual_cli_preserves_capability_action_without_host(tmp_path, capsys, monkeypatch): + from copy import deepcopy + from loopx.cli import main from loopx.control_plane.turn_driver.loop_controller import decide_loop_disposition @@ -114,13 +116,22 @@ def no_host(*args, **kwargs): assert turn["capability_action"]["intent"]["command"] == command assert turn["capability_action"]["command_argv"][:5] == ["loopx", "--registry", str(registry), "--runtime-root", str(runtime)] assert turn["capability_action"]["executed"] is False + # Current plans expose one complete source; the controller consumes it + # directly instead of requiring the historical executor adapter. + assert "turn_envelope" not in turn work = turn["work_contract"] assert work["effective_action"] == "governed_capability_intent" assert work["interaction_contract"]["cli_channel"]["next_cli_actions"] == [command] assert not any(turn["effects"].values()) + # The source may retain competing replan advice; capability precedence + # must still keep the host idle and the owned consumer next. disposition = decide_loop_disposition(turn_receipt=None, quota_decision=work) assert disposition["disposition"] == "capability_action_required" assert not disposition["launches_host"] + changed = deepcopy(work) + changed["pending_capability_intent"]["command"] = "loopx turn run-once --execute" + with pytest.raises(ValueError): + decide_loop_disposition(turn_receipt=None, quota_decision=changed) assert not list((runtime / "goals" / GOAL_ID / "periodic_reports").glob("*/editorial_request.json")) diff --git a/tests/control_plane/test_canonical_quota_projection.py b/tests/control_plane/test_canonical_quota_projection.py index ba363973b0..c473948fc3 100644 --- a/tests/control_plane/test_canonical_quota_projection.py +++ b/tests/control_plane/test_canonical_quota_projection.py @@ -25,6 +25,15 @@ def test_provider_projection_uses_complete_source_differences_and_scope_exit(tmp reference = canonical_todo_source_reference(source) assert reference is not None, "the real native read must supply a validated reference" assert reference["changes"] == [] + # Mapping insertion order is not a caller change. Reordering a complete + # native summary must retain its source without hiding scalar changes. + reordered = deepcopy(source) + entries = list(reordered.items()) + reordered.clear() + reordered.update(reversed(entries)) + assert canonical_todo_source_reference(reordered) == reference + reordered["items"][0]["done"] = 0 + assert canonical_todo_source_reference(reordered) is None copied = deepcopy(source) proof = {"agent_id": fixture.AGENT_ID, "state": "waiting", "evidence": {"revision": 9007199254740993, "ratio": -0.0}} copied["vision_wait_states"] = [proof] @@ -150,6 +159,15 @@ def observed(method, params, **kwargs): assert len(requests) == 1 and len(requests[0]["requests"]) == 2 assert all("source_reference" in row["summary_request"] for row in requests[0]["requests"]) assert all(not row["summary_request"]["consume_display_views"] for row in requests[0]["requests"]) + # Each role must match its own freshly read full field, even when both + # requests share one provider read. A rejected pair cannot poison reuse. + invalid = deepcopy(requests[0]) + references = [row["summary_request"]["source_reference"] for row in invalid["requests"]] + assert references[0]["field_sha256"] != references[1]["field_sha256"] + references[1]["field_sha256"] = references[0]["field_sha256"] + with pytest.raises(ValueError, match="original complete read"): + project_todo_read(invalid) + assert select_quota_todo_summaries(user, agent, agent_identity=identity) == expected stale = deepcopy(agent) stale.expected = {**stale.expected, "cursor": "foreign"} with pytest.raises(ValueError, match="canonical source changed"): diff --git a/tests/control_plane_ts/postgresql_authority_store.integration.test.ts b/tests/control_plane_ts/postgresql_authority_store.integration.test.ts index ab4a952be1..73ef894be8 100644 --- a/tests/control_plane_ts/postgresql_authority_store.integration.test.ts +++ b/tests/control_plane_ts/postgresql_authority_store.integration.test.ts @@ -175,6 +175,29 @@ if (database && installed) { const forged = structuredClone(requests); ((forged[1]!.summary_request as JsonObject).source_reference as JsonObject).changes = [{path: ["items", 0, "note"], value: "Forged source fact"}]; await assert.rejects(readCanonicalQuotaProjection({requests: forged}, dependencies), /canonical Todo facts/); + const agentField = fields.agent_todos as JsonObject; + const sourceItem = (agentField.items as JsonObject[])[0]!; + for (const changes of [ + [{path: ["items", 0, "required_write_scopes", 0], value: "different.json"}], + [{path: ["open_count"], value: Number(agentField.open_count) + 1}], + [{path: ["items"], delete: true}], + ]) { + const changed = structuredClone(requests); + ((changed[1]!.summary_request as JsonObject).source_reference as JsonObject).changes = changes; + await assert.rejects(readCanonicalQuotaProjection({requests: changed}, dependencies), /canonical Todo facts/); + } + // Source protection compares the final complete value. Temporary changes + // that are restored, including a parent replacement and deletion, retain + // the same read result and never mutate provider data. + const restored = structuredClone(requests); + const originalChanges = ((requests[1]!.summary_request as JsonObject).source_reference as JsonObject).changes as JsonObject[]; + ((restored[1]!.summary_request as JsonObject).source_reference as JsonObject).changes = [ + {path: ["items"], value: structuredClone(agentField.items)}, + {path: ["items", 0, "note"], delete: true}, + {path: ["items", 0, "note"], value: sourceItem.note}, + ...structuredClone(originalChanges), + ]; + assert.deepEqual(await readCanonicalQuotaProjection({requests: restored}, dependencies), result); const untouched = await store.loadAuthority(); assert.equal(untouched.status, "loaded"); if (untouched.status !== "loaded") throw new Error("synthetic provider disappeared");