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
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 @@ -64,6 +64,19 @@ without claiming code retirement:
bootstrap, handoff, team-plan and Monitor still have supported source callers;
keep capture/outbox and historical recovery until their own exits. [Caller and
rollback inventory](../../reference/canonical-todo-completion-update.md#canonical-mutation-entrypoint-isolation).
Production Todo consumers now bypass the historic `loopx.todos` re-export:
CLI registration/actions, quota and planning, capability writeback, source lease
reads and the Lark source projection import the same concrete mutation, full-read,
path or Markdown display owners. No new wrapper, decision or RPC is introduced.
The historic public imports and their supported unpromoted IO remain available.
Disposable source/normal-wheel probes remove the facade, the whole legacy Todo
writer and four shadow producers together; real File/SQLite CLI lifecycle,
once-only settlement, Monitor replay and App cold-import/action/restart journeys
must still work, with missing-provider/lease and changed-source/backup refusals.
Lark dry-run and Explore replay qualify local consumers only, not live external
adoption. This closes the production re-export dependency, while last supported
source writers, historical recovery, installed cohort and release exits remain.

The retained import-compatible field writer now composes resume normalization
and contradictory-clear rejection in its existing typed field plan. Keep blank
Python input omission and locked IO; retire the duplicate normalization crossing,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ canonical Todo 入口隔离(T4):五种 mutation facade 统一进入既有
revision 保持。这为最后调用方删除建立边界,不宣称代码已退役:bootstrap、
handoff、team-plan 和 Monitor 仍有受支持的旧源调用;capture/outbox 及历史恢复
各等自己的出口。见[调用方及回滚清单](../../reference/canonical-todo-completion-update.md#canonical-mutation-entrypoint-isolation)。
生产 Todo 消费者不再经历史 `loopx.todos` 重导出:CLI 注册/操作、quota 与规划、
能力写回、旧源租约读取及 Lark 源投影直接导入相同的 mutation、完整读取、路径或
Markdown 显示 owner,不新增 wrapper、决策或 RPC。历史公开导入及其受支持的旧源
IO 继续保留。隔离源码/正常 wheel 同时移除 facade、整个旧 Todo writer 和四个
shadow producer,验证真实 File/SQLite CLI 生命周期、恰好一次结算、Monitor 重放
及 App 冷导入/操作/重启;缺 provider/租约及源/备份变化须拒绝。Lark dry-run
与 Explore 重放只验证本地消费者,不计 live 外部采用。此出口关闭生产重导出依赖,
最后受支持的旧源 writer、历史恢复、安装 cohort 与发布验收继续保留。

保留的 import-compatible field writer 在既有 typed field plan 中统一等待条件
归一化及矛盾 clear 拒绝;保持 Python 空白输入省略和锁内 IO,只退役重复的
normalization crossing,不删除仍受支持的 writer 或迁移 reader。
Expand Down
24 changes: 24 additions & 0 deletions docs/reference/canonical-todo-completion-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,30 @@ Whole-writer retirement still needs the declared support cutoff, last callers
and pending outbox disposition; this separation does not force an upgrade or
change a provider default.

Production callers import those same owners directly: `mutation_api` for the
five operations and archive constant, `list_readback` for complete Todo reads,
`path_resolution` for configured source routing, and `active_state_editing` for
supported source-display parsing. This includes CLI registration, quota/planning,
capability consumers and Lark. The historic `loopx.todos` public surface remains
an alias to the same function objects; no source-format support is withdrawn.
The consumer oracle adds physical facade removal to whole-writer/four-producer
removal in source and normal-wheel copies. It reuses the lifecycle, creation,
lease/once-only settlement and Monitor negative/replay oracles, plus real App
HTTP cold import, later mutations and server restart. The Lark dry-run refuses
remote execution; Explore projection replays without duplicate events. These
local extension checks do not qualify live Lark adoption. Restoring imports is
a code rollback with no new schema, provider selection or receipt conversion.

生产调用方直接导入相同 owner:`mutation_api` 负责五种操作及归档常量,
`list_readback` 负责完整 Todo 读取,`path_resolution` 负责已配置的源路径,
`active_state_editing` 负责受支持的源显示解析;覆盖 CLI 注册、quota/规划、能力
消费者与 Lark。历史 `loopx.todos` 仍重导出相同函数对象,旧格式支持未撤销。
消费者检查在源码及正常 wheel 中同时物理移除 facade、整个 writer 和四个 producer,
复用生命周期、创建、租约/恰好一次结算及 Monitor 负例/重放,另验真实 App HTTP
冷导入、后续写入与服务重启。Lark dry-run 不执行远端命令,Explore 重放不重复事件,
这些本地扩展检查不认证 live Lark 采用。回滚只恢复代码导入,不转换 schema、provider
选择或回执;有真实调用的旧源 IO 和历史恢复仍保留。

The retained field adapter preserves blank Python resume values as omission,
timezone normalization, explicit clears and rejection before source mutation.
Invalid supplied conditions use the typed owner's actionable diagnostic. This
Expand Down
3 changes: 2 additions & 1 deletion loopx/capabilities/explore/result_writeback.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
read_canonical_todos_if_promoted,
)
from ...cli_commands.post_writeback import dispatch_committed_cli_post_writeback_hooks
from ...todos import list_goal_todos, update_goal_todo
from ...control_plane.todos.list_readback import list_goal_todos
from ...control_plane.todos.mutation_api import update_goal_todo
from .turn_context import _policy
from .result_log import (
append_explore_result_events,
Expand Down
2 changes: 1 addition & 1 deletion loopx/capabilities/explore/turn_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
)
from ...control_plane.effect_runtime import effect_runtime_result
from ...explore_graph import compact_explore_graph_policy
from ...todos import list_goal_todos
from ...control_plane.todos.list_readback import list_goal_todos
from .result_log import (
build_explore_result_projection,
explore_result_log_path,
Expand Down
2 changes: 1 addition & 1 deletion loopx/capabilities/issue_fix/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
upsert_issue_fix_feasibility_ledger_jsonl,
upsert_issue_fix_pr_lifecycle_ledger_jsonl,
)
from ...todos import add_goal_todo
from ...control_plane.todos.mutation_api import add_goal_todo
from .acceptance_loop import (
build_issue_fix_acceptance_fixture_packet,
build_issue_fix_caller_repo_branch_packet,
Expand Down
3 changes: 2 additions & 1 deletion loopx/capabilities/issue_fix/explore_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
from ...history import load_registry
from ...paths import resolve_runtime_root
from ...rollout_event_log import load_rollout_events, rollout_event_log_path
from ...todos import resolve_todo_state_path, section_bounds, todo_blocks
from ...control_plane.todos.path_resolution import resolve_todo_state_path
from ...control_plane.todos.active_state_editing import section_bounds, todo_blocks
from ..explore.result_log import (
EVENT_KIND_NODE,
FINDING_STATUS_CONFIRMED,
Expand Down
3 changes: 2 additions & 1 deletion loopx/capabilities/issue_fix/pr_gate_reconcile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
normalize_todo_decision_scope,
)
from ...control_plane.todos.todo_semantics import todo_item_task_class
from ...todos import complete_goal_todo, list_goal_todos
from ...control_plane.todos.mutation_api import complete_goal_todo
from ...control_plane.todos.list_readback import list_goal_todos
from .pr_lifecycle import (
TERMINAL_PR_STATES,
build_issue_fix_pr_lifecycle_monitor_packet,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
acquire_task_lease, inspect_task_lease, release_task_lease,
runtime_root_from_registry, TaskLeaseError,
)
from ...todos import add_goal_todo, complete_goal_todo, list_goal_todos, update_goal_todo
from ...control_plane.todos.mutation_api import add_goal_todo, complete_goal_todo, update_goal_todo
from ...control_plane.todos.list_readback import list_goal_todos

ISSUE_FIX_GROUPED_MONITOR_WRITEBACK_SCHEMA_VERSION = "issue_fix_grouped_monitor_writeback_v0"
DEFAULT_ISSUE_FIX_MONITOR_CADENCE = "30m"
Expand Down
2 changes: 1 addition & 1 deletion loopx/capabilities/issue_fix/pr_review_ack.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
load_rollout_events,
rollout_event_log_path,
)
from ...todos import list_goal_todos
from ...control_plane.todos.list_readback import list_goal_todos
from .metadata_preview import normalise_github_issue_reference


Expand Down
2 changes: 1 addition & 1 deletion loopx/capabilities/issue_fix/pr_wait_reconcile.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from ...rollout_event_log import (
append_rollout_event, build_rollout_event, rollout_event_log_path,
)
from ...todos import list_goal_todos
from ...control_plane.todos.list_readback import list_goal_todos
from . import pr_lifecycle
from .pr_lifecycle_rollout import append_pr_merge_rollout_event

Expand Down
2 changes: 1 addition & 1 deletion loopx/capabilities/manager_context/goal_attention.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def read_goal_attention(
registry_path: Path, runtime_root: Path, goal_id: str, quota_packet: Mapping[str, Any],
) -> dict[str, Any]:
"""A current canonical Todo read is independent of stale/absent run history."""
from ...todos import list_goal_todos
from ...control_plane.todos.list_readback import list_goal_todos

try:
listed = list_goal_todos(registry_path=registry_path,
Expand Down
2 changes: 1 addition & 1 deletion loopx/capabilities/periodic_report/pending_intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,7 @@ def _consume_pending_periodic_report_intent(
path=publication_candidate_path,
candidate=publication_candidate,
)
from ...todos import add_goal_todo
from ...control_plane.todos.mutation_api import add_goal_todo

delivery = add_goal_todo(
registry_path=registry_path,
Expand Down
2 changes: 1 addition & 1 deletion loopx/cli_commands/explore.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
)
from ..history import load_registry
from ..paths import resolve_runtime_root
from ..todos import list_goal_todos
from ..control_plane.todos.list_readback import list_goal_todos
from .explore_feishu_commands import (
FEISHU_SINK_EXPLORE_COMMANDS,
handle_explore_feishu_command,
Expand Down
2 changes: 1 addition & 1 deletion loopx/cli_commands/goal_amendment_proposal.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
)
from ..history import load_registry
from ..runtime import validate_goal_id_path_segment
from ..todos import resolve_todo_state_path
from ..control_plane.todos.path_resolution import resolve_todo_state_path

PrintPayload = Callable[
[dict[str, object], str, Callable[[dict[str, object]], str]],
Expand Down
2 changes: 1 addition & 1 deletion loopx/cli_commands/shared_goal_alignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from ..control_plane.goals.shared_goal_alignment import (
project_shared_goal_alignment,
)
from ..todos import resolve_todo_state_path
from ..control_plane.todos.path_resolution import resolve_todo_state_path

PrintPayload = Callable[
[dict[str, object], str, Callable[[dict[str, object]], str]],
Expand Down
6 changes: 3 additions & 3 deletions loopx/cli_commands/todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@
capture_first_party_host_goal_ref,
)
from ..control_plane.goals.source_session_registry_state import exact_goal_ref
from ..todos import (
from ..control_plane.todos.mutation_api import (
add_goal_todo,
archive_completed_todos,
complete_goal_todo,
list_goal_todos,
resolve_todo_state,
supersede_goal_todo,
update_goal_todo,
)
from ..control_plane.todos.list_readback import list_goal_todos
from ..control_plane.todos.path_resolution import resolve_todo_state
from .todo_argument_validation import (
validate_capability_gap_options,
validate_shared_todo_options,
Expand Down
2 changes: 1 addition & 1 deletion loopx/cli_commands/todo_registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from collections.abc import Callable

from ..control_plane.todos.contract import TODO_CONTINUATION_POLICY_VALUES
from ..todos import ARCHIVE_COMPLETED_DEFAULT_MAX_ACTIVE_DONE
from ..control_plane.todos.mutation_api import ARCHIVE_COMPLETED_DEFAULT_MAX_ACTIVE_DONE
from .todo_argument_validation import (
TODO_ACTION_FIELDS,
register_todo_linkage_arguments,
Expand Down
2 changes: 1 addition & 1 deletion loopx/cli_commands/turn_run_once.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
)
from ..quota import spend_quota_slot
from ..state_refresh import refresh_state_run
from ..todos import resolve_todo_state_path
from ..control_plane.todos.path_resolution import resolve_todo_state_path
from .turn_cadence import managed_cadence_start
from .turn_decision import collect_turn_status_payload
from .turn_dsh_host import build_dsh_host_runner
Expand Down
2 changes: 1 addition & 1 deletion loopx/cli_commands/turn_todo_writeback.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pathlib import Path
from typing import Any, Mapping

from ..todos import complete_goal_todo, update_goal_todo
from ..control_plane.todos.mutation_api import complete_goal_todo, update_goal_todo


def write_turn_repair_update(
Expand Down
2 changes: 1 addition & 1 deletion loopx/control_plane/goals/task_planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from ...execution_profile import execution_profile_is_fine_grained
from ...history import load_registry
from ...registry import find_registry_goal
from ...todos import list_goal_todos
from ...control_plane.todos.list_readback import list_goal_todos
from ..todos.todo_semantics import todo_item_is_actionable_open
from ..todos.contract import (
TODO_STATUS_BLOCKED,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from typing import Any, cast

from ...heartbeat_prompt import build_heartbeat_prompt
from ...todos import add_goal_todo, complete_goal_todo
from ...control_plane.todos.mutation_api import add_goal_todo, complete_goal_todo
from ..quota.turn_envelope import quota_action_signature_document
from .doubao_model_behavior_actor import (
ARK_API_KEY_ENV,
Expand Down
4 changes: 2 additions & 2 deletions loopx/control_plane/todos/durable_completion.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""Project the durable completion continuation for the built-in Turn CLI provider.

``loopx turn run-once`` completes the selected Todo through
:func:`loopx.todos.complete_goal_todo` and must report the continuation the Todo
lifecycle durably recorded (``successor``, ``no_followup``, or ``active_goal``)
:func:`loopx.control_plane.todos.mutation_api.complete_goal_todo` and must report
the continuation the Todo lifecycle durably recorded (``successor``, ``no_followup``, or ``active_goal``)
instead of normalizing every completion to ``active_goal``.

Projection reads the persisted Todo lifecycle record only; it never trusts host
Expand Down
4 changes: 2 additions & 2 deletions loopx/control_plane/todos/goal_todo_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

The text is a parameter rather than a file read so a writer that still holds
the state-file lock can project the exact bytes it is about to commit;
``loopx.todos.list_goal_todos`` passes the on-disk text. Everything here is a
projection of those bytes and rollout metadata. Retired event sources are
``loopx.control_plane.todos.list_readback.list_goal_todos`` passes the on-disk
text. Everything here is a projection of those bytes and rollout metadata. Retired event sources are
rejected before any Markdown substitution.
"""

Expand Down
2 changes: 1 addition & 1 deletion loopx/demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .quota import build_quota_should_run
from .state_refresh import refresh_state_run
from .status import collect_status
from .todos import add_goal_todo
from .control_plane.todos.mutation_api import add_goal_todo


DEFAULT_DEMO_PROJECT = Path("/tmp/loopx-demo")
Expand Down
2 changes: 1 addition & 1 deletion loopx/dreaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from .registry import registry_goals
from .runtime import validate_goal_id_path_segment
from .state_refresh import now_local
from .todos import add_goal_todo, update_goal_todo
from .control_plane.todos.mutation_api import add_goal_todo, update_goal_todo

DREAMING_DRY_RUN_SCHEMA_VERSION = "dreaming_dry_run_proposal_v0"
DREAMING_PROPOSAL_SCHEMA_VERSION = "dreaming_proposal_v0"
Expand Down
3 changes: 2 additions & 1 deletion loopx/extensions/lark/presentation/kanban.py
Original file line number Diff line number Diff line change
Expand Up @@ -2195,7 +2195,8 @@ def sync_loopx_todos_to_lark_kanban(
build_issue_fix_outcome_collection_from_domain_state,
)
from ....control_plane.todos.todo_semantics import todo_priority_label
from ....todos import resolve_todo_state_path, section_bounds, todo_blocks
from ....control_plane.todos.path_resolution import resolve_todo_state_path
from ....control_plane.todos.active_state_editing import section_bounds, todo_blocks

resolved_project, resolved_state_file = resolve_todo_state_path(
registry_path=registry_path,
Expand Down
2 changes: 1 addition & 1 deletion loopx/quota.py
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@ def should_run(current_status: dict[str, Any]) -> dict[str, Any]:
# Discovery/selection is an open-work projection, not the committed
# Turn's lifecycle authority. Read the exact bound record, including
# completed history; TS monitor admission owns its interpretation.
from .todos import list_goal_todos
from .control_plane.todos.list_readback import list_goal_todos

if registry_path is not None:
bound_records = list_goal_todos(
Expand Down
4 changes: 2 additions & 2 deletions loopx/semantics/project_registry_io_manifest_v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@
},
{
"site": "loopx/capabilities/issue_fix/explore_projection.py::<module>.project_issue_fix_explore_graph::codec_read:load_registry#1",
"line": 666,
"line": 667,
"column": 16,
"kind": "codec_read",
"api": "load_registry",
Expand All @@ -215,7 +215,7 @@
},
{
"site": "loopx/capabilities/issue_fix/pr_gate_reconcile.py::<module>.reconcile_acknowledged_issue_fix_pr_reviews::codec_read:load_registry#1",
"line": 372,
"line": 373,
"column": 35,
"kind": "codec_read",
"api": "load_registry",
Expand Down
Loading
Loading