Skip to content

Commit 3f916ff

Browse files
authored
Merge pull request #4443 from huangruiteng/codex/managed-execution-explicit-selection-20260915
feat(turn): select the managed Turn host explicitly
2 parents c979cf1 + 464262e commit 3f916ff

19 files changed

Lines changed: 2099 additions & 200 deletions

‎docs/integrations/deepseek-harness-connector.md‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,46 @@ continuity or an outer wake/timer. See the adapter README for the home and
131131
classification precedence, plus the hermetic verification smoke
132132
(`examples/loopx-turn-dsh-builtin-host-e2e-smoke.py`).
133133

134+
## Host Selection And Managed Executor Readback
135+
136+
The Turn host is **selected, never inferred**. `dsh` is the shipped default
137+
because it is the managed execution unit the steward drives; `LOOPX_TURN_HOST`
138+
re-points that default, and an explicit `--host` (or `--host-adapter-command-json`)
139+
wins over both. A configured `DEEPSEEK_API_KEY` only *authenticates* the selected
140+
host: discovering a credential never changes where a Turn runs.
141+
142+
Both `loopx turn plan` and `loopx turn run-once` report a `managed_executor`
143+
block, so a caller reads the planned executor instead of inferring it from a
144+
host id:
145+
146+
```json
147+
{
148+
"schema_version": "managed_executor_binding_v0",
149+
"executor": "dsh",
150+
"executor_kind": "managed",
151+
"credential_env": "DEEPSEEK_API_KEY",
152+
"endpoint_env": "DEEPSEEK_BASE_URL",
153+
"operator_credential_bound": true,
154+
"available": true,
155+
"unavailable_reason": null
156+
}
157+
```
158+
159+
`executor_kind` names where the Turn's model work is billed and bounded:
160+
`managed` for a host bound to an operator credential, `individual` for a host
161+
that runs on one person's own CLI login, and `generic` for a caller-supplied
162+
adapter command. `operator_credential_bound` is the narrower claim: it is `true`
163+
only when the operator credential or an explicit injected runner hook is
164+
configured. `available` is `false` only when LoopX can prove the planned host
165+
cannot launch here, and `null` for executors this projection does not probe
166+
rather than an unproven claim. Only the credential variable *name* is reported;
167+
the value is never read back.
168+
169+
`run-once --execute` fails closed on that verdict: status `unavailable`, no host
170+
invocation, no journal write, and no quota spend, with
171+
`dsh_runtime_unavailable` or `operator_credential_unconfigured` naming the
172+
missing fact. `plan` reports the same verdict without refusing.
173+
134174
## Boundaries
135175

136176
- LoopX keeps the durable goal, todo, claim, gate, quota, evidence, and

‎docs/reference/protocols/loopx-turn-v0.md‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,45 @@ terminal failures reach the Turn Journal. The module/subprocess invocation with
9797
`--host generic-cli` remains the compatibility and rollback path.
9898
See [DeepSeek Harness connector](../../integrations/deepseek-harness-connector.md).
9999

100+
### Host Selection
101+
102+
The Turn host is **selected, never inferred**. `loopx turn plan` and
103+
`loopx turn run-once` default to the managed `dsh` host, the operator may
104+
re-point that default with `LOOPX_TURN_HOST` or one explicit `--host`, and a
105+
configured operator credential only *authenticates* the host that was already
106+
selected. Discovering `DEEPSEEK_API_KEY` must never re-point a Turn by itself.
107+
108+
| surface | value |
109+
| --- | --- |
110+
| shipped default host | `dsh` (managed executor) |
111+
| explicit default selector | `LOOPX_TURN_HOST` |
112+
| per-command override | `--host codex-cli\|claude-code\|dsh\|generic-cli` (plan), `codex-cli\|dsh\|generic-cli` (run-once) |
113+
| authenticating credential | `DEEPSEEK_API_KEY`, optional endpoint `DEEPSEEK_BASE_URL` |
114+
115+
This is a default behavior change for the affected lanes: `run-once` moved from
116+
`generic-cli` to `dsh`, and `plan` from `codex-cli` to `dsh`. `--host
117+
generic-cli` and `--host codex-cli` remain the explicit compatibility and
118+
rollback paths, and a machine that wants the former default should set
119+
`LOOPX_TURN_HOST=generic-cli` (or `codex-cli`) once instead of relying on the
120+
ambient environment.
121+
122+
`plan` and `run-once` payloads carry the executor readback `managed_executor`
123+
(`managed_executor_binding_v0`): the executor and its kind (`managed`,
124+
`individual`, `generic`), the credential env var *name* (never its value), the
125+
endpoint env var name, whether the executor is operator-credential-bound, and
126+
whether it can launch here. When it cannot, `available` is `false` and
127+
`unavailable_reason` names the missing fact:
128+
129+
| `unavailable_reason` | meaning | remediation |
130+
| --- | --- | --- |
131+
| `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` |
132+
| `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 |
133+
134+
`run-once --execute` fails closed on that verdict: status `unavailable`, no host
135+
invocation, no Journal write, and no quota slot spend. An explicitly selected
136+
individual host (`--host codex-cli`, `--host claude-code`) is billed to that
137+
individual CLI login and makes no launchability claim (`available: null`).
138+
100139
### Five Questions For Any Agent CLI
101140

102141
Before wiring Trae CLI, Codex CLI, or another host, answer these five questions:

‎examples/control_plane/cli-output-probe-runner.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ def _receipt_row(
108108
"reward_memory_outcome_prompt_revision": (
109109
semantics.reward_memory_outcome_prompt_revision(text)
110110
),
111+
"managed_executor_binding_revision": (
112+
semantics.managed_executor_binding_revision(text)
113+
),
111114
"guided_todo_delta_schema_versions": (
112115
semantics.guided_todo_delta_schema_versions(payload)
113116
if isinstance(payload, dict)

0 commit comments

Comments
 (0)