Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3111,7 +3111,15 @@ This closes that T3/L5 consumer family, not D1 permanent display freshness,
D2 durability, D3 whole-Goal qualification or default-provider selection. The
conditional 7–9 remaining delivery-package estimate is unchanged.

Summary/work-lane counts now remain independent of display limits and retain incomplete-source knowledge through Agent scoping; canonical list acceptance holds match status. This closes one L5 read consumer, not permanent projection freshness or D1–D3. See [count semantics](../../reference/todo-work-counts.md).
The Todo summary consumer now uses one TS batch for scope, lanes, counts,
claimant-balanced display and closure. It retires Python count/cap/allocation
branches and two separate internal lane/closure calls. Recent completion uses
actual completion instants, not edit time or ISO-string order; partial source
knowledge cannot become a whole-source closure proof after selection. Public
summary/persisted record schemas and display budgets stay unchanged. Real CLI
and complete-graph provider readback qualify this read-model boundary, not
permanent projection freshness or all D1–D3. See
[count and chronology semantics](../../reference/todo-work-counts.md).

The Goal Channel ownership observation consumes one complete provider revision before bounding display. It never repairs Markdown or revives old local leases; provider failures and truncation stay visible. This is a T3 read closure with shared TS interpretation, not D1/D2 qualification or D3 cutover. See [coordination observation](../../reference/coordination-observation.md).

Expand Down Expand Up @@ -3296,7 +3304,15 @@ merges qualifies default-on; unresolved acceptance evidence keeps its hold.
| 6. Capture plus whole-Goal migration/rollback (1–2 PRs) | L7/L8: combine mixed-writer/event continuity, drain, old-writer fencing, canonical readback, fenced export/rollback and cohort migration. | One D3 packet binds exact profile, lineage, source digest and command inventory; existing-Goal cohort cutover remains explicit. |
| 7. Default/onboarding and bounded Python retirement | L9/T4: make new-Goal creation, settings, installer and packaged clients choose the qualified local profile; publish migration/disable guidance and delete replaced final business writers. | Integrated L8 qualification, rollback and affected user-entrypoint readback. Preserve active rendering, host execution and import/export adapters. |

After boundary 3 lands, **six planned PRs remain, potentially eight** under those
At the 2026-09-24 reconciliation, #4870/#4888/#4920, #4922 (snapshot pagination),
#4960 (qualified SQLite runtime admission) and #4961 (refresh display recovery)
are merged, while #4931 (SQLite proof encoding) remains a separate in-review
dependency and SQLite #4224 still retains failing/missing D2 evidence. This
summary slice closes shared read-model decisions and advances boundary 4, not
those delivery gates: requalify the combined accepted head before updating the
estimate, and do not count each helper migration as one complete package.

With boundary 3 landed, **six planned PRs remain, potentially eight** under those
two named splits. Caller audit can expose additional missing effects, so this is
an implementation estimate, not a guarantee. Small Python business-rule
retirements accompany their TS owner; deleting all Python is neither the exit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2422,6 +2422,14 @@ Scoped fallback 的选择与门禁关系也已复用同一 TS decision owner,

**D1 — 资格化永久投影交付,可与 T1/T2 重叠推进。**

Todo 摘要现由一个 TS 批次决定范围、lanes、计数、claim 展示分配和收尾证明,删除
Python 的重复汇总分支及分离的 lane/closure 内部调用。最近完成按真实完成时刻排序,
不把编辑时间或 ISO 字符串顺序当作完成顺序;partial 来源不能在再次筛选后重新取得
整源收尾证明。公开摘要/持久记录合同与展示预算保持不变。
见[计数与时间语义](../../reference/todo-work-counts.md)。这关闭共享摘要决策,不宣称
全部消费者、永久展示新鲜度或 D1–D3 已通过。


摘要与 work-lane 计数已独立于展示上限,并在 Agent 筛选后保留来源不完整状态;canonical 列表的 acceptance 限制与 status 一致。这只闭合 L5 的一个读取消费者,不代表永久投影新鲜度或 D1–D3 完成。见[计数语义](../../reference/todo-work-counts.md)。

