Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -4,7 +4,7 @@
- Supersedes / closes: none
- Proposed by: LoopX maintainers
- Date: 2026-08-15
- Last revised: 2026-10-20
- Last revised: 2026-10-21
- Scope: an incremental, replacement-first migration of the LoopX control-plane
core from Python to TypeScript without maintaining two semantic
implementations
Expand Down Expand Up @@ -34,6 +34,17 @@ and follow-up wire contracts, real runtime transport, installed callers and
matched complete SQLite CLI performance must qualify independently before
delivery. Fewer requests alone do not establish a performance gain.

### Global read CLI caller adoption

The existing five global read commands now use the selected parser and shared
dispatcher. `summary_all_registration.py` owns their parser-only registration;
the old registration import remains an alias. Full-parser compatibility callers
use the same handler dispatch, and the old full-CLI branch is removed. Help and
diagnostics retain the existing interface; accepted reads retain registry/runtime
resolution, guards, formatting and typed owners. This adds no domain rule, bridge
operation or data cache. Incremental qualification accounts for pending quota
request-scope adoption separately rather than counting its gain again.

### Product conversations and asynchronous inbox

**Receiver Inbox read transaction (2026-10-19).**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
- 替代 / 关闭:无
- Proposed by:LoopX maintainers
- Date:2026-08-15
- Last revised:2026-10-20
- Last revised:2026-10-21
- Scope:LoopX 控制面核心从 Python 到 TypeScript 的增量、replacement-first
迁移;不长期维护两份语义实现
- Tracking issue:[#3225](https://github.com/loopx-project/loopx/issues/3225)
Expand Down Expand Up @@ -32,6 +32,15 @@ Python builder 和 App 兼容组合逻辑已退役。Python 保留既有 executi
follow-up wire 契约、真实 runtime transport、已安装调用者,以及匹配的完整
SQLite CLI 性能。仅减少请求次数不能证明性能收益。

### 全局读取 CLI 调用者接入

既有五个全局读取命令现在使用按命令 parser 和共享 dispatcher。
`summary_all_registration.py` 统一持有仅解析参数的注册实现,旧注册 import 保留
同一函数的 alias。完整 parser 的兼容调用者复用相同 handler 分发,旧完整 CLI
分支已删除。Help 和诊断保留既有 interface;实际读取保留 registry/runtime 解析、
guard、格式和 typed owner。这不新增领域规则、桥接操作或数据缓存。增量资格验证
单独计入待合入的 quota 请求作用域接入,避免重复计算其收益。

### 产品对话与通用异步 inbox

**接收方 Inbox 读取事务(2026-10-19)。**
Expand Down
11 changes: 0 additions & 11 deletions loopx/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@
handle_review_batch_command,
handle_registry_admin_command,
handle_starter_command,
handle_summary_all_command,
handle_support_control_command,
handle_handoff_mode_command,
handle_task_lease_command,
Expand Down Expand Up @@ -836,16 +835,6 @@ def main(argv: list[str] | None = None) -> int:
if lark_inbox_result is not None:
return lark_inbox_result

summary_all_result = handle_summary_all_command(
args,
registry_path=registry_path,
runtime_root_arg=args.runtime_root,
output_format=output_format,
print_payload=print_payload,
)
if summary_all_result is not None:
return summary_all_result

pr_review_result = handle_pr_review_command(
args,
registry_path=registry_path,
Expand Down
126 changes: 2 additions & 124 deletions loopx/cli_commands/summary_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
build_global_todos_error,
render_global_todos_markdown,
)
from ..paths import default_public_scan_root
from ..summary_all import (
build_global_gates,
build_global_gates_error,
Expand All @@ -25,6 +24,8 @@
render_summary_all_markdown,
)

from .summary_all_registration import register_summary_all_command as register_summary_all_command


PrintPayload = Callable[
[dict[str, object], str, Callable[[dict[str, object]], str]],
Expand All @@ -36,129 +37,6 @@ def _scan_roots(args: argparse.Namespace) -> list[Path]:
return scan_roots or [Path(args.scan_root).expanduser()]


def _add_current_manager_flags(
parser: argparse.ArgumentParser,
*,
agent_help: str,
limit_help: str,
) -> None:
parser.add_argument("--agent-id", help=agent_help)
parser.add_argument("--limit", type=int, default=8, help=limit_help)
parser.add_argument(
"--scan-root",
default=default_public_scan_root(),
help=(
"Public files to scan for obvious private material. "
"Defaults to the LoopX install root."
),
)
parser.add_argument(
"--scan-path",
action="append",
default=[],
help=(
"Specific public file or directory to scan. Repeatable. "
"Overrides --scan-root when set."
),
)


def register_summary_all_command(
subparsers: argparse._SubParsersAction,
add_subcommand_format: Callable[[argparse.ArgumentParser], None],
) -> None:
portfolio = subparsers.add_parser(
"goal-portfolio", help="Read scoped Goal evidence with explicit source coverage."
)
add_subcommand_format(portfolio)
portfolio.add_argument("--manager-view", choices=("portfolio", "todos", "deliveries", "agents"), help="Export an audience-safe manager evidence page from this registry.")
portfolio.add_argument("--query", default="", help="Search registered Agent identities and responsibilities with --manager-view agents.")
portfolio.add_argument("--todo-id", dest="context_todo_id", help="Read an exact permitted Todo with --manager-view todos and one --goal-id.")
portfolio.add_argument("--offset", type=int, default=0)
portfolio.add_argument("--days", type=int, default=1)
portfolio.add_argument("--include-stopped", action="store_true")
portfolio.add_argument(
"--goal-id", action="append", dest="portfolio_goal_ids",
help="Exact registered Goal to include; repeat to narrow scope.",
)
portfolio.add_argument(
"--limit", type=int, default=8,
help="Maximum Goals to read, 1..128; omitted Goals remain in coverage.",
)
portfolio.add_argument(
"--max-age-hours", type=float, default=24,
help="Maximum age of a progress source before it is marked stale.",
)
parser = subparsers.add_parser(
"global-summary",
help=(
"Read a public-safe /loopx-global-summary progress digest; "
"see `loopx slash-commands` for slash help."
),
)
add_subcommand_format(parser)
_add_current_manager_flags(
parser,
agent_help="Registered agent id for agent-lane quota projection.",
limit_help="Maximum items per digest section.",
)
parser.add_argument(
"--time-range",
default="24h",
help="Recent progress window, e.g. 24h or 7d.",
)

gates_parser = subparsers.add_parser(
"global-gates",
help=(
"Read public-safe /loopx-global-gates user/controller decisions; "
"see `loopx slash-commands` for slash help."
),
)
add_subcommand_format(gates_parser)
_add_current_manager_flags(
gates_parser,
agent_help="Registered agent id used to narrow gate projection.",
limit_help="Maximum returned gate count.",
)

todos_parser = subparsers.add_parser(
"global-todos",
help=(
"Read a public-safe current-state todo inbox across visible goals; "
"see `loopx slash-commands` for slash help."
),
)
add_subcommand_format(todos_parser)
_add_current_manager_flags(
todos_parser,
agent_help="Registered agent id used to narrow todo projection.",
limit_help="Maximum returned todo count.",
)

risks_parser = subparsers.add_parser(
"global-risks",
help=(
"Read a public-safe current risk inbox across visible goals; "
"see `loopx slash-commands` for slash help."
),
)
add_subcommand_format(risks_parser)
_add_current_manager_flags(
risks_parser,
agent_help="Registered agent id used to narrow risk projection.",
limit_help="Maximum returned risk count.",
)
risks_parser.add_argument(
"--time-range",
default="24h",
help=(
"Risk request window for protocol compatibility, e.g. 24h or 7d; "
"current risks remain visible."
),
)


def handle_summary_all_command(
args: argparse.Namespace,
*,
Expand Down
135 changes: 135 additions & 0 deletions loopx/cli_commands/summary_all_registration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
from __future__ import annotations

import argparse
from collections.abc import Callable

from ..paths import default_public_scan_root


GLOBAL_READ_COMMANDS = frozenset({
"goal-portfolio", "global-summary", "global-gates", "global-todos", "global-risks",
})


def _add_current_manager_flags(
parser: argparse.ArgumentParser,
*,
agent_help: str,
limit_help: str,
) -> None:
parser.add_argument("--agent-id", help=agent_help)
parser.add_argument("--limit", type=int, default=8, help=limit_help)
parser.add_argument(
"--scan-root",
default=default_public_scan_root(),
help=(
"Public files to scan for obvious private material. "
"Defaults to the LoopX install root."
),
)
parser.add_argument(
"--scan-path",
action="append",
default=[],
help=(
"Specific public file or directory to scan. Repeatable. "
"Overrides --scan-root when set."
),
)



def register_summary_all_command(
subparsers: argparse._SubParsersAction,
add_subcommand_format: Callable[[argparse.ArgumentParser], None],
) -> None:
portfolio = subparsers.add_parser(
"goal-portfolio", help="Read scoped Goal evidence with explicit source coverage."
)
add_subcommand_format(portfolio)
portfolio.add_argument("--manager-view", choices=("portfolio", "todos", "deliveries", "agents"), help="Export an audience-safe manager evidence page from this registry.")
portfolio.add_argument("--query", default="", help="Search registered Agent identities and responsibilities with --manager-view agents.")
portfolio.add_argument("--todo-id", dest="context_todo_id", help="Read an exact permitted Todo with --manager-view todos and one --goal-id.")
portfolio.add_argument("--offset", type=int, default=0)
portfolio.add_argument("--days", type=int, default=1)
portfolio.add_argument("--include-stopped", action="store_true")
portfolio.add_argument(
"--goal-id", action="append", dest="portfolio_goal_ids",
help="Exact registered Goal to include; repeat to narrow scope.",
)
portfolio.add_argument(
"--limit", type=int, default=8,
help="Maximum Goals to read, 1..128; omitted Goals remain in coverage.",
)
portfolio.add_argument(
"--max-age-hours", type=float, default=24,
help="Maximum age of a progress source before it is marked stale.",
)
parser = subparsers.add_parser(
"global-summary",
help=(
"Read a public-safe /loopx-global-summary progress digest; "
"see `loopx slash-commands` for slash help."
),
)
add_subcommand_format(parser)
_add_current_manager_flags(
parser,
agent_help="Registered agent id for agent-lane quota projection.",
limit_help="Maximum items per digest section.",
)
parser.add_argument(
"--time-range",
default="24h",
help="Recent progress window, e.g. 24h or 7d.",
)

gates_parser = subparsers.add_parser(
"global-gates",
help=(
"Read public-safe /loopx-global-gates user/controller decisions; "
"see `loopx slash-commands` for slash help."
),
)
add_subcommand_format(gates_parser)
_add_current_manager_flags(
gates_parser,
agent_help="Registered agent id used to narrow gate projection.",
limit_help="Maximum returned gate count.",
)

todos_parser = subparsers.add_parser(
"global-todos",
help=(
"Read a public-safe current-state todo inbox across visible goals; "
"see `loopx slash-commands` for slash help."
),
)
add_subcommand_format(todos_parser)
_add_current_manager_flags(
todos_parser,
agent_help="Registered agent id used to narrow todo projection.",
limit_help="Maximum returned todo count.",
)

risks_parser = subparsers.add_parser(
"global-risks",
help=(
"Read a public-safe current risk inbox across visible goals; "
"see `loopx slash-commands` for slash help."
),
)
add_subcommand_format(risks_parser)
_add_current_manager_flags(
risks_parser,
agent_help="Registered agent id used to narrow risk projection.",
limit_help="Maximum returned risk count.",
)
risks_parser.add_argument(
"--time-range",
default="24h",
help=(
"Risk request window for protocol compatibility, e.g. 24h or 7d; "
"current risks remain visible."
),
)
Loading
Loading