From 46f844e9d2c03fc8fdbceee691fb854e4b07439b Mon Sep 17 00:00:00 2001 From: "lusendong.6789" Date: Thu, 12 Nov 2026 18:03:37 +0800 Subject: [PATCH 1/2] perf(todos): request only consumed replan projection views Signed-off-by: lusendong.6789 Co-authored-by: TRAE CLI --- loopx/control_plane/effect_runtime.py | 14 ++- .../control_plane/todos/context_projection.ts | 16 ++- loopx/control_plane/todos/quota_selection.py | 2 + loopx/control_plane/todos/quota_selection.ts | 6 +- loopx/control_plane/todos/quota_summary.py | 38 +++++++ .../work_items/semantic_replan_writeback.py | 10 +- .../test_canonical_quota_projection.py | 105 +++++++++++++++++- 7 files changed, 170 insertions(+), 21 deletions(-) diff --git a/loopx/control_plane/effect_runtime.py b/loopx/control_plane/effect_runtime.py index 8da649943d..e4f1fda620 100644 --- a/loopx/control_plane/effect_runtime.py +++ b/loopx/control_plane/effect_runtime.py @@ -1611,12 +1611,14 @@ def effect_runtime_result( def validate_result(result: Any) -> Any: # A caller must explicitly request a bundle. A request scope or a small # source does not establish that it will consume additional views. - if set(params) == {"summary_display_views"} and (not isinstance(result, dict) or any( - not isinstance(result.get(view), list) - or any(not isinstance(row, dict) for row in result[view]) - for view in ("summary", "planning", "terminal") - )): - raise RuntimeError("invalid TypeScript Todo source views") + if set(params) == {"summary_display_views"}: + requested = params["summary_display_views"].get("view_names", ("summary", "planning", "terminal")) + if not isinstance(result, dict) or any( + not isinstance(result.get(view), list) + or any(not isinstance(row, dict) for row in result[view]) + for view in requested + ): + raise RuntimeError("invalid TypeScript Todo source views") return result key = None diff --git a/loopx/control_plane/todos/context_projection.ts b/loopx/control_plane/todos/context_projection.ts index 30eeda5b75..20b39cc3e9 100644 --- a/loopx/control_plane/todos/context_projection.ts +++ b/loopx/control_plane/todos/context_projection.ts @@ -27,15 +27,21 @@ export function projectTodoContextPage(input: JsonObject): JsonObject { if (input.summary_display_views !== undefined) { if (Object.keys(input).length !== 1) throw new EffectRuntimeRequestError("summary display views cannot be combined with other views"); const source = requireJsonObject(input.summary_display_views, "summary display views"); - if (Object.keys(source).some(key => key !== "source" && key !== "handoff_gates")) { + if (Object.keys(source).some(key => key !== "source" && key !== "handoff_gates" && key !== "view_names")) { throw new EffectRuntimeRequestError("invalid summary display views fields"); } requireJsonObject(source.source, "summary source"); - return { - summary: projectTodoSummaryDisplay(source), - planning: projectTodoSummaryDisplay({source: source.source, include_terminal: false}), - terminal: projectTodoSummaryDisplay({source: source.source, include_terminal: true}), + const views: Record JsonObject[]> = { + summary: () => projectTodoSummaryDisplay(source), + planning: () => projectTodoSummaryDisplay({source: source.source, include_terminal: false}), + terminal: () => projectTodoSummaryDisplay({source: source.source, include_terminal: true}), }; + const names = source.view_names === undefined ? Object.keys(views) : source.view_names; + if (!Array.isArray(names) || names.length === 0 || new Set(names).size !== names.length || + names.some(name => typeof name !== "string" || !Object.hasOwn(views, name))) { + throw new EffectRuntimeRequestError("summary display views must name distinct supported views"); + } + return Object.fromEntries(names.map(name => [name, views[name as string]()])); } if (input.summary_display !== undefined) { if (Object.keys(input).length !== 1) throw new EffectRuntimeRequestError("summary display cannot be combined with other views"); diff --git a/loopx/control_plane/todos/quota_selection.py b/loopx/control_plane/todos/quota_selection.py index 1447c0a2f7..d78078f5af 100644 --- a/loopx/control_plane/todos/quota_selection.py +++ b/loopx/control_plane/todos/quota_selection.py @@ -116,6 +116,7 @@ def project_quota_planning( resolve_capacity: bool = False, current_time: str | None = None, summary_kind: str | None = None, consume_display_views: bool = False, request_only: bool = False, + display_view_names: list[str] | None = None, ) -> dict[str, Any]: identity = agent_identity if isinstance(agent_identity, dict) else {} profile = identity.get("agent_profile") @@ -195,6 +196,7 @@ def integer_text(raw: Any) -> str | None: if not native_profile else {}), "materialize_resume": reference is not None or request_only, "consume_display_views": consume_display_views, + **({"display_view_names": display_view_names} if display_view_names is not None else {}), }} if summary_kind else {}), "frontier_deadline": value.get("frontier_deadline"), "route_items": build_todo_route_continuation_facts(value, handoff_gates=handoff_gates), diff --git a/loopx/control_plane/todos/quota_selection.ts b/loopx/control_plane/todos/quota_selection.ts index a3521f641d..86c7ee34a1 100644 --- a/loopx/control_plane/todos/quota_selection.ts +++ b/loopx/control_plane/todos/quota_selection.ts @@ -501,8 +501,12 @@ export function projectTodoQuotaPlanning(value: unknown): JsonObject { if (request.summary_request !== undefined) { const wire = composeQuotaSummary(request, planning); const summary = requireJsonObject(request.summary_request, "summary request"); + if (summary.display_view_names !== undefined && summary.consume_display_views !== true) { + throw new EffectRuntimeRequestError("display view names require consumed display views"); + } if (summary.consume_display_views === true) { - const display = {source: summary.source, handoff_gates: (request.handoff_items as JsonObject[]).map(row => row.display)}; + const display = {source: summary.source, handoff_gates: (request.handoff_items as JsonObject[]).map(row => row.display), + ...(summary.display_view_names === undefined ? {} : {view_names: summary.display_view_names})}; wire.display_views = projectTodoContextPage({summary_display_views: display}); } if (summary.consume_vision_wait_basis === true) { diff --git a/loopx/control_plane/todos/quota_summary.py b/loopx/control_plane/todos/quota_summary.py index 50883f292a..97f7272266 100644 --- a/loopx/control_plane/todos/quota_summary.py +++ b/loopx/control_plane/todos/quota_summary.py @@ -508,6 +508,44 @@ def select_quota_todo_summaries( select_quota_todo_summary(agent_source, None, agent_identity=agent_identity)) +def select_quota_todo_summaries_with_terminal( + user_source: Any, agent_source: Any, *, agent_identity: dict[str, Any] | None, +) -> tuple[dict[str, Any] | None, dict[str, Any] | None, list[dict[str, Any]]]: + """Read two summaries and complete Agent terminal rows in one transaction. + + Reuse the typed quota and display owners while requesting only consumed + views. Ordinary quota retains its own full displays and prepared wait facts. + """ + from .quota_selection import _decode_quota_summary_wire + from .goal_todo_projection import project_todo_read + + sources = [(role, value) for role, value in (("user", user_source), ("agent", agent_source)) + if isinstance(value, dict)] + requests = [project_quota_planning(value, all_open_items=[], + source_open_count=value.get("open_count"), agent_identity=agent_identity, + filter_user_gate_blocks_agent=role == "user", available_capabilities=None, + summary_kind="user", consume_display_views=role == "agent", request_only=True, + display_view_names=["terminal"] if role == "agent" else None) + for role, value in sources] + summaries: dict[str, dict[str, Any]] = {} + terminal: list[dict[str, Any]] = [] + if requests: + result = project_todo_read({"kind": "quota_projection", "requests": requests}) + wires = result.get("quota_wires") + if not isinstance(wires, list) or len(wires) != len(requests): + raise RuntimeError("invalid complete quota projection response") + for (role, source), wire in zip(sources, wires, strict=True): + summaries[role] = _decode_quota_summary_wire(wire, source) + if role == "agent": + views = wire.get("display_views") + if not isinstance(views, dict) or set(views) != {"terminal"}: + raise RuntimeError("invalid consumed Agent terminal view") + terminal = views["terminal"] + if not isinstance(terminal, list) or any(not isinstance(row, dict) for row in terminal): + raise RuntimeError("invalid Agent terminal source rows") + return summaries.get("user"), summaries.get("agent"), terminal + + def select_quota_todo_contexts( user_canonical: Any, user_asset: Any, agent_canonical: Any, agent_asset: Any, *, agent_identity: dict[str, Any] | None, available_capabilities: Any, diff --git a/loopx/control_plane/work_items/semantic_replan_writeback.py b/loopx/control_plane/work_items/semantic_replan_writeback.py index 27e850f76d..494bb176ad 100644 --- a/loopx/control_plane/work_items/semantic_replan_writeback.py +++ b/loopx/control_plane/work_items/semantic_replan_writeback.py @@ -20,8 +20,7 @@ ) from ..todos.active_state_todo_parser import parse_active_state_todos from ..todos.quota_summary import ( - select_planning_inventory_source_items, - select_quota_todo_summaries, + select_quota_todo_summaries_with_terminal, ) from ..todos.succession_warning import todo_succession_gap_items from .autonomous_replan_ack import ( @@ -264,14 +263,9 @@ def qualify_replan_writeback( ) raw_user_todos = todo_projection.get("user_todos") raw_agent_todos = todo_projection.get("agent_todos") - user_todos, agent_todos = select_quota_todo_summaries( + user_todos, agent_todos, agent_todo_source_items = select_quota_todo_summaries_with_terminal( raw_user_todos, raw_agent_todos, agent_identity=agent_identity, ) - agent_todo_source_items = select_planning_inventory_source_items( - raw_agent_todos, - None, - include_terminal=True, - ) agent_todo_completion_items = ( [ item diff --git a/tests/control_plane/test_canonical_quota_projection.py b/tests/control_plane/test_canonical_quota_projection.py index c473948fc3..b226688216 100644 --- a/tests/control_plane/test_canonical_quota_projection.py +++ b/tests/control_plane/test_canonical_quota_projection.py @@ -7,12 +7,115 @@ from loopx.control_plane.coordination.local_authority import LocalCoordinationAuthorityUnavailable, read_canonical_todos_if_promoted from loopx.control_plane.todos.goal_todo_projection import project_todo_read, todo_summaries_from_fields from loopx.control_plane.todos.quota_selection import project_quota_planning -from loopx.control_plane.todos.quota_summary import select_quota_todo_contexts, select_quota_todo_summaries, select_quota_todo_summary +from loopx.control_plane.todos.quota_summary import select_quota_todo_contexts, select_quota_todo_summaries, select_quota_todo_summary, select_quota_todo_summaries_with_terminal, select_planning_inventory_source_items from loopx.control_plane.todos.summary_item import canonical_todo_source_reference from loopx.control_plane.todos.list_readback import list_goal_todos from tests.control_plane import test_quota_settlement_cli as fixture +@pytest.mark.parametrize("provider", ["file", "sqlite"]) +def test_replan_transaction_retains_complete_terminal_rows_and_source_fences(tmp_path, monkeypatch, provider): + from loopx.control_plane import effect_runtime as runtime_owner + + project, runtime, _ = fixture._write_fixture(tmp_path, claimed=False) + state = project / f".codex/goals/{fixture.GOAL_ID}/ACTIVE_GOAL_STATE.md" + with state.open("a") as file: + for index in range(160): + file.write(f"\n- [x] [P1] Completed synthetic work {index}\n" + f" \n") + fixture._initialize_fixture_authority(project, runtime, provider=provider) + identity = {"agent_id": fixture.AGENT_ID} + replies = [] + dispatch = runtime_owner.effect_runtime_request + def observed(method, params, **kwargs): + result = dispatch(method, params, **kwargs) + if method == "todo.read" and params.get("kind") == "quota_projection": + replies.append((params, result)) + return result + monkeypatch.setattr(runtime_owner, "effect_runtime_request", observed) + with effect_runtime_request_scope(): + before = read_canonical_todos_if_promoted(runtime_root=runtime, + goal_id=fixture.GOAL_ID, include_summary=True) + fields = before["_todo_fields"] + user, agent = fields["user_todos"], fields["agent_todos"] + expected = (*select_quota_todo_summaries(user, agent, agent_identity=identity), + select_planning_inventory_source_items(agent, None, include_terminal=True)) + replies.clear() + actual = select_quota_todo_summaries_with_terminal(user, agent, agent_identity=identity) + assert actual == expected + assert len(actual[2]) == 161 + assert actual[2][-1]["successor_todo_ids"] == ["todo_terminal_160"] + assert len(replies) == 1 + request, response = replies[0] + assert all("source_reference" in row["summary_request"] for row in request["requests"]) + wires = response["result"]["quota_wires"] + assert "display_views" not in wires[0] + assert set(wires[1]["display_views"]) == {"terminal"} + assert all("vision_wait_basis" not in wire for wire in wires) + invalid = deepcopy(request) + invalid["requests"][1]["summary_request"]["source_reference"]["field_sha256"] = "0" * 64 + with pytest.raises(ValueError, match="original complete read"): + project_todo_read(invalid) + stale = deepcopy(agent) + stale.expected = {**stale.expected, "cursor": "foreign"} + with pytest.raises(ValueError, match="canonical source changed"): + select_quota_todo_summaries_with_terminal(user, stale, agent_identity=identity) + directory = runtime / "authority" / f"{provider}-v0" + retained = directory.with_name(directory.name + "-retained") + directory.rename(retained) + try: + with pytest.raises(LocalCoordinationAuthorityUnavailable) as original: + read_canonical_todos_if_promoted(runtime_root=runtime, goal_id=fixture.GOAL_ID) + with pytest.raises(LocalCoordinationAuthorityUnavailable) as narrowed: + select_quota_todo_summaries_with_terminal(user, agent, agent_identity=identity) + assert narrowed.value.code == original.value.code + assert narrowed.value.payload == original.value.payload + finally: + retained.rename(directory) + # References leaving their request scope use the complete supplied codec. + assert select_quota_todo_summaries_with_terminal(user, agent, agent_identity=identity) == expected + after = read_canonical_todos_if_promoted(runtime_root=runtime, goal_id=fixture.GOAL_ID) + assert after["provider_revision"] == before["provider_revision"] + assert after["todos"] == before["todos"] + + +@pytest.mark.parametrize("names", [[], ["terminal", "terminal"], ["foreign"], [1], "terminal"]) +def test_summary_display_view_selection_rejects_invalid_names(names): + from loopx.control_plane.effect_runtime import EffectRuntimeRejected, effect_runtime_result + from loopx.control_plane.todos.handoff_note import todo_read_source + + source = {"items": [{"todo_id": "todo_a", "status": "done", "done": True}]} + with pytest.raises(EffectRuntimeRejected, match="distinct supported views"): + effect_runtime_result("todo.context.page", {"summary_display_views": { + "source": todo_read_source(source), "view_names": names}}) + + +def test_summary_display_default_parity_and_explicit_terminal_selection(): + from loopx.control_plane.effect_runtime import effect_runtime_result + from loopx.control_plane.todos.handoff_note import todo_read_source + from loopx.control_plane.todos.summary_item import todo_source_display_views + + source = {"items": [{"todo_id": "todo_a", "text": "Completed work", "status": "done", "done": True, + "task_class": "advancement_task", "successor_todo_ids": ["todo_b"]}, + {"todo_id": "todo_b", "text": "Successor work", "status": "open", "done": False, "task_class": "advancement_task"}]} + request = {"source": todo_read_source(source)} + default = effect_runtime_result("todo.context.page", {"summary_display_views": request}) + assert set(default) == {"summary", "planning", "terminal"} + assert default == todo_source_display_views(source) + selected = effect_runtime_result("todo.context.page", {"summary_display_views": { + **request, "view_names": ["terminal"]}}) + assert selected == {"terminal": default["terminal"]} + assert {row["todo_id"] for row in selected["terminal"]} == {"todo_a", "todo_b"} + invalid = project_quota_planning(source, all_open_items=[], source_open_count=1, + agent_identity={"agent_id": "agent-a"}, filter_user_gate_blocks_agent=False, + available_capabilities=None, summary_kind="user", request_only=True, + display_view_names=["terminal"]) + with pytest.raises(ValueError, match="require consumed display views"): + project_todo_read({"kind": "quota_projection", "requests": [invalid]}) + + @pytest.mark.parametrize("provider", ["file", "sqlite"]) def test_provider_projection_uses_complete_source_differences_and_scope_exit(tmp_path, provider): project, runtime, registry = fixture._write_fixture(tmp_path, claimed=False) From e19dda2821a7e72a08f86cbcc1421c7494a7d6e4 Mon Sep 17 00:00:00 2001 From: "lusendong.6789" Date: Thu, 12 Nov 2026 18:08:09 +0800 Subject: [PATCH 2/2] docs(rfc): record scoped replan projection qualification Signed-off-by: lusendong.6789 Co-authored-by: TRAE CLI --- .../rfcs/monorepo-distribution-split-v0.md | 31 +++++++++++++++++++ .../monorepo-distribution-split-v0.zh-CN.md | 24 ++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/docs/architecture/rfcs/monorepo-distribution-split-v0.md b/docs/architecture/rfcs/monorepo-distribution-split-v0.md index 366573c3b6..2021df3c6c 100644 --- a/docs/architecture/rfcs/monorepo-distribution-split-v0.md +++ b/docs/architecture/rfcs/monorepo-distribution-split-v0.md @@ -3437,3 +3437,34 @@ boundaries. Workspace/meta-package publication, complete install/load/context closure, independent Standard packages, other host/platform adoption, matched model effectiveness and complete costs remain open. This synthetic task and recovery evidence establishes neither model benefit nor an installed-host upgrade. + +### 2026-11-12 — Replan consumes only required Todo views + +The replan writeback caller now requests its two role summaries and complete +Agent terminal rows through the existing quota read transaction. The existing +TypeScript display owner accepts an explicit subset; omitted selection retains +all three ordinary quota views. User source-summary rows, unused Agent views +and prepared Vision wait facts are not generated for this caller. Source +references, complete supplied-source fallback and provider error diagnostics +retain their existing owners. No storage, lease, scheduler or quota-debit rule +changes. + +Against immutable base `0abd0dc27`, candidate code `46f844e9d` uses the same +disposable mixed-state fixtures and six alternating pairs per workload on real +File/default-SQLite. SQLite replan qualification medians at 320/3,500 extra +Agent Todos are 93.2→83.3 ms and 612.3→572.0 ms; canonical-read plus +qualification medians are 139.4→130.0 ms and 900.9→857.0 ms. Strict refresh +dry-run rejection medians are 142.4→135.1 ms and 934.4→911.8 ms. At zero extra +Todos that refresh median is 28.9→29.3 ms; retain this observation without a +noise or causality claim. Up to 128 User rows are included. Normalized +obligations and rejection details match; counting fewer RPCs alone is not the +acceptance oracle. Seventy focused production-provider and transport checks +pass, including complete terminal tails, stale/missing sources and ordinary +display defaults. + +Preserve #8624's original negative SQLite qualification (83.0→91.2 ms and +605.9→704.1 ms) at its original head and criteria. This new scoped result +qualifies the consumed replan read cost; full CLI process, durable writeback, +model and end-to-end outcome costs are not inferred from these timings. The +complete minimal load/context closure, R1/M3, independent Standard packages, +workspace/meta publication and installed-host adoption remain open. 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 82609b51ff..b38cf52a99 100644 --- a/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md +++ b/docs/architecture/rfcs/monorepo-distribution-split-v0.zh-CN.md @@ -2682,3 +2682,27 @@ package-smoke 工作流执行这套安装后验证。 保留 D1-D7、原有里程碑、历史失败与验收边界。workspace/meta 发行、完整安装/ 加载/context 闭包、独立 Standard 包、其他宿主/平台采用、配对模型效果和完整 成本仍开放。合成任务与恢复证据不证明模型收益,也不代表已升级当前宿主。 + +### 2026-11-12 — Replan 只消费所需 Todo 视图 + +Replan 写回调用方现在通过既有 quota 读取事务取得两个角色摘要及完整 Agent +terminal 行。既有 TypeScript 显示 owner 接受显式视图子集;省略选择时仍保留普通 +quota 的全部三种视图。该调用方不再生成 User source-summary 行、未消费的 Agent +视图及预建 Vision 等待事实。来源引用、完整内联来源回退及 provider 错误诊断仍由 +既有 owner 处理;存储、lease、scheduler 及 quota 扣额规则保持原语义。 + +以不可变基线 `0abd0dc27` 对照候选代码 `46f844e9d`,复用同一隔离混合状态夹具, +在真实 File/默认 SQLite 上每种负载执行六组交替配对。额外 320/3,500 条 Agent +Todo 时,SQLite replan 资格检查中位数为 93.2→83.3 ms、612.3→572.0 ms;包含 +canonical 读取与资格检查的中位数为 139.4→130.0 ms、900.9→857.0 ms。严格 refresh +dry-run 拒绝路径的中位数为 142.4→135.1 ms、934.4→911.8 ms。零条额外 Todo 时, +该 refresh 中位数为 28.9→29.3 ms;保留这项观测,不推断噪声或因果。夹具包含 +最多 128 条 User 行。归一化后的义务及拒绝详情一致;减少 RPC 次数本身不能作为 +验收依据。70 项聚焦生产 provider 与传输检查通过,覆盖完整 terminal 尾部、 +过期/缺失来源及普通显示默认值。 + +保留 #8624 原 head 及原标准下的 SQLite 负面资格结果(83.0→91.2 ms、 +605.9→704.1 ms)。这份新范围结果只证明所消费 replan 读取的成本资格;不能从 +这些计时推断完整 CLI 进程、持久写回、模型及端到端成果成本。完整最小加载/ +上下文闭包、R1/M3、独立 Standard 包、workspace/meta 发布及安装宿主采用仍未 +完成。