Repository navigation
refactor(todos): retire Python summary display rules - #7411
Conversation
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent · gpt-6.1-sol · OpenAI · declaration_source=runtime_reported · reasoning_effort=max.
评审对象:#7411,完整 head f60d86ab68b5d7a9458d5314a78671d5f3ed2878;对照基线 c6462f902a1c6a519eb4752b62637580f0e9cd35。
[P2] 保留已注册的 scoped-decision 回执版本。 合法记录经 compactSummaryRecord 后,公开 quota 的下一步展示把 todo_decision_scope_outcome_v0 改成 decision_scope_outcome_v0。独立 File/SQLite CLI 对照均复现,同次 canonical 源材料仍保持原版本。定位:context_projection.ts:214。复用 todo_decision_scope_outcome_v0 的现有注册定义,并让同一真实 File/SQLite quota 用例验证源记录与 agent_lane_next_action 的版本一致。
动机
受影响的是通过 quota、规划与 Todo 索引读取已接受工作方向的 Agent 和维护者。 同一合法决策回执在原始记录和旧显示里使用同一格式;候选显示重建时改写了格式标识,使一次只读重构产生两个不一致的版本。 预期结果是删除重复 Python 展示规则,同时完整保留已注册的公开输出;目前仅原始记录与普通读取保持不变,quota 的下一步展示仍有回归。 本 PR 不修改 Todo 持久化、权限、租约、provider 默认值,也不宣告完整 TS 迁移、已安装交付或长程效率收益。
重复的显示规则会让后续一次声明调整需要维护两个实现。迁到同一个类型化 owner 有实际维护价值,但只读重构必须保留调用者已经收到的字段与版本;字段数量、文本长度以及原始状态没变,均不足以证明完整兼容。当前观察没有出现持久记录被改写,问题集中在生成的显示记录。
改动思路
把摘要来源选择和显示规范化组合进既有 TS owner,可以删除重复 Python 规则;原始值兼容和 IO 保留在 facade 有真实调用方,未发现需要另建 RPC 或迁移框架。 当前边界应保持为只读展示收敛,并修正第 214 行的未注册回执版本;无需扩张到其它 writer、provider 或整个迁移路线。
保留的 Python 层仍有明确职责:公开导入、原始值字符串/repr 兼容、有界传输、响应基数检查和现有 IO;它不再承担显示选择与字段规范化。quota 在既有 TS 规划请求中组合显示,原来的两次规划决策保持独立。这条边界足够完成本切片;需要修的是已注册格式的精确复用。
| 输入/owner | 原版 | 当前 head |
|---|---|---|
| canonical 决策回执 | todo_decision_scope_outcome_v0 |
原版本保留 |
agent_lane_next_action 显示回执 |
原版本保留 | decision_scope_outcome_v0 |
| 存储与 provider revision | 读取不修改 | 读取不修改 |
具体改动
整个 base-to-head 差异为 20 个文件、+857/−525。
七个生产文件收敛独立摘要、来源去重、handoff 组合和 quota 显示;四个文档文件同步 RFC 中英文及对应 ledger;九个测试/夹具文件把纯显示语义移到 TS,并保留真实 Python 传输/provider 集成。生产净减少的代码有明确退役对象,不能代替输出等价证明。
按变更前已接受的 docs/architecture/rfcs/typescript-control-plane-migration-v0.md 验收,固定 spec_revision c6462f902a1c6a519eb4752b62637580f0e9cd35:
- Payoff-phase PR contract:已覆盖。Replace duplicated semantic ownership with a bounded existing transaction and name retained facade callers and retirement. whole seven-file production diff, caller inventory, focused native tests
- Caller-observable semantic parity:未满足。Preserve caller-observable inputs, diagnostics, fields, identity and no-effect results against an immutable baseline. 真实 quota should-run 的 agent_lane_next_action.decision_scope_outcomes[0].schema_version:基线为 todo_decision_scope_outcome_v0,候选为 decision_scope_outcome_v0;同次源材料仍为原版本。
- Correctness:已覆盖。Keep malformed/rejected input fail-closed, complete source coverage and required real-path negative cases. 59 typed/37 Python focused tests; canonical CLI File/SQLite source/revision unchanged and provider-unavailable recovery
- Performance:仍有明确资格边界。Report matched complete caller cost separately from handler count or bridge reduction. No independent latency or installed qualification is claimed in this source review; author reports external25-run evidence, not adopted as our measurement.
关键符号与调用方向:
- function compactSummaryRecord(
loopx/control_plane/todos/context_projection.ts:198):Normalize retained public display fields;Python field rules -> TS display rules。关键条件是 Registered scoped-outcome version must remain exact; violated at214,由 projectTodoSummaryDisplay maps each selected source 调用,结果交给 summary/planning/quota display rows。 - export function projectTodoSummaryDisplay(
loopx/control_plane/todos/context_projection.ts:239):Select/compose display rows;Python lane source loops -> one TS projection。关键条件是 Source order, dedup, explicit false readiness and terminal causality preserved,由 summary_item._project; projectTodoQuotaPlanning 调用,结果交给 todo.context.page and quota planning。 - def compact_todo_summary_items(
loopx/control_plane/todos/summary_item.py:62):Bound compatibility transport;Python normalizer -> raw source batch transport。关键条件是 Equal cardinality; large rows use existing snapshot; empty list stays empty,由 summary compaction/source compatibility exports 调用,结果交给 Existing management, index, planning callers。 - export function decodeTodoReadSource(
loopx/control_plane/todos/read_codec.ts:138):Keep Python scalar spelling;generic weak-map facts rather than semantic Python fields。关键条件是 Facts remain request local; no persisted authority metadata,由 context page decode and handoffReadSource 调用,结果交给 context and quota projections。 - export function projectTodoQuotaPlanning(
loopx/control_plane/todos/quota_selection.ts:415):Compose before existing lane decisions;removes one nonempty Python display crossing。关键条件是 Retain both independent planning decisions and old wire rows,由 quota_selection.py project_quota_planning and quota_summary 调用,结果交给 existing quota planning decoder and public guidance。
正向路径:真实 File/SQLite CLI 的原始 Todo 与 provider revision 在读取、status、quota 和 agent-context 后不变;既有真实故障/恢复、长记录和无 Python 回退测试通过。
反向/恢复路径:真实 quota should-run 的 agent_lane_next_action.decision_scope_outcomes[0].schema_version:基线为 todo_decision_scope_outcome_v0,候选为 decision_scope_outcome_v0;同次源材料仍为原版本。
独立对照还覆盖 437 个原始值/字段组合与摘要、规划、终态来源;完整记录保留 16 处差异,其中包含畸形 repository 和超出安全整数范围的标量。本次阻塞结论只使用可正常由 canonical provider 读出、且真实 quota CLI 已输出的合法决策回执,未把畸形输入差异统一定为公开缺陷。
对主干的风险
最强反例已经通过真实 CLI 观察:同一个公开 quota 返回中,canonical 源材料仍声明已注册版本,下一步显示却声明另一个版本。这使只读投影不再遵守原有数据契约,严格按版本消费的调用者会拿到无法按原 schema 解释的记录。现有新增 TS 断言正好硬编码了错误拼写,因而当前绿灯不能否定此反例。应以现有 producer/contract 的独立定义作为 oracle,修复后重复同一 File/SQLite 路径。
59 项 TS 聚焦测试、37 项 Python 聚焦测试、类型检查、改动文件 Ruff、现有配置的 17 文件 mypy、双语 RFC 和差异检查通过;mypy 配置不包含这些修改过的 Python 模块。扩展九文件 Python 集合为 head 308 通过/11 失败,immutable base 325 通过/同 11 个失败 ID;保留失败,不把相同失败 ID 冒充完整诊断等价。当前新版本 schema 断言在基线通过、候选两种真实 backend 均失败。
标准 premerge 的 6 项直接检查和 19 项选择检查通过,但 aggregate 为 quality_invalid_receipt,因为精确范围 CQR 明确保留本次协议回归和失败验证,回执 cqr_be83d57075698b8dbd03 的结论为 fail。原有基线失败另列,修复范围继续围绕本次合法输出兼容。未查询或等待远程 CI;较少 crossing、源码净减以及作者测量均不作本次延迟收益证明。
我的整体评价
本次未改动渲染页面;检查的是 Todo 摘要、quota JSON 与 handoff 显示规则,因此不以截图认证运行时输出。 未验证真实安装、最低 Node/Windows、完整 PostgreSQL 与匹配的整条 CLI 延迟;未把作者测量或模型理解当作本次证据。
退役重复规则的方向和切片大小合理,保留的兼容层也有具体消费者;本次需要的是精确修复,不需要更大的框架或无关迁移。完整公开输出尚未保留,结论 REQUEST_CHANGES:复用 todo_decision_scope_outcome_v0 的现有注册定义,并让同一真实 File/SQLite quota 用例验证源记录与 agent_lane_next_action 的版本一致。 原始数据无损与投影格式错误是两项分别观察的事实;修复前不能把该 head 记为行为保持交付。
English verdict: REQUEST_CHANGES — head f60d86ab68b5d7a9458d5314a78671d5f3ed2878 changes the registered scoped-decision outcome schema in quota should-run next-action display. The same legal canonical fixture reproduces it on File and SQLite while source records stay unchanged. Preserve todo_decision_scope_outcome_v0 and replay the public CLI regression; passing focused tests do not cover the mistaken new literal.
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent · gpt-6.1-sol · OpenAI · declaration_source=runtime_reported · reasoning_effort=max
当前精确 head c242ca5f439c269c313329c883299a28d95a55dc:REQUEST_CHANGES,剩余是默认迁移的验收证据缺口;上轮 schema 拼写问题已修复。 没有把不稳定测量写成已确认的性能回归。
[P2] 补齐当前切换的 caller 与性能资格。 本 PR 的 checkpoint 仍把完整性能比较列为外部资格,公开数字主要是旧基点的 crossing、输出大小及 median。改动却已无条件切换既有默认读取路径。接受的 §5/6 要求精确基点/头部的实际 caller 重放和 cold/warm/full-CLI p50/p95、idle/burst 内存,不能仅凭减一 crossing 判断通过。请沿现有切片补齐这些证据、解释保留的长尾观察;真实回退才做原 owner 内的修复。保留两次独立规划,不为凑次数减少工作语义,也不要求此 PR 完成整个 T3/T4 或真实模型收益。
动机 / Motivation
通过既有 Todo 摘要、quota 和规划入口读取工作、等待条件与交接信息的 Agent 和维护者。原 Python 先选择摘要来源、规范化声明并组装交接,再向 typed quota owner 规划;现在原始事实直接进入既有 TypeScript display owner,Python 保留兼容运输,quota 在同一次规划内组合显示。合法 scoped-decision 回执在真实 File/SQLite 的 canonical Todo 和下一步显示均保持 todo_decision_scope_outcome_v0,读取前后记录及 provider revision 不变;独立 wheel/sdist 复验也成立。不增加能力、RPC operation、provider、权限或持久格式,不宣称整个 T3/T4、安装态 Host/模型采用、最低 Node/Windows 或长程净收益已完成。
这是有用的有界收敛:以后改摘要声明、来源顺序和交接显示,可以在同一 typed owner 判断。只搬文件、减少行数或单元测试通过均不足以证明这个收益;至少要保持已有调用者的实际输入、错误、输出和完整成本。这里不增加用户确认,也不把原有审批/权限从系统转交给用户。
改动思路 / Approach
复用 todo.context.page、read_codec 和既有 handoff projection,删除 Python 的逐字段显示和来源选择规则;Python 保留真实调用方仍需要的公开签名、通用 str/repr 编码、byte-bound/private-snapshot 运输、响应校验和可变行附件。quota 在既有 typed planning 内组合显示,两次独立规划继续存在。没有必要新建 RPC leaf、provider、服务或迁移框架。
剩余兼容运输有 agents、work_items、quota_summary、todo_index 等真实调用者;等最后一个 Python 消费者改为 in-process typed owner 后再退出。兼容源 key 常量不再决定选择顺序,因此不构成仍在执行的第二套规则。共享 schema 常量的修复是这条边界内合适的整理。
具体改动 / Changes
独立接受依据为 docs/architecture/rfcs/typescript-control-plane-migration-v0.md@be1dc37a008be7017b64b622f653b6707df5c544,在审改动前读取,非用本次改写的 ledger 证明自身。条款映射使用原章节锚点:payoff-phase-pr-contract 部分实现(owner/删除/caller/退出可核,但最终计数与基点应同步);correctness 的当前 schema、源码/包和真实存储边界已验证;caller-observable-semantic-parity-is-a-promotion-gate 部分实现,当前明确不认证全部 public 分支/packet 字节等价;performance 为 not_yet_proven。这是原切换门的余项,不新增全局审批或父 Goal 完成前置。
完整 be1dc37→c242ca5 差异为 23 文件 +913/-527:9 个生产文件 +246/-359,净 -113;4 个文档 +136;10 个测试/fixture +531/-168。不能沿用旧 7 文件的经济账认证最终版本。
关键代码讲解
compactSummaryRecord迁入显示字段规范化;第215行 现在复用 completion producer 的TODO_DECISION_SCOPE_OUTCOME_SCHEMA_VERSION,不再制造另一拼写。合法 source 和agent_lane_next_action均保留原 schema。projectTodoSummaryDisplay先按完整来源选择与去重,再做显示、交接和 terminal 字段;明确的resume_ready=false不被清除后继 overlay 覆盖。它是派生显示,不能授权或完成任务。compact_todo_summary_items成为 batch transport;空输入、参数/响应 cardinality 和原 private snapshot 边界保留。todo_read_source/decodeTodoReadSource只携带 request-local Python spelling,WeakMap 不是持久事实。projectTodoQuotaPlanning在原规划内调用同一显示 owner;独立跟踪实际 SQLite CLI 为 83→82 次 request,todo.context.page为22→21,而两次todo.quota_planning.project均保留。这个夹具/计数与作者旧75→74分开,不把 handler 数或少一次请求称为速度收益。
原 Python semantic assertions 迁到实际 TS owner,新加真实 canonical File/SQLite schema 回归;新增的静态 fixture 在独立语义检查之外提供表征支持,不能被当成规范本身。源码、metadata 和凭据过滤仍复用原 owner,没有 domain-specific 通用协议或新执行权。
对主干的风险 / Risks
本轮 72 个 native tests 通过;相关 Python 为 67 passed / 6 failed。六项分别是原等待/无 Todo replan 恢复案例,全部在最初 todo list 因夹具没有初始化 canonical authority 而停止。不可变 base 与 head 的六个完整错误对象(含字段、write_admitted=false、backup/migrate 补救)逐项严格相等;它们保持失败,未被执行的后续恢复不能算通过。新增两个合法 canonical schema 案例通过,真实独立 CLI 的原 source/record/revision 也保持。
独立 wheel 和 sdist 均构建并安装到全新非 editable 环境,在 File/SQLite 共四组合跑实际控制台,1,767 个已发出的 Python/TypeScript/JSON 产品成员与源码和安装字节一致。将隔离 wheel 的那一个 schema 表达式故意替回错误拼写,同一真实 SQLite CLI 的独立 oracle 检出 display 错而 canonical 仍对;随后恢复原字节。这确认旧问题已经修复,并证明检查能看到它;没有改活动安装。
真实隔离 PostgreSQL 17.11 store369 / service11 全通过、零 skip,两台 owned 容器已停止并读回消失。首次把 service 放在做过 identity-rotation 的 store 测试数据库后发生2项身份拒绝;原失败保留,按套件隔离要求用全新数据库后11过。构建首次陈旧 Chat bundle 拒绝亦保留,正常 build:chat 后 wheel/sdist 通过;未放宽产品检查。typecheck、正确路径的 Ruff、双语差分、差分语义 advisory 与标准 premerge 6 direct +19 selected 及 public boundary 均通过。未查询、轮询或等待 CI。
437 个字段/类型组合是辅助诊断:有6项非法 repository 规范化差异以及超 JS 精度整数/浮点表示差异,不能把整组称为逐字 parity,也没有将这些输入升级成已证明的合法 canonical 缺陷。完整 source/planning/terminal 顺序检查支持当前有界语义;所有 public branch 的同一脚本完整 packet 对照仍未在本次完成。
完整成本测量固定同一物理 source、Python3.12.15、真实默认 SQLite 单任务夹具与 warm daemon,base/head 平衡交错,不删样本:
| 独立批次 | base p50/p95 ms | head p50/p95 ms | 观察 |
|---|---|---|---|
| 32 对 | 336.97 / 521.98 | 345.96 / 836.79 | p95 +60.31%,保留为未解释长尾 |
| 预定64对复验 | 301.56 / 400.98 | 305.88 / 391.08 | p95 -2.47%,没有重现稳定回退 |
两组结果不一致,当前共享 Mac 的其它用户负载不可控制,不能宣称代码已造成 +60% 回归,也不能只挑第二组把原门标绿。独立 Pyinstrument5.1.3 仅采当前 Python observed thread:330.48ms stack weight,socket.recv self18.44ms;不覆盖 Node worker CPU/其它线程,既不等于 p95,也不能解释罕见尾样本。按原 performance-diagnosis 工作流完成计划、真实目标执行、非空 Speedscope 和 native inspect;没有生产 attach、提权或上传。cold-start、warm typed request 分布及 daemon idle/burst RSS 尚未资格,首次尾部归因仍未知。全部 owned matched runtimes 已正常停止。
我的整体评价 / Verdict
REQUEST_CHANGES。旧 schema 负例已被真实源码、物理包与敏感性测试消除;方向和生产体量总体相称,未发现新的已证实合法输入功能阻断。当前仍不能批准默认切换,因为原有完整 caller/cost 验收未闭。最小下一步是补齐并更新本 PR 的现有 qualification receipt;出现实际回退才沿当前 owner 修复,不重开整体迁移、不追加新框架或另造审批。
long_horizon 为 not_yet_proven:单 owner 与信息保持是局部工程增量,完整切换成本/实际后续采用另列;user_experience 为 preserved:原旅程直接读回结果,无新增配置/确认。已检查既有 CLI/summary/index/规划和相关呈现调用,23文件没有渲染页面或布局变动,visual_review not_applicable,视觉未验证范围 none。最低 Node、原生 Windows、App/Lark/Host、真实模型和长程全费收益仍未资格;它们不被冒称通过,也不成为无关父工作前置。没有合并、dismiss、resolve、共享安装或新增模型费用。
English verdict: REQUEST_CHANGES — c242ca5. The previous registered-schema defect is fixed and independently verified through source, physical wheel/sdist and a sensitive semantic mutation. Local checks and real PostgreSQL pass; six pre-existing canonical-fixture failures retain identical complete diagnostics. The existing unconditional cutover still lacks complete current-baseline caller/cost qualification. Two matched warm-CLI cohorts disagree on tail behavior, so neither a proven regression nor a fully qualified performance pass is claimed.
c242ca5 to
e7a54b8
Compare
|
This pull request has merge conflicts with Choose the remote for the base repository, not an out-of-date fork. 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 HEADFor a same-repository clone whose Keep the DCO |
Source-neutral bounded reproduction scripts (review evidence; no production helper added)Use one prepared checkout interpreter with test dependencies. Export the two exact revisions into adjacent, separate directories, precompile both with that interpreter, and keep all output in a private disposable directory. The scripts initialize synthetic canonical SQLite state only. Raw profiles, stderr, paths and samples remain private. Percentiles and summary aggregates are the public evidence. # BASE and HEAD are empty sibling directories; PYTHON is the same prepared interpreter.
git archive ff8d9932294e9004b9ffeb2fb473d00354397eb8 | tar -x -C "$BASE"
git archive e7a54b8f32a648124133b02e11404b75a421fdac | tar -x -C "$HEAD"
"$PYTHON" -m compileall -q "$BASE/loopx" "$HEAD/loopx"
"$PYTHON" qualify_summary.py "$BASE" "$HEAD" "$PRIVATE_OUTPUT/main" "$PYTHON"
"$PYTHON" qualify_summary_kernel.py "$BASE" "$HEAD" "$PRIVATE_OUTPUT/kernel" "$PYTHON"Save the following parameterized versions of the executed offline code beside one another. They preserve the workload, counts and operations; host-specific source/output paths have been replaced with arguments. Do not run against an active Goal. qualify_summary_worker.py import sys, os, json, time, subprocess, hashlib, io, contextlib
from pathlib import Path
from collections import Counter
source, owned = map(Path, sys.argv[1:3])
sys.path[:0] = [str(source), str(source / 'tests/control_plane')]
import test_quota_settlement_cli as fixture
from canonical_authority_fixture import initialize_canonical_source_fixture
from loopx.control_plane import effect_runtime as runtime
from loopx.control_plane.todos.quota_selection import project_quota_planning
from loopx.control_plane.testing.quota_fixtures import quota_todo_item, quota_todo_summary
import loopx
assert Path(loopx.__file__).resolve().is_relative_to(source.resolve())
owned.mkdir(parents=True, exist_ok=True)
if not (owned/'project/.loopx/registry.json').exists():
project, storage, registry = fixture._write_fixture(owned)
state = fixture._configure_read_only_todo(project)
initialize_canonical_source_fixture(storage, fixture.GOAL_ID, state_path=state, provider='sqlite')
else:
project, storage, registry = owned/'project', owned/'runtime', owned/'project/.loopx/registry.json'
row = quota_todo_item(todo_id=fixture.TODO_ID, index=1, text='Validate the accepted artifact.',
priority='P1', claimed_by=fixture.AGENT_ID)
summary = quota_todo_summary([row], role='agent', item_limit=None)
request = {'records':[{'todo_id':fixture.TODO_ID,'role':'agent','status':'open','priority':'P1','text':'Validate the accepted artifact.'}],
'owner_scope':True,'offset':0,'limit':48}
cli = [sys.executable,'-m','loopx.cli','--format','json','--registry',str(registry),
'--runtime-root',str(storage),'quota','should-run','--goal-id',fixture.GOAL_ID,
'--agent-id',fixture.AGENT_ID,'--codex-app','--available-capability','shell',
'--available-capability','filesystem_read']
def typed():
value=runtime.effect_runtime_result('todo.context.page', request)
assert value['todos'][0]['todo_id']==fixture.TODO_ID
return value
def transaction():
value=project_quota_planning(summary,all_open_items=[row],source_open_count=1,
agent_identity={'agent_id':fixture.AGENT_ID},filter_user_gate_blocks_agent=False,
available_capabilities=['shell','filesystem_read'],current_time='2026-10-27T00:00:00Z')
assert isinstance(value,dict)
return value
def rss():
fingerprint=runtime._runtime_fingerprint()
info=runtime._runtime_info_for_request(runtime._runtime_info_path(fingerprint),fingerprint=fingerprint)
raw=subprocess.check_output(['ps','-o','rss=','-p',str(info['pid'])],text=True)
return int(raw.strip())/1024
def cli_once(cwd_kind="project"):
start=time.perf_counter_ns()
p=subprocess.run(cli,cwd=project if cwd_kind == "project" else source,capture_output=True,text=True,env=os.environ.copy(),timeout=45)
ms=(time.perf_counter_ns()-start)/1e6
assert p.returncode==0,(p.returncode,p.stderr,p.stdout)
value=json.loads(p.stdout)
selected=value.get('selected_todo') or value.get('agent_lane_next_action') or {}
assert selected.get('todo_id')==fixture.TODO_ID,value
return {'ms':ms,'stdout_bytes':len(p.stdout.encode()),'decision':value['decision'],
'selected_todo_id':selected['todo_id'],'schema':selected.get('schema_version'),
'load':os.getloadavg()}
os.chdir(project)
print(json.dumps({'ready':True,'source':str(source),'fixture_sha256':hashlib.sha256((project/f'.codex/goals/{fixture.GOAL_ID}/ACTIVE_GOAL_STATE.md').read_bytes()).hexdigest(),
'python':sys.version.split()[0],'node':subprocess.check_output(['node','--version'],text=True).strip()}),flush=True)
for line in sys.stdin:
try:
command=json.loads(line)
op=command['op']; n=command.get('n',1)
if op=='cli': result=cli_once(command.get('cwd','project'))
elif op=='cold':
values=[]
for i in range(n):
runtime.restart_effect_runtime(wait_for_exit=True)
start=time.perf_counter_ns();typed();values.append((time.perf_counter_ns()-start)/1e6)
result={'ms':values}
elif op in ('typed','transaction'):
function=typed if op=='typed' else transaction
with runtime.effect_runtime_request_scope():
for _ in range(10):function()
values=[]
for _ in range(n):
start=time.perf_counter_ns();function();values.append((time.perf_counter_ns()-start)/1e6)
result={'ms':values}
elif op=='memory':
typed();time.sleep(.5);idle=rss();peaks=[idle]
with runtime.effect_runtime_request_scope():
for i in range(n):
transaction()
if i%100==99:peaks.append(rss())
after=rss();time.sleep(.5)
result={'idle_mib':idle,'burst_sampled_peak_mib':max(peaks),'after_burst_mib':after,'settled_mib':rss(),'requests':n}
elif op=='trace':
from loopx.cli import main
counts=Counter(); original=runtime._request_with_info
def counted(*args,**kwargs):
counts[kwargs['method']]+=1
return original(*args,**kwargs)
runtime._request_with_info=counted
output=io.StringIO()
try:
with contextlib.redirect_stdout(output):code=main(cli[3:])
finally:runtime._request_with_info=original
value=json.loads(output.getvalue());assert code==0,value
result={'requests':sum(counts.values()),'methods':dict(counts),'stdout_bytes':len(output.getvalue().encode())}
elif op=='stop':
result=runtime.restart_effect_runtime(wait_for_exit=True)
else:raise ValueError(op)
print(json.dumps({'ok':True,'result':result}),flush=True)
except Exception:
import traceback
print(json.dumps({'ok':False,'error':traceback.format_exc()}),flush=True)qualify_summary.py import sys,os,subprocess,json,time,hashlib,math
from pathlib import Path
base,head=sys.argv[1:3]
python=sys.argv[4]
out=Path(sys.argv[3]);out.mkdir(parents=True,exist_ok=True)
plan={'base':'ff8d9932294e9004b9ffeb2fb473d00354397eb8','head':'e7a54b8f32a648124133b02e11404b75a421fdac',
'source_topology':'adjacent immutable Git archives; both precompiled with the same Python; CLI cwd is its synthetic project',
'warm_order':'16 alternating batches of 16 samples, 10 warmups per batch',
'cold_pairs':24,'cli_pairs':64,'typed_requests':256,'transaction_requests':256,'memory_burst':2000,
'order':'alternating AB/BA, no samples removed','cold':'new managed process, warm filesystem/compile cache',
'full_cli':'quota should-run, one claimed canonical SQLite Todo, read-only declared capabilities',
'p95':'nearest-rank ceil(.95*n)','limits':{'full_cli_percent':5,'unexplained_additive_ms':25,'warm_nondurable_p95_ms':2}}
(out/'plan.json').write_text(json.dumps(plan,indent=2))
workers={}; metadata={}; results={'plan':plan,'cold':{},'cli':{'base':[],'head':[]},'typed':{},'transaction':{},'memory':{}}
for name,source in [('base',base),('head',head)]:
owned=out/name;owned.mkdir(exist_ok=True)
temp=out/(name+'-tmp');temp.mkdir(exist_ok=True)
env={**os.environ,'PYTHONPATH':source,'TMPDIR':str(temp),'TEMP':str(temp),'TMP':str(temp),
'CODEX_HOME':str(owned/'host'),'DO_NOT_TRACK':'1','LOOPX_USAGE_PING_ENABLED':'0','PYTHONDONTWRITEBYTECODE':'1'}
env.pop('CODEX_THREAD_ID',None)
p=subprocess.Popen([python,str(Path(__file__).with_name('qualify_summary_worker.py')),source,str(owned)],cwd=source,env=env,
stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=open(out/(name+'-stderr.log'),'w'),text=True,bufsize=1)
workers[name]=p;metadata[name]=json.loads(p.stdout.readline());assert metadata[name]['ready']
assert metadata['base']['fixture_sha256']==metadata['head']['fixture_sha256']
results['metadata']=metadata
def ask(name,op,n=1):
p=workers[name];p.stdin.write(json.dumps({'op':op,'n':n})+'\n');p.stdin.flush()
value=json.loads(p.stdout.readline());assert value['ok'],value
return value['result']
def save(): (out/'results.json').write_text(json.dumps(results,indent=2))
try:
for name in workers:ask(name,'typed',10);ask(name,'cli')
print('ready; fixtures match; starting fixed 24 cold pairs',flush=True)
for name in workers:results['cold'][name]=[]
for i in range(24):
for name in (['base','head'] if i%2==0 else ['head','base']):
results['cold'][name].extend(ask(name,'cold')['ms'])
save();print('cold done; starting 64 CLI pairs',flush=True)
for i in range(64):
for name in (['base','head'] if i%2==0 else ['head','base']):results['cli'][name].append(ask(name,'cli'))
if i%16==15:save();print('CLI pairs',i+1,flush=True)
for op in ('typed','transaction'):
for name in workers:results[op][name]=[]
for i in range(16):
for name in (['base','head'] if i%2==0 else ['head','base']):
results[op][name].extend(ask(name,op,16)['ms'])
for name in workers:results['memory'][name]=ask(name,'memory',2000)
results['trace']={name:ask(name,'trace') for name in workers}
save()
finally:
for name,p in workers.items():
try:ask(name,'stop')
except Exception:pass
p.stdin.close();p.wait(timeout=10)
def stats(rows):
rows=sorted(rows);return {'n':len(rows),'p50':rows[math.ceil(.5*len(rows))-1],'p95':rows[math.ceil(.95*len(rows))-1],'max':rows[-1]}
report={op:{name:stats([r['ms'] for r in rows] if op=='cli' else rows) for name,rows in results[op].items()} for op in ('cold','cli','typed','transaction')}
report['memory']=results['memory'];(out/'summary.json').write_text(json.dumps(report,indent=2));print(json.dumps(report,indent=2))qualify_summary_kernel_worker.py import sys, os, json, time, subprocess, hashlib, io, contextlib
from pathlib import Path
from collections import Counter
source, owned = map(Path, sys.argv[1:3])
sys.path[:0] = [str(source), str(source / 'tests/control_plane')]
import test_quota_settlement_cli as fixture
from canonical_authority_fixture import initialize_canonical_source_fixture
from loopx.control_plane import effect_runtime as runtime
from loopx.control_plane.todos.quota_selection import project_quota_planning
from loopx.control_plane.testing.quota_fixtures import quota_todo_item, quota_todo_summary
import loopx
assert Path(loopx.__file__).resolve().is_relative_to(source.resolve())
owned.mkdir(parents=True, exist_ok=True)
if not (owned/'project/.loopx/registry.json').exists():
project, storage, registry = fixture._write_fixture(owned)
state = fixture._configure_read_only_todo(project)
initialize_canonical_source_fixture(storage, fixture.GOAL_ID, state_path=state, provider='sqlite')
else:
project, storage, registry = owned/'project', owned/'runtime', owned/'project/.loopx/registry.json'
row = quota_todo_item(todo_id=fixture.TODO_ID, index=1, text='Validate the accepted artifact.',
priority='P1', claimed_by=fixture.AGENT_ID)
summary = quota_todo_summary([row], role='agent', item_limit=None)
request = {'records':[{'todo_id':fixture.TODO_ID,'role':'agent','status':'open','priority':'P1','text':'Validate the accepted artifact.'}],
'owner_scope':True,'offset':0,'limit':48}
cli = [sys.executable,'-m','loopx.cli','--format','json','--registry',str(registry),
'--runtime-root',str(storage),'quota','should-run','--goal-id',fixture.GOAL_ID,
'--agent-id',fixture.AGENT_ID,'--codex-app','--available-capability','shell',
'--available-capability','filesystem_read']
def typed():
value=runtime.effect_runtime_result('todo.context.page', request)
assert value['todos'][0]['todo_id']==fixture.TODO_ID
return value
def transaction():
value=project_quota_planning(summary,all_open_items=[row],source_open_count=1,
agent_identity={'agent_id':fixture.AGENT_ID},filter_user_gate_blocks_agent=False,
available_capabilities=['shell','filesystem_read'],current_time='2026-10-27T00:00:00Z')
assert isinstance(value,dict)
return value
def rss():
fingerprint=runtime._runtime_fingerprint()
info=runtime._runtime_info_for_request(runtime._runtime_info_path(fingerprint),fingerprint=fingerprint)
raw=subprocess.check_output(['ps','-o','rss=','-p',str(info['pid'])],text=True)
return int(raw.strip())/1024
def cli_once(cwd_kind="project"):
start=time.perf_counter_ns()
p=subprocess.run(cli,cwd=project if cwd_kind == "project" else source,capture_output=True,text=True,env=os.environ.copy(),timeout=45)
ms=(time.perf_counter_ns()-start)/1e6
assert p.returncode==0,(p.returncode,p.stderr,p.stdout)
value=json.loads(p.stdout)
selected=value.get('selected_todo') or value.get('agent_lane_next_action') or {}
assert selected.get('todo_id')==fixture.TODO_ID,value
return {'ms':ms,'stdout_bytes':len(p.stdout.encode()),'decision':value['decision'],
'selected_todo_id':selected['todo_id'],'schema':selected.get('schema_version'),
'load':os.getloadavg()}
os.chdir(project)
from loopx.control_plane.todos import quota_selection as quota_module
captured={}
_original=quota_module.effect_runtime_result
def capture(method,params,**kwargs):
if method=='todo.quota_planning.project':captured.update(method=method,params=params,kwargs=kwargs)
return _original(method,params,**kwargs)
quota_module.effect_runtime_result=capture
try:transaction()
finally:quota_module.effect_runtime_result=_original
assert captured
def internal():
result=runtime.effect_runtime_result(captured['method'],captured['params'],**captured['kwargs'])
assert result['schema_version']=='todo_quota_planning_wire_v1'
return result
print(json.dumps({'ready':True,'source':str(source),'fixture_sha256':hashlib.sha256((project/f'.codex/goals/{fixture.GOAL_ID}/ACTIVE_GOAL_STATE.md').read_bytes()).hexdigest(),
'python':sys.version.split()[0],'node':subprocess.check_output(['node','--version'],text=True).strip()}),flush=True)
for line in sys.stdin:
try:
command=json.loads(line)
op=command['op']; n=command.get('n',1)
if op=='cli': result=cli_once(command.get('cwd','project'))
elif op=='cold':
values=[]
for i in range(n):
runtime.restart_effect_runtime(wait_for_exit=True)
start=time.perf_counter_ns();typed();values.append((time.perf_counter_ns()-start)/1e6)
result={'ms':values}
elif op in ('typed','transaction','internal'):
function=typed if op=='typed' else internal if op=='internal' else transaction
with runtime.effect_runtime_request_scope():
for _ in range(10):function()
values=[]
for _ in range(n):
start=time.perf_counter_ns();function();values.append((time.perf_counter_ns()-start)/1e6)
result={'ms':values}
elif op=='memory':
typed();time.sleep(.5);idle=rss();peaks=[idle]
with runtime.effect_runtime_request_scope():
for i in range(n):
transaction()
if i%100==99:peaks.append(rss())
after=rss();time.sleep(.5)
result={'idle_mib':idle,'burst_sampled_peak_mib':max(peaks),'after_burst_mib':after,'settled_mib':rss(),'requests':n}
elif op=='trace':
from loopx.cli import main
counts=Counter(); original=runtime._request_with_info
def counted(*args,**kwargs):
counts[kwargs['method']]+=1
return original(*args,**kwargs)
runtime._request_with_info=counted
output=io.StringIO()
try:
with contextlib.redirect_stdout(output):code=main(cli[3:])
finally:runtime._request_with_info=original
value=json.loads(output.getvalue());assert code==0,value
result={'requests':sum(counts.values()),'methods':dict(counts),'stdout_bytes':len(output.getvalue().encode())}
elif op=='stop':
result=runtime.restart_effect_runtime(wait_for_exit=True)
else:raise ValueError(op)
print(json.dumps({'ok':True,'result':result}),flush=True)
except Exception:
import traceback
print(json.dumps({'ok':False,'error':traceback.format_exc()}),flush=True)qualify_summary_kernel.py import sys
from pathlib import Path
import json,subprocess,os,math
roots={'base':sys.argv[1],'head':sys.argv[2]}
python=sys.argv[4]
out=Path(sys.argv[3]);out.mkdir(parents=True,exist_ok=True)
processes={};results={name:[] for name in roots}
for name,source in roots.items():
temp=out/(name+'-tmp');temp.mkdir(exist_ok=True)
env={**os.environ,'PYTHONPATH':source,'TMPDIR':str(temp),'DO_NOT_TRACK':'1','CODEX_HOME':str(out/(name+'-host'))}
env.pop('CODEX_THREAD_ID',None)
p=subprocess.Popen([python,str(Path(__file__).with_name('qualify_summary_kernel_worker.py')),source,str(out/name)],cwd=source,env=env,
stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=open(out/(name+'-stderr.log'),'w'),text=True,bufsize=1)
assert json.loads(p.stdout.readline())['ready'];processes[name]=p
def ask(name,op):
p=processes[name];p.stdin.write(json.dumps({'op':op,'n':16})+'\n');p.stdin.flush()
result=json.loads(p.stdout.readline());assert result['ok'],result
return result['result']
try:
for i in range(16):
for name in (['base','head'] if i%2==0 else ['head','base']):results[name].extend(ask(name,'internal')['ms'])
finally:
for name,p in processes.items():ask(name,'stop');p.stdin.close();p.wait(timeout=10)
(out/'samples.json').write_text(json.dumps(results))
def stats(rows):
rows=sorted(rows);return {'n':len(rows),'p50':rows[math.ceil(.5*len(rows))-1],'p95':rows[math.ceil(.95*len(rows))-1],'max':rows[-1]}
summary={name:stats(rows) for name,rows in results.items()};(out/'summary.json').write_text(json.dumps(summary,indent=2));print(json.dumps(summary)) |
Compose standalone summary and planning displays with the existing TypeScript context and handoff owners. Keep Python raw-value codecs, bounded transport and public compatibility adapters; build quota displays in process before both independent planning decisions. Pin pre-cutover synthetic CLI rows, move display rule cases to TypeScript, and record bilingual retirement evidence and remaining facade exits. Complete pinned-clock CLI outputs stay byte-identical. Measured quota crossings fall from 75 to 74; the estimated 73 target remains unqualified because empty User planning had no display request to retire. The synthetic credential-label test vector was restructured for the public-boundary scanner. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> Signed-off-by: hhyykk <4408344+hhyykk@users.noreply.github.com>
…mmary display Preserve agent_lane_next_action.decision_scope_outcomes[*].schema_version as todo_decision_scope_outcome_v0 instead of the unregistered decision_scope_outcome_v0 emitted by compactSummaryRecord. Extract the completion writer's registered version into TODO_DECISION_SCOPE_OUTCOME_SCHEMA_VERSION in user_completion_types.ts and reuse it in completion and summary display. No other receipt field changes. Add a TS compaction regression proving verbatim preservation and correct the existing normalization oracle's expected version. Add a File/SQLite quota should-run regression comparing the selected lane receipt against canonical readback. Append equivalent correction lines to both migration ledger translations. Typecheck, 73 focused TS tests and 12 completion tests pass. Focused Python: 39 passed; the 6 remaining failures in test_receipt_next_action_cli.py fail identically on origin/main be1dc37 (tracked by #7433) and are untouched here. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> Signed-off-by: hhyykk <4408344+hhyykk@users.noreply.github.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
e7a54b8 to
11bd498
Compare
Final qualification after the main rebaseExact head
Full-CLI p95 delta is −0.336125 ms (−0.015%). The actual RSS base → head (MiB), 2,000 bounded projections: idle 110.00 → 94.73, sampled burst peak 116.11 → 137.89, after burst and bounded settle 116.11 → 137.89. This supplies the required bounded observations; it does not prove long-run allocation/leak behavior. Synthetic source-state SHA-256 Current validation: 45 focused Python tests, 60 TS tests, control-plane typecheck, Ruff, bilingual checks and standard premerge (4 direct checks, compile, 19 selected checks) pass. Fresh wheel and sdist each pass installed File/SQLite canonical → selected-action version readback. All 855 shipped control-plane members match current source bytes in both archives; the intentional test-only helper exclusion remains. A summary-only installed mutation fails the actual CLI oracle and restoration passes both providers again. Wheel SHA-256 Current migration cost: 9 production files +246/−359, net −113; Python net −273. Validation: 10 files +531/−167; docs: 6 files +270. Real CLI requests 93 → 92, context pages 22 → 21, quota-planning requests 2 → 2. Counts from earlier bases are not reused as current measurements. 已解决新主线冲突并复测。此前未到达场景的 fixture 修复采用主线版本;最终 head 的功能、安装和匹配性能证据已补齐,请复审。 Replay runner for the current base/headReuse git archive 17b2a0f9b818dc6e6fe77ccc567b20ff91b3bc40 | tar -x -C "$BASE"
git archive 11bd4989f2cd1b9989962250f349b4f5c0d7bc26 | tar -x -C "$HEAD"
"$PYTHON" -m compileall -q "$BASE/loopx" "$HEAD/loopx"
"$PYTHON" qualify_summary.py "$BASE" "$HEAD" "$PRIVATE_OUTPUT" "$PYTHON"import sys,os,subprocess,json,time,hashlib,math
from pathlib import Path
base,head=sys.argv[1:3]
python=sys.argv[4]
out=Path(sys.argv[3]);out.mkdir(parents=True,exist_ok=True)
plan={'base':'17b2a0f9b818dc6e6fe77ccc567b20ff91b3bc40','head':'11bd4989f2cd1b9989962250f349b4f5c0d7bc26',
'source_topology':'adjacent immutable Git archives; both precompiled with the same Python; CLI cwd is its synthetic project',
'warm_order':'16 alternating batches of 16 samples, 10 warmups per batch',
'cold_pairs':24,'cli_pairs':64,'typed_requests':256,'transaction_requests':256,'memory_burst':2000,
'order':'alternating AB/BA, no samples removed','cold':'new managed process, warm filesystem/compile cache',
'full_cli':'quota should-run, one claimed canonical SQLite Todo, read-only declared capabilities',
'p95':'nearest-rank ceil(.95*n)','limits':{'full_cli_percent':5,'unexplained_additive_ms':25,'warm_nondurable_p95_ms':2}}
(out/'plan.json').write_text(json.dumps(plan,indent=2))
workers={}; metadata={}; results={'plan':plan,'cold':{},'cli':{'base':[],'head':[]},'typed':{},'transaction':{},'internal':{},'memory':{}}
for name,source in [('base',base),('head',head)]:
owned=out/name;owned.mkdir(exist_ok=True)
temp=out/(name+'-tmp');temp.mkdir(exist_ok=True)
env={**os.environ,'PYTHONPATH':source,'TMPDIR':str(temp),'TEMP':str(temp),'TMP':str(temp),
'CODEX_HOME':str(owned/'host'),'DO_NOT_TRACK':'1','LOOPX_USAGE_PING_ENABLED':'0','PYTHONDONTWRITEBYTECODE':'1'}
env.pop('CODEX_THREAD_ID',None)
p=subprocess.Popen([python,str(Path(__file__).with_name('qualify_summary_worker.py')),source,str(owned)],cwd=source,env=env,
stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=open(out/(name+'-stderr.log'),'w'),text=True,bufsize=1)
workers[name]=p;metadata[name]=json.loads(p.stdout.readline());assert metadata[name]['ready']
assert metadata['base']['fixture_sha256']==metadata['head']['fixture_sha256']
results['metadata']=metadata
def ask(name,op,n=1):
p=workers[name];p.stdin.write(json.dumps({'op':op,'n':n})+'\n');p.stdin.flush()
value=json.loads(p.stdout.readline());assert value['ok'],value
return value['result']
def save(): (out/'results.json').write_text(json.dumps(results,indent=2))
try:
for name in workers:ask(name,'typed',10);ask(name,'cli')
print('ready; fixtures match; starting fixed 24 cold pairs',flush=True)
for name in workers:results['cold'][name]=[]
for i in range(24):
for name in (['base','head'] if i%2==0 else ['head','base']):
results['cold'][name].extend(ask(name,'cold')['ms'])
save();print('cold done; starting 64 CLI pairs',flush=True)
for i in range(64):
for name in (['base','head'] if i%2==0 else ['head','base']):results['cli'][name].append(ask(name,'cli'))
if i%16==15:save();print('CLI pairs',i+1,flush=True)
for op in ('typed','internal','transaction'):
for name in workers:results[op][name]=[]
for i in range(16):
for name in (['base','head'] if i%2==0 else ['head','base']):
results[op][name].extend(ask(name,op,16)['ms'])
for name in workers:results['memory'][name]=ask(name,'memory',2000)
results['trace']={name:ask(name,'trace') for name in workers}
save()
finally:
for name,p in workers.items():
try:ask(name,'stop')
except Exception:pass
p.stdin.close();p.wait(timeout=10)
def stats(rows):
rows=sorted(rows);return {'n':len(rows),'p50':rows[math.ceil(.5*len(rows))-1],'p95':rows[math.ceil(.95*len(rows))-1],'max':rows[-1]}
report={op:{name:stats([r['ms'] for r in rows] if op=='cli' else rows) for name,rows in results[op].items()} for op in ('cold','cli','typed','internal','transaction')}
report['memory']=results['memory'];(out/'summary.json').write_text(json.dumps(report,indent=2));print(json.dumps(report,indent=2)) |
|
This pull request has merge conflicts with Choose the remote for the base repository, not an out-of-date fork. 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 HEADFor a same-repository clone whose Keep the DCO |
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · reasoning_effort=max
APPROVE:当前精确 head a8c1690484c6d647dad8893bceb3a1cac232bb29 未发现阻断 finding。 本次完整差异基线 f7a1ad73fec0c9058fe9feecfdff66438be37476;这是新的独立资格,不继承此前对 c242 的结论。
动机 / Motivation
维护 Todo 摘要、规划和交接读回的开发者,以及从 CLI 继续原任务的 Agent。
原来修改一项摘要规则,需要同时核对 Python 规范化、来源选择和 TypeScript 展示;本版本把这些规则收敛到已有 typed owner,同一任务仍能读取完整声明、继续工作并恢复原轮次。
当前真实 File/SQLite 的完整读回与基线同义,原回执版本、恢复和一次结算保持;一个具名 SQLite CLI 路径少一次跨运行时展示调用。
本 PR 交付有界的只读规则退役,不改变存储 authority、执行权限、调度策略或用户配置,也不以此认证完整 TS 迁移或长程净收益。
其余 Python 调用方及 facade 的退役、大 Goal 持续资源行为和安装宿主/模型实际采用仍在原迁移工作中开放。
这是已接受迁移计划中的维护成本问题。只移动文件会保留两份知识;本次实际删除 Python 字段规则和来源选择,再由原入口消费同一个 TS 实现。CLI 仍读取原任务并给出原命令,没有增加用户录入、导航或确认轮次。
改动思路 / Approach
来源选择、展示规范化与 handoff 组合应归现有 TypeScript context/read owner;Python 保留泛型值编码和 IO,canonical provider、准入、结算及两次独立规划继续由原 owner 负责。
当前 PR 的可用边界是现有 CLI/上下文读回的一个完整规则退役切片;不新增 RPC、状态库或产品配置界面,保留同一请求内直接组合和明确的 facade 退出条件。
独立摘要继续走既有 todo.context.page;quota planning 在 TS 进程内组合摘要,删除之前那次展示预处理往返。保留两次完整规划,它们消费不同事实,不能为了凑调用数再删一个。Python 的 tuple/set/float 字符串与 repr 是兼容输入事实,不是第二个任务决策;request-local WeakMap 不进入持久记录。
我比较了不改、保留 Python 判断加 wrapper、复用现有 owner 三种方案。前两者继续留下同一规则的两个修改点;现方案净减生产代码,且真实调用少一次。handoffReadSource 的旧 encoded 输入分支仍可做小型后续整理:当前仓库生产运输调用已使用 record carrier,持久回执并不要求保留旧请求形态。它是无副作用格式入口,没有第二份决策或状态,不构成本次阻断;不需要为这点新建迁移框架或人工审批。
具体改动 / Changes
独立接受依据为 docs/architecture/rfcs/typescript-control-plane-migration-v0.md,spec_revision f7a1ad73fec0c9058fe9feecfdff66438be37476。先读原有 5. Payoff-phase PR contract、Correctness、Caller-observable semantic parity is a promotion gate 和 Performance,再审实现。此 head 的映射:唯一 owner/实删规则、实际调用与退出条件 implemented;真实调用同义、恢复、打包和缺陷敏感性 implemented;全部成本轴已测且默认 SQLite 当前门通过。其他迁移和平台不提升为本 PR 新前置。
完整25文件 +1047/-526:9个生产文件 +246/-359(净减113),10个测试/fixture +531/-167,6个双语文档 +270。ledger 保留最早7文件切片和各旧版本数据,不能把旧计数当成本次最终差异。9个产品改动 blob 与作者资格版本11bd相同;重基新增的两个 main 调用方已重新检查,并在当前组合重跑真实 CLI、恢复、成本及标准检查。
关键代码讲解
- projectTodoSummaryDisplay / compactSummaryRecord:从明确的来源序列选行、去重并规范化,保留显式 false readiness 和终态 frontier 字段;复用 completion writer 的注册常量,避免把
todo_decision_scope_outcome_v0换成未注册版本。 - todo_read_source / decodeTodoReadSource:Python 运送原值及 Python 专属 string/repr 事实;TS read codec 复用已有 scope、repository、agent 和 handoff 规范化。错误不回退到旧 Python 策略,原可变行 attachment identity 仍保留。
- compact_todo_summary_items / _project:变成有界运输和结果形状校验,空批次不发请求;大来源沿既有私有 snapshot 运输,没有提前截断凭据筛选所需原文。
- projectTodoQuotaPlanning:复制选择输入,在原规划 owner 内组合 display_source,再执行原 lane 选择;不是增加一次 domain RPC,也不把摘要当作新的准入 authority。
todo_index.py的两阶段交接仍消费同一公共 codec。
此前回执版本问题已通过当前源码、独立 wheel/sdist 和故意改坏安装文件的实际反例闭合。移去的 Python 单元规则被 TS 独立语义用例承接;微秒排序已有原 TS 用例保留,Python 保留实际运输、批次、失败和恢复测试。292行合成 fixture 只作已声明公共默认值/来源顺序的回归旁证,不当作独立规格或真实使用效果。
对主干的风险 / Risks
最强风险是迁移后回执字段、完整诊断或错误恢复悄悄改变,同时更少调用掩盖完整入口变慢。本轮对不可变基线和当前 head,以相同 fixture 执行 File/SQLite 的 todo list、status、quota should-run、agent-context 及再次 canonical 读回。每个完整结果在明确归一后相等,完整 Task 和 provider cursor 在单个观察内不变。只归一已解析的临时根路径、观测时钟、初始化 provider 身份及其派生 lineage;scheduler 的 base64/zlib carrier 先完整解码再逐字段比较,没有忽略整段 opaque 命令、诊断或权限。
另有80个其他 Agent 任务置于 canonical 源前部并逆序、伪造高优先级旧 Markdown 展示、已完成归档的决定来源三组 × File/SQLite × base/head,共12个真实场景通过:完整规范化读回一致,仍选中原 canonical 任务,声明/认领/记录未被展示预算或旧页接管。初始补充 driver 的 __file__ 以及不合法 index/archive token 在进入目标断言前失败,原日志保留;仅修夹具以符合已有 contract,未改产品或削弱比较。
PASS:45项 Python(含8项真实恢复)、72项 TS、typecheck、变更 Python Ruff、配置内17源文件 mypy;独立 PostgreSQL17.11 的369 store+11 service,零skip,专用数据库及服务器已清理。首次 service 只提供一种 URL 而跳过另一分支,原skip保留,后来用两个独立数据库补齐。标准 premerge 6直接+19选中均通过;双语与公开边界检查通过。CQR cqr_dc3cd1ff99353c57977b 的完整25文件精确作用域已在首评前落盘并逐字段读取,状态 pass。
真实 wheel/sdist 各两个 provider 的五命令读回通过,855个已分发 control-plane 源成员及全部9个变更产品文件与 head 一致。唯一未分发文件是原有 private-process test driver,符合 package-data 范围,没有把它算作产品遗漏。故意把 wheel 的回执版本改坏后,真实 CLI 的独立 schema oracle 失败;canonical 源仍正确,恢复原文件后通过。首次 build 拒绝旧前端 bundle,按现有流程重建后再打包;错误构建目录和已存在测试环境的准备失败也保留。
同一 Python3.14.8、Node24.21.0、相邻不可变 archive、同一合成 SQLite 输入,计时不与本 Agent 重型验证并行。预定24对 cold、64对 CLI、每版256次 typed/kernel/facade 请求和2000次 burst,不删样本:
| 轴(ms,p50 / p95) | base | head |
|---|---|---|
| 新受管进程,warm filesystem | 191.50 / 255.63 | 184.33 / 244.99 |
| 完整 CLI,64对 | 820.11 / 2245.70 | 854.30 / 1518.25 |
| warm typed quota kernel | 0.476 / 0.649 | 0.516 / 0.681 |
| 完整 Python quota facade | 1.152 / 1.701 | 1.039 / 1.767 |
独立普通 typed request p95为0.401→0.451ms;完整 trace 为93→92次,其中 context22→21,规划2→2。当前完整CLI p95未达原5%或25ms回退门,warm kernel低于2ms;没有用微基准替代 CLI。较高的候选 p50与全部长尾原样保留,不宣称普遍提速。
首次 RSS idle/peak 为97.77/113.13→140.70/143.66MiB。为判断是否新增持续差量,又预定三轮各2000投影、新进程按AB/BA交错:两版都增长,最终 sampled peak221.92→211.81MiB,未出现候选持续高于基线;这不证明长期无泄漏或内存已回落。旧32对+60.31%、旧64对和作者后续各 cohort 全保留,各自版本/环境分开;当前完整同条件结果不倒改旧失败,也不以历史未归因自动否决当前边界。
语义与 CI 对齐
复用已有 schema/owner,新增共享常量保持原注册值,没有新持久 vocabulary、feature gate 或权限。原机器工作/等待/结算义务仍是强制语义,摘要文字不是授权;共享 handoff credential 排除先于截断。现有公共读回 envelope 继续由原 seal owner 提供,内部条目数组没有另造公共 freshness authority。未查询、轮询或等待 CI。
我的整体评价 / Verdict
本次有完整、可回滚且被真实入口采用的规则退役增量;APPROVE 仅指该精确源码/打包切片。long_horizon为 preserved:恢复与一次结算、完整源和任务承诺保持,但未测真实模型净益;user_experience为 preserved:原 CLI 返回同义结果,无额外确认或新配置,错误仍沿原 owner 恢复。生产代码净减113、少一次具名调用是工程结果,不是效率收益证明。
来源选择、展示规范化与 handoff 组合应归现有 TypeScript context/read owner;Python 保留泛型值编码和 IO,canonical provider、准入、结算及两次独立规划继续由原 owner 负责。
当前 PR 的可用边界是现有 CLI/上下文读回的一个完整规则退役切片;不新增 RPC、状态库或产品配置界面,保留同一请求内直接组合和明确的 facade 退出条件。
其余 Python 调用方及 facade 的退役、大 Goal 持续资源行为和安装宿主/模型实际采用仍在原迁移工作中开放。
已检查现有 CLI、status/context 和 handoff 消费者;没有渲染页面、布局或新交互变化,视觉评审不适用。视觉未验证范围:none。最强剩余范围是大 Goal/长期内存、最低 Node和原生 Windows、正式 App/Host采用及完整模型/人工成本;未把这些未来资格冒充完成。本评审不合并、撤销其他评审或改变共享安装,旧有效阻断仍须按原 closeout owner 分别核对。
English verdict: APPROVE — a8c1690. The complete summary-display retirement preserves current real File/SQLite readback, registered receipts and recovery; wheel/sdist mutation controls detect schema drift. Current default SQLite cost gates,380real PostgreSQL tests and local premerge pass. Historical failures and bounded RSS growth remain disclosed; live host/model benefit and long-run behavior are unqualified.
Problem and result
Python still owned Todo summary selection, display normalization and handoff assembly before the typed quota owner selected lanes. This change moves those read rules into the existing TypeScript context/handoff owners, preserving public Python entrypoints as codecs and transport. Quota composes display in process; both independent planning decisions remain.
The follow-up preserves the registered
todo_decision_scope_outcome_v0on the selected action. Canonical recovery fixtures now come from main (#7459); conflict resolution adopts that shared repair, and this PR adds the File/SQLite receipt-version regression without duplicating the fixture patch. There is no persisted-format, provider, authority, lease, receipt-identity or default change.Migration economics
todos/context_projection.ts, shared read/handoff codecs and quota planning. No new RPC method._compact_todo_summary_item_record,_refs,_TEXT_FIELDS,handoff_context_source, Python source joining and display normalization bodies.todo_read_source,_project, retained summary facades, quota raw-fact input and index handoff calls. Public source-key exports, Python-only scalar/repr facts, text revisions, bounded transport and response validation remain.todo.context.page22 → 21; bothtodo.quota_planning.projectcalls remain. Earlier 75 → 74, 83 → 82 and 88 → 87 traces use different fixtures/revisions.Exact-head validation
Baseline
17b2a0f9b818dc6e6fe77ccc567b20ff91b3bc40; head11bd4989f2cd1b9989962250f349b4f5c0d7bc26. Both are immutable source revisions. Detailed commands, aggregates and source-neutral replay code are in the author qualification comment.Default SQLite performance
Full-CLI p95 changes by −0.34 ms (−0.015%), within the unchanged 25 ms and 5% limits. Actual warm quota typed-request p95 is 1.263 ms, below 2 ms. All 64 paired CLI samples remain; observed maximum wall times are 4462.88/5230.64 ms, so this is not a p99 or sustained-tail claim.
Over 2,000 projections, base/head daemon RSS is 110.00/94.73 MiB idle and 116.11/137.89 MiB at sampled burst peak and after the burst. These are bounded observations, not a leak-free or long-run memory claim.
The final comparison uses adjacent immutable exports, identical bytecode preparation, the same synthetic project cwd, one interpreter and real SQLite, with alternating AB/BA order and no overlapping owned heavy build/test. Warm requests/facades use alternating 16-sample batches with 10 warmups per batch. Both quota-planning decisions remain.
All earlier cohorts remain historical evidence in the bilingual ledger and review replies: conflicting independent 32/64-pair results, this session’s mismatched source-placement experiment, and the later controlled qualification before the main rebase. None is silently relabelled. Main advanced during qualification, so this matrix was rerun for the current exact base/head. No threshold, source check or semantic input was weakened.
Limits and rollback
No new PostgreSQL store, minimum-Node, Windows, full-CI or whole-Goal migration qualification is claimed. File correctness is exercised; no new File performance claim. The broader contract-health suite now passes on main after adopting its canonical fixture repairs; failures from the earlier base remain historical records. Rollback is a code revert with no state migration. Agent-consumed prose and frontend entrypoints are unchanged; this is a shared read-owner retirement through existing consumers.
中文说明
把摘要展示、来源选择和 handoff 组合收敛到既有 TS owner,Python 保留必要的兼容编码和 transport。最终生产净减少 113 行;两个完整规划决策都保留。沿用主线 #7459 的 canonical fixture 修复,保留 receipt-version 回归,八个恢复及版本用例已实际跑通。默认 SQLite 的最终对照满足原有完整 CLI 与温态请求限值;历史失败、不一致批次和未验证范围均保留,不声称整 Goal、所有平台或长期性能已经验收。