Skip to content
Closed
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
30 changes: 18 additions & 12 deletions docs/architecture/rfcs/harness-selection-dsh-pi-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,17 @@ an endpoint from the operator environment (`DEEPSEEK_BASE_URL`) and a credential
from the operator environment (`DEEPSEEK_API_KEY`).

LoopX **selects** the default host for bounded managed Turns and never infers it
(`loopx/control_plane/turn_driver/host_binding.py`): the shipped default is `dsh`,
`LOOPX_TURN_HOST` re-points it, and an explicit `--host` wins over both. The
operator credential is not a selection input. This distinction is the whole
point of the binding: discovering a key is not a decision to change where work
runs, and a surface that resolves its host from the environment makes a chosen
configuration indistinguishable from an incidental one. A lane selected onto the
DSH host therefore never depends on an individual developer's CLI subscription
being available, funded, or logged in.
from a launch-time surprise (`loopx/control_plane/turn_driver/host_binding.py`):
an explicit `--host` or `LOOPX_TURN_HOST` always wins, and only when neither is
configured is the shipped default resolved from the operator's own credential
facts -- the managed `dsh` host when a credential exists, and the individual
`codex-cli` host when one does not, because an unauthenticated managed host
would refuse to run. The distinction that matters is between a *default* and a
*decision*: a credential may resolve a default that would otherwise have to pick
a host at random, but it never re-points a host the operator already selected.
A lane resolved onto the DSH host therefore never depends on an individual
developer's CLI subscription being available, funded, or logged in, and a lane
without an operator credential never silently borrows one either.

The steward channel is a **different** surface with a different default. Its
shipped executor is `codex`, because that is the only transport that can hold an
Expand All @@ -89,10 +92,13 @@ steward onto an operator model while the executor stays on the CLI endpoint.

Evidence for this binding, separated by source:

- repository-covered without any provider call: the shipped default is `dsh`, an
explicit `LOOPX_TURN_HOST` re-points it, an explicit `--host` still wins, and a
configured credential changes none of those selections (tests in PR #4443, not
yet on `main`);
- repository-covered without any provider call: with an operator credential the
shipped default is `dsh` and without one it is `codex-cli`, an explicit
`LOOPX_TURN_HOST` re-points either default, and an explicit `--host` still
wins over all of them (`tests/test_turn_default_host_binding.py`,
`tests/test_turn_managed_executor_binding.py`,
`examples/loopx-turn-managed-executor-binding-smoke.py`,
`examples/loopx-turn-managed-default-flow-smoke.py`);
- local live qualification with the real SDK and runtime
(`deepseek-harness-sdk==0.1.5rc1`, the pin PR #4420 proposes; `main` still
pins `0.1.2a3` and the same pair also passed there): the in-process
Expand Down
25 changes: 15 additions & 10 deletions docs/architecture/rfcs/harness-selection-dsh-pi-v0.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ opt-in,不因前者被晋级,仍需本文 C0、C1、开销、保留与 Mode