Goal Channel 所有权观察先读取完整 provider revision,再限制展示;不修复 Markdown、不复活旧本地 lease,明确披露失败与截断。这是共用 TS 解释规则的 T3 读链路闭合,不完成 D1/D2 或 D3 切换,见 [coordination observation](../../reference/coordination-observation.md)。
Expand Down Expand Up @@ -2536,11 +2544,11 @@ provider 确认;权威空集合不回退到陈旧 Markdown。Legacy 与预览
| D/L9:新 Goal 默认与有界退役 | 单独 default-change PR 让新建/onboarding 选择合格本地 profile,配齐 settings/readback、installer 和打包客户端;最后 caller 与迁移窗口退出才删除旧业务 writer。 | L8 整体产品/回滚资格;区分新 Goal 默认和已有 Goal 迁移。发布兼容/停用说明,保留显式 provider、永久 renderer 和合法 import/export。T4 可在默认启用后继续收尾。 |

**2026-09-24 基线核对。** 保留 claim 的 #4870、reviewed cutover #4888、shadow drain
规划 #4920 已合并,快照分页 #4922 也已合并,后续应验收组合 head,而不是继续沿用
旧的 PR hold;SQLite 读取证明优化 #4931 仍在评审。#4910 已加入更大测量轴;#4224
实测 1 MiB receipt/scan 超预算,恢复和自然时间资格仍有缺项,不能将优化 PR 当成 D2
通过。本次刷新恢复推进下表中第 4 项投影恢复边界,但没有把其他调用方或默认切换
标记完成。
规划 #4920 已合并,快照分页 #4922、SQLite runtime 准入 #4960 与刷新显示恢复 #4961 也已
合并,后续应验收组合 head,而不是继续沿用旧的 PR hold;SQLite 读取证明优化 #4931 仍在
评审。#4224 实测 1 MiB receipt/scan 超预算,恢复和自然时间资格仍有缺项,不能将优化 PR
当成 D2 通过。本次摘要规则收口推进下表中第 4 项投影恢复边界,但没有把其他调用方或默认
切换标记完成;数量估计应在组合 head 验收后更新,不能按 helper 迁移数量机械扣减。

**开发节奏以证据推进。** 2026-09-23 将旧计划的五类粗粒度交付包细化为
**七个明确 PR 边界;D2 和迁移各拆两批时最多九个**,其中包含本批一致性分页。
Expand Down
13 changes: 13 additions & 0 deletions docs/architecture/rfcs/typescript-control-plane-migration-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -1905,3 +1905,16 @@ This is a migration orchestration checkpoint, not completion of Stage 3 or a
default-provider flip. Integrate claim-preserving migration separately, retain
real-backend and captured-source qualification, and retire Python only where its
actual callers have moved. [Operator contract](../../reference/reviewed-coordination-promotion.md).


### Todo summary decision ownership

One TS summary batch now owns selected-source counts, display allocation,
recent-completion chronology, orchestration candidate positions and closure
proofs. Python retains decoding, public field allowlists and rendering. The
old Python claimant selector and aggregate branches are retired; the internal
lane and closure RPC entries are replaced without retaining unused wire paths.
Public `todo_summary_v0` and persisted records do not change. Full-source
relationship evaluation is reused before selection, and source completeness is
preserved independently of query matching. See [semantics and rollback](../../reference/todo-work-counts.md).
This advances T3/L5; it does not replace D2/D3 or flip a provider default.
Original file line number Diff line number Diff line change
Expand Up @@ -1468,3 +1468,13 @@ This is a migration orchestration checkpoint, not completion of Stage 3 or a
default-provider flip. Integrate claim-preserving migration separately, retain
real-backend and captured-source qualification, and retire Python only where its
actual callers have moved. [Operator contract](../../reference/reviewed-coordination-promotion.md).


### Todo 摘要决策收口

