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 @@ -182,7 +182,7 @@ Audited at `6c3da75ca`. These are current facts, not proposed behavior.
| Attached broker | [`loopx/attached_session.py`](../../../loopx/attached_session.py) implements bind, claim, and complete under `loopx_attached_agent_session_broker_v0`, adapter kind `attached_host_session`, upstream mode `host_broker`, with a bounded claim wait of 1800 seconds, duplicate-safe claim and completion receipts, and per-binding file locks. |
| Runtime fencing | [`loopx/chat_runtime.py`](../../../loopx/chat_runtime.py) never starts a managed adapter for an attached session and fails closed with typed errors such as `attached_session_live_steering_unavailable`, `live_steering_requires_active_turn`, and `live_steering_session_not_attached`. |
| CLI surface | `loopx worker-bridge attached-session-bind`, `-list`, `-claim`, and `-complete` exist in [`loopx/cli_commands/worker_bridge.py`](../../../loopx/cli_commands/worker_bridge.py), documented in the [broker guide](../../integrations/attached-agent-session-broker.md) and the [worker-bridge install contract](../../integrations/worker-bridge-install-contract.md). |
| Existing-session delegation | [`loopx delegation`](../../reference/local-delegation.md#use-an-existing-agent-conversation-through-its-shell) exposes the same explicitly bound work as MCP to an existing shell-capable Agent. It retains the caller conversation and original operation on reconnect; it does not provision an Agent, migrate a host or install an automatic wake policy. |
| Existing-session delegation | [`loopx delegation`](../../reference/local-delegation.md#use-an-existing-agent-conversation-through-its-shell) exposes the same explicitly bound work as MCP to an existing shell-capable Agent. `operations` recovers requester-scoped work without remembered IDs, rechecks acceptance and exposes unavailable items and further pages. Newly tool-equipped Goal Chat consumes the same inventory; resumed native threads keep their original tool schema. It does not provision an Agent, migrate a host or install an automatic wake policy. |
| Focused tests | [`tests/test_attached_session_cli.py`](../../../tests/test_attached_session_cli.py) and `tests/test_chat_codex_home.py::test_attached_session_uses_existing_host_not_managed_adapter` cover bind/claim/complete and the no-managed-adapter fence. |
| Product-level proposal | The [Desktop execution frontends RFC](desktop-execution-frontends-v0.md) owns the Mode A/Mode B product comparison, the connector and event-source orthogonality, and the Desktop non-goals. |
| Host-side loop guidance | [Codex CLI TUI loop](../../product/runtimes/codex-cli/codex-cli-tui-loop.md) documents session-attached automation and resume options for one visible host. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ LoopX 启动,另一种已经属于其他宿主。当绑定没有说明自己
| 挂接 broker | [`loopx/attached_session.py`](../../../loopx/attached_session.py) 在 `loopx_attached_agent_session_broker_v0` 下实现 bind/claim/complete,适配器类型 `attached_host_session`,上游模式 `host_broker`,claim 等待上限 1800 秒,claim 与完成回执去重,并按绑定加文件锁。 |
| 运行时围栏 | [`loopx/chat_runtime.py`](../../../loopx/chat_runtime.py) 绝不为挂接会话启动托管适配器,并以类型化错误失败关闭,例如 `attached_session_live_steering_unavailable`、`live_steering_requires_active_turn`、`live_steering_session_not_attached`。 |
| CLI 面 | `loopx worker-bridge attached-session-bind`、`-list`、`-claim`、`-complete` 存在于 [`loopx/cli_commands/worker_bridge.py`](../../../loopx/cli_commands/worker_bridge.py),并在 [broker 指南](../../integrations/attached-agent-session-broker.md) 与 [worker-bridge 安装契约](../../integrations/worker-bridge-install-contract.md) 中记录。 |
| 原会话委派 | [`loopx delegation`](../../reference/local-delegation.md#use-an-existing-agent-conversation-through-its-shell) 让有 shell 能力的原 Agent 使用与 MCP 相同的显式执行绑定;重连保留原对话和操作身份,不创建 Agent、不迁移宿主,也不安装自动唤醒策略。 |
| 原会话委派 | [`loopx delegation`](../../reference/local-delegation.md#use-an-existing-agent-conversation-through-its-shell) 让有 shell 能力的原 Agent 使用与 MCP 相同的显式执行绑定;`operations` 无需记住 ID 即可找回自身委派,重新核验 accepted,明确单条不可用及剩余分页。新挂载工具的 Goal Chat 复用同一目录,已存在的原生线程恢复时保留原工具 schema;不创建 Agent、不迁移宿主,也不安装自动唤醒策略。 |
| 聚焦测试 | [`tests/test_attached_session_cli.py`](../../../tests/test_attached_session_cli.py) 与 `tests/test_chat_codex_home.py::test_attached_session_uses_existing_host_not_managed_adapter` 覆盖 bind/claim/complete 与"不启动托管适配器"的围栏。 |
| 产品级提案 | [桌面执行前端 RFC](desktop-execution-frontends-v0.zh-CN.md) 拥有 Mode A/Mode B 的产品对比、连接器与事件源正交性,以及桌面端非目标。 |
| 宿主侧循环指引 | [Codex CLI TUI loop](../../product/runtimes/codex-cli/codex-cli-tui-loop.md) 记录了一个可见宿主的会话挂接自动化与恢复选项。 |
Expand Down
8 changes: 5 additions & 3 deletions docs/architecture/rfcs/loopx-overall-roadmap-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,10 @@ These priorities do not change live Goal quota or authorize experiments/cloud re
priorities and attention; a project coordinator is an ordinary registered Agent
accountable for a scoped objective, substantive investigation and synthesis.
Members may coordinate narrower work through the same operations. Local Goal Chat
now reuses scoped evidence, semantic handoff and original-conversation return;
it is not the persistent coordinator or an implicit worker launch. See
reuses scoped evidence, semantic handoff and original-conversation return.
Explicit [Goal Chat LoopX mode](../../reference/goal-chat-continuation.md) now
adds native continuation, authorized member delegation and pause/recovery;
ordinary conversation does not implicitly launch workers. See
[shared capabilities, local path and implementation order](../../reference/project-coordination.md).
This advances R3's local entrypoint without closing R2/G1 or new Lark qualification.

Expand Down Expand Up @@ -282,7 +284,7 @@ sessions, generic Agent creation, dynamic governed work derivation, complete
inbox/queue/steer, authenticated remote authority and packaged frontend/Lark
companion work remain R2/R3/R4/R6 boundaries. Existing Goals are not promoted.

An existing shell-capable coordinator can now use `delegation list/start/read/wait/resume` without replacing its session or loading new MCP tools. The synthetic example's `prepare` path creates only isolated operator bindings; the existing Agent chooses and starts the work. This completes the attached-caller entrypoint over the existing execution owner. Dynamic identity/profile provisioning, unattended lead wakeup and full inbox/queue/steer remain separate R2/R3 requirements; fixed binding readback is not fleet readiness.
An existing shell-capable coordinator uses `delegation list/operations/start/read/wait/resume` without replacing its session. Requester-scoped `operations` recovers durable work after context loss, independently rechecks accepted results and preserves unavailable branches and pagination; enabled MCP and newly tool-equipped Goal Chat use the same read model. Existing native threads retain their tool schema on resume. It starts no work and does not infer overall readiness from a display list. The example's `prepare` still only provisions isolated operator bindings. Next, feed actual execution/acceptance facts into existing R2 readiness, then extend existing registration/runtime configuration for approved identity/profile provisioning and qualify original-request return/lead continuation. Unattended wake, full cross-host inbox/queue/steer and Lark parity remain separate requirements; no G1/G3 promotion follows from this recovery entrypoint.

### R3: Semantic Requests and Automatic Return

Expand Down
7 changes: 4 additions & 3 deletions docs/architecture/rfcs/loopx-overall-roadmap-v0.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,9 @@ R2 的一条依赖必须通过真实 LoopX Agent 间的请求/产物交接完成

**产品职责。** 管家负责所有者跨项目的上下文、取舍和注意力;项目 coordinator 是
对有范围目标、实质调查与综合负责的普通注册 Agent。成员可以用同一操作协调更小
范围的工作。本地 Goal Chat 已复用范围内证据、语义交接和原对话返回;它不等于
持久 coordinator,也不隐式启动 worker。见[共用能力、本地路径与实施顺序](../../reference/project-coordination.md)。
范围的工作。本地 Goal Chat 复用范围内证据、语义交接和原对话返回;显式开启
[LoopX 模式](../../reference/goal-chat-continuation.md)后支持原生持续推进、授权成员
委派和暂停恢复,普通对话不隐式启动 worker。见[共用能力、本地路径与实施顺序](../../reference/project-coordination.md)。
这一进展补齐 R3 本地入口,不关闭 R2/G1,也不新增 Lark 资格声明。

- **入口与 owner:** 现有 session binding、Turn driver、quota/scheduler、manager runtime 配置;复用已有设置 editor,不新建 profile。
Expand Down Expand Up @@ -263,7 +264,7 @@ Todo 完成入口分别执行当前 pinned 检查,accepted 返回读 canonical
完成。长期 attached 会话、通用 Agent 创建、动态受治理工作派生、完整 inbox/queue/steer、
认证远端权威与 packaged frontend/Lark 配套仍归 R2/R3/R4/R6;不晋升已有 Goal。

有 shell 能力的原 coordinator 现在可通过 `delegation list/start/read/wait/resume` 调用已有执行 owner,无需替换会话或重新加载 MCP 工具。合成示例的 `prepare` 只准备隔离绑定,由原 Agent 自行选择并启动工作。这闭合原会话调用入口;动态身份/profile 创建、无人值守唤醒和完整 inbox/queue/steer 仍按 R2/R3 推进,固定绑定读回不等于团队全部就绪。
有 shell 能力的原 coordinator 可通过 `delegation list/operations/start/read/wait/resume` 调用已有执行 owner,无需替换会话。`operations` 从自身持久记录找回上下文丢失前的工作,重新核验 accepted,保留不可用分支与分页;已启用的 MCP 和新挂载工具的 Goal Chat 共用该读模型;已有原生线程恢复时保留原工具 schema。读取不启动工作,也不把展示列表当整体 readiness。合成示例 `prepare` 仍只准备隔离绑定。下一步先将实际执行/验收事实接入已有 R2 readiness,再沿现有注册及 runtime 配置扩展经授权的身份/profile 创建,并验证原请求返回与主力继续推进。无人值守唤醒、完整跨宿主 inbox/queue/steer 和 Lark 等价仍分别验收,不因新增恢复入口晋升 G1/G3。

### R3:语义请求与自动回报

Expand Down
12 changes: 12 additions & 0 deletions docs/reference/goal-chat-continuation.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ executable, workspace or acceptance rule. The same delegation service supports
an authorized member coordinating further members. Results returned as
`accepted` require current canonical task completion and unchanged artifacts.

In newly tool-equipped conversations, `action=operations` recovers the configured sender's
durable work with the same [paged inventory](local-delegation.md#recover-work-without-remembered-operation-ids)
as CLI/MCP. It includes work started outside this conversation. Follow
`next_cursor`, read the original operations and reconcile unavailable entries
before starting replacements. The recent member chips remain conversation
observations, not the complete inventory. Pausing still fences this tool.
Existing native threads retain their original tool schema when resumed; this
change does not replace an unfinished Goal to add a tool operation. Such a
thread keeps its original read/wait operations; a shell-capable caller can use
the CLI recovery entrypoint independently. Tool-schema upgrade remains a
separate session capability.

The composer shows native state, accumulated coordinator usage and last member
observations. **Pause** stops the coordinator, while already delegated members
continue under their independent deadlines and acceptance rules. **Continue**
Expand Down
47 changes: 47 additions & 0 deletions docs/reference/local-delegation.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,53 @@ turn. The conversation remains persistent independently of whether autonomous
LoopX mode is enabled. Current Dashboard/Lark setup is unchanged; those surfaces
keep their existing conversation and runtime owners.

### Recover work without remembered operation ids

After reconnecting or losing conversation context, use the same registered
requester and execution configuration:

```bash
delegate operations --limit 10
# When has_more is true, copy next_cursor from that response:
delegate operations --limit 10 --cursor "$NEXT_CURSOR"
delegate read --operation-id "$ORIGINAL_OPERATION_ID"
```

This reads the existing requester-scoped journal, including work created from
another conversation under that identity. Each item includes its original
operation/request/task identity and current execution readback. Accepted items
are independently rechecked against current canonical completion and artifacts;
the page includes artifact references/hashes, while `read` supplies full content.
One changed binding, corrupt record or invalid artifact yields `unavailable`
for that item and `page_readback_complete: false`; healthy siblings remain
visible. This is a reconciliation case, not permission to dispatch a replacement.
Failure to read the journal itself fails the command instead of returning empty.

Pages contain at most 50 items. `has_more` is independent of page readback
completeness. Accepted-item checks rerun the existing pinned validators; use a
smaller page when those checks are expensive. Inventory is requested on demand,
not added to the dashboard polling loop. The cursor follows stable record addresses, not business priority;
this is a live listing, so restart paging to discover new records inserted before
the cursor. An empty page for one requester says nothing about other members or
whether the Goal is complete. Only explicit `start`/`resume` can launch execution.

Enabled MCP exposes the same operation as `list_delegations`. Newly tool-equipped Goal Chat
uses `loopx_collaboration` with `action=operations`, optional `limit` and `cursor`.
It retains its existing sender/configuration pin and pause fence. Both the lead
and a coordinating member recover their own operations; creation ancestry grants
no access to another requester's journal. No new settings or background polling
are required, and disabling execution tools removes this tool with them.
Already enrolled native Chat threads keep their original tool schema on resume;
they are not replaced to install this new operation. Recovery guidance is part
of the new tool description, not injected into those older threads' shared prompt.

中文:原对话重连后执行 `delegate operations`,不用先记住每个 operation ID。
主力与承担协调的成员各自找回自己的工作,再用原 ID 读取完整结果;需要恢复时
仍显式调用 `resume --execute`。分页回读会重新核验 accepted,单条失效显示
`unavailable`,不能当成失败重派或静默隐藏。`has_more` 表示还有下一页,
`page_readback_complete` 只表示本页是否均成功读取;二者都不代表整个团队已完成。
此入口不创建 Agent、不扩大授权,也不唤醒闲置的 Codex 对话。

## Use the same bindings through MCP

Start the existing stdio server with the explicit opt-in:
Expand Down
16 changes: 14 additions & 2 deletions loopx/chat_loopx_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,22 @@
"Use action=bindings first; start requires binding_id, stable operation_id and brief with "
"schema_version=collaboration_brief_v0, purpose, context, constraints (strings), inputs "
"(relative ref, description, optional sha256), acceptance (strings), return_requirement. "
"Read/wait/resume use the original operation_id. Running is not failure; do not duplicate it.",
"Read/wait/resume use the original operation_id. Running is not failure; do not duplicate it. "
"After context loss, action=operations recovers this requester's durable work. Follow "
"next_cursor for more; unavailable means reconcile, not redispatch.",
"inputSchema": {
"type": "object",
"additionalProperties": False,
"properties": {
"action": {
"type": "string",
"enum": ["bindings", "start", "read", "wait", "resume", "messages"],
"enum": ["bindings", "operations", "start", "read", "wait", "resume", "messages"],
},
"binding_id": {"type": "string"},
"operation_id": {"type": "string"},
"brief": {"type": "object"},
"limit": {"type": "integer", "minimum": 1, "maximum": 50},
"cursor": {"type": "string"},
},
"required": ["action"],
},
Expand Down Expand Up @@ -505,9 +509,15 @@ def dispatch(name, arguments):
"binding_id",
"operation_id",
"brief",
"limit",
"cursor",
}:
raise ValueError("invalid collaboration arguments")
action = arguments.get("action")
if action != "operations" and ("limit" in arguments or "cursor" in arguments):
raise ValueError("pagination is only valid for operations")
if action == "operations" and set(arguments) - {"action", "limit", "cursor"}:
raise ValueError("operations reads a page; use read to select an operation")
operation_id = arguments.get("operation_id", "")
if action == "messages":
rows = [
Expand All @@ -525,6 +535,8 @@ def dispatch(name, arguments):
}
elif action == "bindings":
result = service.directory()
elif action == "operations":
result = service.operations(limit=arguments.get("limit", 20), cursor=arguments.get("cursor"))
elif action == "start":
result = service.start(
arguments.get("binding_id", ""),
Expand Down
Loading
Loading