| 角色 | 来源 | 当前选型 | 晋级门槛 |
| --- | --- | --- | --- |
| 默认托管执行宿主 | LoopX Turn 加 `dsh` 宿主适配器,并绑定到运维方提供的模型端点 | 出货默认值:托管有界 Turn 走 `dsh`,与环境无关;`LOOPX_TURN_HOST` 可改指,显式 `--host` 优先;在托管栈中(PR #4443),尚未进入 `main` | 保持类型化 host request/result、独立验证与凭据归属运维方的边界;没有同等或更强的契约不替换 |
| 默认托管执行宿主 | LoopX Turn 加 `dsh` 宿主适配器,并绑定到运维方提供的模型端点 | 出货默认值:配置了运维方凭据时托管有界 Turn 走 `dsh`,没有凭据时走个体 `codex-cli`;显式 `LOOPX_TURN_HOST` 可改指,显式 `--host` 优先 | 保持类型化 host request/result、独立验证与凭据归属运维方的边界;没有同等或更强的契约不替换 |
| 管家通道执行器 | 管家回答所依赖的交互式 Chat 传输 | 出货默认值:`codex`;`LOOPX_MANAGER_ENDPOINT` 可改指;在托管栈中(PR #4446),尚未进入 `main` | 托管宿主具备交互式 Chat 传输,管家通道才能选择它;凭据的存在从不是晋级信号 |
| 受支持的替代 Turn 宿主 | LoopX Turn 加 `codex-cli` 适配器 | 可显式选择;它属于 `individual` 执行器类型,账落在某个人的 CLI 登录上 | 任何托管通道都不得静默依赖某个人的 CLI 订阅;个人通道必须被显式选择,而不是默认走到 |
| L1 事件源与会话归属 runtime 候选 | DSH | opt-in,未晋级;有界 Turn 宿主角色见上一行默认值 | 本文 C0、C1、开销、保留与 Mode B 各行被真实执行并通过评审 |
Expand All @@ -60,12 +60,14 @@ DSH 绑定是 DSH Turn 宿主 + provider `deepseek-official` + 模型 `deepseek-
(DeepSeek V4.1 Flash),端点取自运维方环境(`DEEPSEEK_BASE_URL`),凭据取自
运维方环境(`DEEPSEEK_API_KEY`)。

LoopX **选择**托管有界 Turn 的默认宿主,而从不由环境推断
(`loopx/control_plane/turn_driver/host_binding.py`):出货默认值是 `dsh`,
`LOOPX_TURN_HOST` 可改指,显式 `--host` 优先于两者。operator 凭据不是选型输入。
这个区分正是该绑定的意义:发现一把 key 不等于决定换运行位置;一个按环境解析宿主的
面,会让"选定的配置"和"偶然生效的配置"无法区分。因此被选到 DSH 宿主的通道不会依赖
某个开发者本机 CLI 订阅是否可用、是否还有额度或是否已登录。
LoopX **选择**托管有界 Turn 的默认宿主,而从不由启动时的意外推断
(`loopx/control_plane/turn_driver/host_binding.py`):显式 `--host` 或
`LOOPX_TURN_HOST` 始终优先;两者都没配置时,出货默认值由运维方自己的凭据事实解析
——配置了凭据就是托管 `dsh` 宿主,没有凭据则是个体 `codex-cli` 宿主,因为无法认证的
托管宿主只会拒绝运行。真正需要区分的是**默认值**与**决定**:凭据可以解析一个本来
无从选择的默认值,但它永远不会改指运维方已经显式选定的宿主。因此解析到 DSH 宿主的
通道不会依赖某个开发者本机 CLI 订阅是否可用、是否还有额度或是否已登录;没有运维方
凭据的通道也不会悄悄借用别人的订阅。

管家通道是**另一个**面,默认值也不同。它的出货执行器是 `codex`,因为这是今天唯一
能承载交互式管家会话的传输;`LOOPX_MANAGER_ENDPOINT` 可改指,凭据不能改指。它的
Expand All @@ -74,9 +76,12 @@ CLI 的情况下把管家悄悄换成 operator 模型。

该绑定的证据按来源区分:

- 仓库覆盖、无需任何 provider 调用:出货默认值是 `dsh`,显式 `LOOPX_TURN_HOST`
可改指,显式 `--host` 仍然优先,且配置凭据不改变以上任何一项选择
(PR #4443 的测试,尚未进入 `main`);
- 仓库覆盖、无需任何 provider 调用:配置了运维方凭据时出货默认值是 `dsh`,没有时
是 `codex-cli`;显式 `LOOPX_TURN_HOST` 可改指任一默认值,显式 `--host` 优先于
全部(`tests/test_turn_default_host_binding.py`、
`tests/test_turn_managed_executor_binding.py`、
`examples/loopx-turn-managed-executor-binding-smoke.py`、
`examples/loopx-turn-managed-default-flow-smoke.py`);
- 本地真实验证:在真实 SDK 与 runtime(`deepseek-harness-sdk==0.1.5rc1`,即 PR
#4420 提出的固定版本;`main` 今天仍固定在 `0.1.2a3`,同一对路径在那里也通过)下,
进程内 `--host dsh` 路径与 `generic-cli` 子进程路径均通过;
Expand Down
12 changes: 7 additions & 5 deletions docs/integrations/deepseek-harness-connector.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,13 @@ classification precedence, plus the hermetic verification smoke

## Host Selection And Managed Executor Readback

The Turn host is **selected, never inferred**. `dsh` is the shipped default
because it is the managed execution unit the steward drives; `LOOPX_TURN_HOST`
re-points that default, and an explicit `--host` (or `--host-adapter-command-json`)
wins over both. A configured `DEEPSEEK_API_KEY` only *authenticates* the selected
host: discovering a credential never changes where a Turn runs.
The Turn host is **selected, never inferred from an incidental environment**. An
explicit `--host` (or `--host-adapter-command-json`) or `LOOPX_TURN_HOST` always
wins. With neither configured, the shipped default is resolved from the
operator's own credential facts: `dsh` is the default when `DEEPSEEK_API_KEY` is
configured, because it is the managed execution unit the steward drives and that
credential authenticates it, and `codex-cli` is the default when no credential is
configured, because an unauthenticated managed host would refuse to run.

Both `loopx turn plan` and `loopx turn run-once` report a `managed_executor`
block, so a caller reads the planned executor instead of inferring it from a
Expand Down
33 changes: 21 additions & 12 deletions docs/reference/protocols/loopx-turn-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,33 @@ See [DeepSeek Harness connector](../../integrations/deepseek-harness-connector.m

### Host Selection

The Turn host is **selected, never inferred**. `loopx turn plan` and
`loopx turn run-once` default to the managed `dsh` host, the operator may
re-point that default with `LOOPX_TURN_HOST` or one explicit `--host`, and a
configured operator credential only *authenticates* the host that was already
selected. Discovering `DEEPSEEK_API_KEY` must never re-point a Turn by itself.
The Turn host is **selected, never inferred from an incidental environment**. An
explicit `--host` or `LOOPX_TURN_HOST` always wins; only when the operator
configured neither is the shipped default resolved from the operator's own
credential facts:

- operator credential configured: the default host is the managed `dsh`
executor, which that credential authenticates;
- no operator credential configured: the default host is the individual
`codex-cli` executor, because a managed host nothing can authenticate would
otherwise refuse to run at all.

| surface | value |
| --- | --- |
| shipped default host | `dsh` (managed executor) |
| shipped default host, credential configured | `dsh` (managed executor) |
| shipped default host, no credential | `codex-cli` (individual executor) |
| explicit default selector | `LOOPX_TURN_HOST` |
| per-command override | `--host codex-cli\|claude-code\|dsh\|generic-cli` (plan), `codex-cli\|dsh\|generic-cli` (run-once) |
| authenticating credential | `DEEPSEEK_API_KEY`, optional endpoint `DEEPSEEK_BASE_URL` |

This is a default behavior change for the affected lanes: `run-once` moved from
`generic-cli` to `dsh`, and `plan` from `codex-cli` to `dsh`. `--host
generic-cli` and `--host codex-cli` remain the explicit compatibility and
rollback paths, and a machine that wants the former default should set
`LOOPX_TURN_HOST=generic-cli` (or `codex-cli`) once instead of relying on the
This is a default behavior change for the affected lanes. Both `plan` and
`run-once` previously defaulted to `dsh` regardless of the credential, so a lane
without one failed closed on `operator_credential_unconfigured`; the default is
now credential-resolved and a lane without a credential keeps running on the
individual CLI host. `--host dsh` remains the explicit managed path and still
fails closed with the same typed reason when nothing can authenticate it,
`--host generic-cli` remains the compatibility path, and a machine that wants
one fixed host should set `LOOPX_TURN_HOST` once instead of relying on the
ambient environment.

`plan` and `run-once` payloads carry the executor readback `managed_executor`
Expand All @@ -129,7 +138,7 @@ whether it can launch here. When it cannot, `available` is `false` and
| `unavailable_reason` | meaning | remediation |
| --- | --- | --- |
| `dsh_runtime_unavailable` | the DeepSeek Harness runtime is not importable and no explicit runner hook was supplied | install the released runtime, pass its runner hook, or select `--host codex-cli` |
| `operator_credential_unconfigured` | the managed host is selected but no operator credential or runner hook would authenticate it | set `DEEPSEEK_API_KEY`, or select `--host codex-cli` explicitly |
| `operator_credential_unconfigured` | the managed host is selected but no operator credential or runner hook would authenticate it | set `DEEPSEEK_API_KEY`, or select `--host codex-cli` explicitly; the shipped default already resolves to `codex-cli` until a credential exists |

`run-once --execute` fails closed on that verdict: status `unavailable`, no host
invocation, no Journal write, and no quota slot spend. An explicitly selected
Expand Down
32 changes: 17 additions & 15 deletions examples/loopx-turn-managed-default-flow-smoke.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
#!/usr/bin/env python3
"""Qualify the explicit operator default flow for one bounded managed Turn.
"""Qualify the credential-resolved default flow for one bounded managed Turn.

The shipped operator rule is *selection first*: the default host is the managed
``dsh`` executor by product decision, the operator credential only authenticates
that selection, and discovering a credential never re-points a Turn. That rule
The shipped operator rule is *explicit selection first*: an explicit ``--host``
or ``LOOPX_TURN_HOST`` is honoured, and the shipped default is resolved from the
operator's own credential facts -- a configured operator credential runs the
managed ``dsh`` host on that credential, and its absence runs the individual
``codex-cli`` host instead of a managed host nothing can authenticate. That rule
is only usable if the *default* command (no explicit ``--host``) actually starts
the managed Turn and reports what ran.
the resolved host and reports what ran.

This smoke is hermetic: a local mock OpenAI-compatible SSE server stands in for
the model endpoint, so no operator key and no individual CLI subscription is
consumed. It proves, through the public CLI only:

1. no credential: the default host is still ``dsh``, reported as an unauthenticated
managed executor with the typed ``operator_credential_unconfigured`` reason;
2. credential: the same default host reports its credential environment, its
billing boundary, and its launchability before any work runs;
1. no credential: the default host is the individual ``codex-cli`` executor, so
the default flow still runs here and claims no managed credential;
2. credential: the default host resolves to the managed ``dsh`` executor and
reports its credential environment, its billing boundary, and its
launchability before any work runs;
3. credential: ``turn run-once`` without ``--host`` starts the real dsh runtime,
commits one validated Turn, and reports the mode/executor/status readback;
4. credential but an unavailable managed runtime: the same default flow fails
Expand Down Expand Up @@ -570,16 +573,15 @@ def log_message(self, _format: str, *args: object) -> None:
effects = summary["managed_default_run"]["effects"] or {}
ok = (
unbound_default_exit == 0
and summary["default_without_credential"]["host_kind"] == "dsh"
and summary["default_without_credential"]["host_kind"] == "codex-cli"
and summary["default_without_credential"]["execution_mode"]
== "isolated-headless"
== "interactive-visible"
and summary["default_without_credential"]["executor_kind"]
== EXECUTOR_KIND_MANAGED
== EXECUTOR_KIND_INDIVIDUAL
and summary["default_without_credential"]["credential_env"] is None
and summary["default_without_credential"]["operator_credential_bound"] is False
and summary["default_without_credential"]["available"] is False
and summary["default_without_credential"]["unavailable_reason"]
== OPERATOR_CREDENTIAL_UNCONFIGURED
and summary["default_without_credential"]["available"] is None
and summary["default_without_credential"]["unavailable_reason"] is None
and individual_exit == 0
and summary["explicit_individual_host"]["host_kind"] == "codex-cli"
and summary["explicit_individual_host"]["executor_kind"]
Expand Down
28 changes: 16 additions & 12 deletions examples/loopx-turn-managed-executor-binding-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,21 +243,23 @@ def main() -> int:
root = Path(directory)
project, runtime, workspace, registry = _write_fixture(root)

# 1. The shipped default is the managed host, and without the operator
# credential it refuses instead of borrowing a personal login.
# 1. Without the operator credential the shipped default is the
# individual CLI host, so a default plan still runs here instead of
# gating on a managed host nothing can authenticate.
with _operator_credential(None), _harness_runtime(available=True):
exit_code, payload = _run_cli(_plan_command(registry, runtime, project))
assert exit_code == 0, payload
assert payload["host"]["kind"] == "dsh", payload
unbound = _managed_binding(payload)
assert unbound["operator_credential_bound"] is False, unbound
assert unbound["available"] is False, unbound
assert unbound["unavailable_reason"] == OPERATOR_CREDENTIAL_UNCONFIGURED, (
unbound
assert payload["host"]["kind"] == "codex-cli", payload
uncredentialed_default = payload["managed_executor"]
assert (
uncredentialed_default["executor_kind"] == EXECUTOR_KIND_INDIVIDUAL
), uncredentialed_default
assert uncredentialed_default["operator_credential_bound"] is False, (
uncredentialed_default
)
assert uncredentialed_default["available"] is None, uncredentialed_default

# 2. Configuring the credential authenticates that same selection; it
# does not get to pick a different host.
# 2. The credential resolves and authenticates the managed default.
with (
_operator_credential("sk-fixture-operator"),
_harness_runtime(available=True),
Expand Down Expand Up @@ -298,8 +300,9 @@ def main() -> int:
assert individual["available"] is None, individual
assert individual["operator_credential_bound"] is False, individual

# 5. Executing the unauthenticated managed default fails closed: typed
# status, no host invocation, no journal, and no quota slot spend.
# 5. Executing an explicitly selected managed host without the
# credential fails closed: typed status, no host invocation, no
# journal, and no quota slot spend.
with _operator_credential(None), _harness_runtime(available=True):
exit_code, refusal = _run_cli(
_run_once_command(
Expand All @@ -308,6 +311,7 @@ def main() -> int:
project,
workspace,
instance="managed-executor-unauthenticated",
host="dsh",
)
)
assert exit_code == 1, refusal
Expand Down
2 changes: 1 addition & 1 deletion loopx/cli_commands/turn_registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def register_turn_commands(
# The default host and the default execution mode are one decision: the
# selected managed host runs bounded headless Turns, so pairing it with a
# visible interactive mode would produce a default plan that cannot be
# scheduled. The mode follows the *selected* host, never the environment.
# scheduled. The mode follows the *selected* host, whatever resolved it.
resolved_default_host = resolve_default_turn_host()
resolved_default_execution_mode = (
"isolated-headless"
Expand Down
Loading
Loading