已选来源的计数、展示分配、最近完成时间顺序、编排候选位置与收尾证明,收口到一个
TS 摘要批次;Python 保留旧格式解码、公开字段筛选及渲染。删除旧 Python claim 分配
算法和汇总分支,用一个内部入口替换 lane/closure 两次调用,不保留无调用方的旧 wire。
公开 `todo_summary_v0` 和持久记录不变;完整来源的关系求值先于筛选,来源完整性不被
查询命中情况覆盖。见[语义及回滚](../../reference/todo-work-counts.md)。这是 T3/L5 的
共享读取边界推进,不替代 D2/D3 或 provider 默认切换。
54 changes: 50 additions & 4 deletions docs/reference/todo-work-counts.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ read and continue to show the whole Goal; no new configuration editor is needed.
Resume and succession are evaluated on the complete source before selection.
The typed batch filters rows without renumbering their original source indexes,
then builds lanes/counts, and only then applies display limits. Status/identity
filters do not recompute dependencies from their smaller view. The v1 internal
request composes this selection into the existing call; v0 unfiltered callers
retain their wire contract. Python decodes legacy input and renders results,
with no independent Agent-addressing rule.
filters do not recompute dependencies from their smaller view. One internal `todo.summary.project` batch now composes selection, counts,
visibility allocation and closure. Its transient request replaces the separate
lane and closure RPC calls; it does not change persisted Todo or public summary
schemas. Python decodes legacy input, validates source ordinals and materializes
public fields, with no independent summary count, cap or claimant-allocation rule.

## 中文说明

Expand Down Expand Up @@ -112,3 +113,48 @@ claim/exclusion 筛选,可见不代表获准执行。
当前列表。未筛选的整 Goal 视图仍显示这些记录。依赖和 succession 先在完整来源求值,
TS 再筛选并保留原数组位置,最后生成 lanes、计数和有界展示;筛选后的数组位置不是原
来源位置。无需新增 capability、配置、前端或 Lark 编辑入口,不增加一次筛选 RPC。

## Summary chronology and source completeness

The same TS projection now supplies `recent_completed_advancement_items`,
claimant-balanced display lanes, orchestration candidate positions and closure
proofs to legacy and canonical consumers. Display budgets are unchanged;
`items` limits never change full-source counts. Full-source resume/succession
evaluation still precedes filtering, and returned positions refer to the original
array, not a newly numbered subset. Python retains public field allowlists,
warning text, privacy redaction and Markdown parsing/rendering.

**Intentional read behavior changes:** recent completions are ordered by the
actual `completed_at` instant, preserving timezone offsets and microseconds.
Later `updated_at` edits no longer make an old completion recent. Missing or
invalid completion times remain in completed-work counts/history but do not
claim a place in the recent-completion lane. Equal instants retain reverse
source-coordinate order and stable ties. Succession warnings keep their
last-change ordering, now comparing instants rather than timestamp strings;
unknown instants follow known ones without discarding the warning.

A source already marked partial cannot regain `source_proof` or
`terminal_closure_proof` simply because a later selection matches all visible
rows. Query scope and source completeness are independent conditions. These
proofs remain read-only observations, not permission to settle a Goal.

This changes status, Todo-list and quota summary readback for both legacy and
promoted Goals without a flag. Existing frontend and Lark views consume these
Core projections; no new setting or frontend asset is required. No provider,
lease, registry or display writer is added. Rollback requires the matching
Python/TS package but no data migration. Full L5 consumer acceptance, projection
freshness, SQLite D2 and default/cutover gates remain separate.

### 中文补充

摘要的计数、展示上限、领取者之间的展示分配、编排候选位置及收尾证明,现由一个 TS
批次决定;删除 Python 的重复汇总分支和仅为旧内部调用保留的 claim 分配 helper。
Python 继续负责旧数据解码、公开字段筛选、隐私处理与文本展示。

这是有意的读取语义修复:最近完成列表按 `completed_at` 的真实时刻排序,保留时区和
微秒,不再把较晚编辑误作较晚完成。缺失/非法时间仍计入已完成总数和历史,但不进入
最近完成列表。后继缺口警告仍按最后更新时间排序,未知时间靠后,不丢弃警告。
已有 partial 来源不会因为再次筛选命中所有可见行,就重新获得整个来源的收尾证明。

覆盖 legacy 与 canonical 的 status、Todo 查询和 quota 摘要;展示预算保持原值。
没有新增设置、权限或 writer,不改变 provider 默认值,也不宣称完成整 Goal 迁移。
18 changes: 2 additions & 16 deletions examples/control_plane/todo-projection-shared-helper-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
build_goal_frontier_projection_from_summaries,
)
from loopx.status import ( # noqa: E402
claimed_visibility_items as status_claimed_visibility_items,
todo_item_is_deferred as status_todo_item_is_deferred,
todo_projection_sort_key,
)
Expand All @@ -42,7 +41,6 @@
TODO_TASK_CLASS_MONITOR,
)
from loopx.control_plane.todos.projection import ( # noqa: E402
todo_claimed_visibility_items as shared_claimed_visibility_items,
todo_item_claimed_by_agent_or_unclaimed as shared_todo_item_claimed_by_agent_or_unclaimed,
todo_item_is_deferred as shared_todo_item_is_deferred,
todo_projection_sort_key as shared_todo_projection_sort_key,
Expand Down Expand Up @@ -165,7 +163,7 @@ def assert_shared_ordering_parity(summary: dict) -> None:
assert quota_todo_projection_sort_key(embedded_priority) == (50, 9), embedded_priority


def assert_claimed_visibility_parity() -> None:
def assert_claim_scope_parity() -> None:
items = [
quota_todo_item(
todo_id="todo_a1",
Expand Down Expand Up @@ -199,18 +197,6 @@ def assert_claimed_visibility_parity() -> None:
task_class=TODO_TASK_CLASS_ADVANCEMENT,
),
]
for selector in (
shared_claimed_visibility_items,
status_claimed_visibility_items,
):
selected_two = selector(items, limit=2)
assert [item["todo_id"] for item in selected_two] == ["todo_a1", "todo_b1"], selected_two
selected_three = selector(items, limit=3)
assert [item["todo_id"] for item in selected_three] == [
"todo_a1",
"todo_a2",
"todo_b1",
], selected_three
claimed_by_current = items[0]
claimed_by_other = items[2]
unclaimed = items[3]
Expand Down Expand Up @@ -487,7 +473,7 @@ def main() -> int:
summary = build_agent_todo_summary()
assert_status_summary_lanes(summary)
assert_shared_ordering_parity(summary)
assert_claimed_visibility_parity()
assert_claim_scope_parity()
assert_agent_scope_frontier_routing_parity()
assert_deferred_helper_parity()
assert_monitor_item_collection_parity(summary)
Expand Down
8 changes: 4 additions & 4 deletions loopx/control_plane/effect_runtime_handlers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {projectTodoSummary} from "./todos/summary_projection.ts";
import {admitAutomationStart, confirmAutomationStart, manageAutomationCadence, projectCadenceSchedule} from "./quota/automation_cadence.ts";
import {deliverShadowEntry} from "./coordination/shadow_entry_delivery.ts";
import {readShadowDrainPlan} from "./coordination/shadow_drain_plan.ts";
Expand All @@ -9,8 +10,8 @@ import {projectPeerOrchestration} from "./quota/peer_orchestration.ts";
import {inspectTaskLease} from "./work_items/task_lease_inspection.ts";
import {evaluateTodoPriority} from "./todos/priority.ts";
import {evaluateUserCompletion} from "./todos/user_completion.ts";
import {projectTodoSuccession, projectTodoClosure} from "./todos/succession.ts";
import {projectTodoSummaryLanes, projectLegacyTodoWorkCounts} from "./todos/summary_lanes.ts";
import {projectTodoSuccession} from "./todos/succession.ts";
import {projectLegacyTodoWorkCounts} from "./todos/summary_lanes.ts";
import {recordDelegationAdoption, delegationInventoryItem, delegationInventoryQuery, delegationPreflight, delegationTurnPlanDecision, recoverValidatedDelegationSettlement, selectDelegationBinding, transitionDelegationObservation} from "./collaboration/delegation.ts";
import {planChatMode} from "./collaboration/chat_mode.ts";
import {resolveConversationScope} from "./collaboration/conversation_scope.ts";
Expand Down Expand Up @@ -442,11 +443,10 @@ export function createEffectRuntimeHandlers(
["todo.priority.plan", evaluateTodoPriority],
["todo.public_update.plan", planPublicTodoUpdate],
["todo.standing_decision.project", evaluateStandingDecisionProjection],
["todo.summary_lanes.project", projectTodoSummaryLanes],
["todo.summary.project", projectTodoSummary],
["capabilities.periodic_report.progress.select", selectPeriodicReportProgress],
["capabilities.periodic_report.approval_retry.select", selectPeriodicReportApprovalRetry],
["todo.succession.project", projectTodoSuccession],
["todo.succession.closure", projectTodoClosure],
["todo.work_counts.project", projectLegacyTodoWorkCounts],
["todo.decision_scope.evaluate", evaluateDecisionScope],
["todo.user_completion.plan", evaluateUserCompletion],
Expand Down
Loading
Loading