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
40 changes: 40 additions & 0 deletions docs/integrations/deepseek-harness-connector.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,46 @@ continuity or an outer wake/timer. See the adapter README for the home and
classification precedence, plus the hermetic verification smoke
(`examples/loopx-turn-dsh-builtin-host-e2e-smoke.py`).

## 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.

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
host id:

```json
{
"schema_version": "managed_executor_binding_v0",
"executor": "dsh",
"executor_kind": "managed",
"credential_env": "DEEPSEEK_API_KEY",
"endpoint_env": "DEEPSEEK_BASE_URL",
"operator_credential_bound": true,
"available": true,
"unavailable_reason": null
}
```

`executor_kind` names where the Turn's model work is billed and bounded:
`managed` for a host bound to an operator credential, `individual` for a host
that runs on one person's own CLI login, and `generic` for a caller-supplied
adapter command. `operator_credential_bound` is the narrower claim: it is `true`
only when the operator credential or an explicit injected runner hook is
configured. `available` is `false` only when LoopX can prove the planned host
cannot launch here, and `null` for executors this projection does not probe
rather than an unproven claim. Only the credential variable *name* is reported;
the value is never read back.

`run-once --execute` fails closed on that verdict: status `unavailable`, no host
invocation, no journal write, and no quota spend, with
`dsh_runtime_unavailable` or `operator_credential_unconfigured` naming the
missing fact. `plan` reports the same verdict without refusing.

## Boundaries

- LoopX keeps the durable goal, todo, claim, gate, quota, evidence, and
Expand Down
39 changes: 39 additions & 0 deletions docs/reference/protocols/loopx-turn-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,45 @@ terminal failures reach the Turn Journal. The module/subprocess invocation with
`--host generic-cli` remains the compatibility and rollback path.
See [DeepSeek Harness connector](../../integrations/deepseek-harness-connector.md).

### 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.

| surface | value |
| --- | --- |
| shipped default host | `dsh` (managed 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
ambient environment.

`plan` and `run-once` payloads carry the executor readback `managed_executor`
(`managed_executor_binding_v0`): the executor and its kind (`managed`,
`individual`, `generic`), the credential env var *name* (never its value), the
endpoint env var name, whether the executor is operator-credential-bound, and
whether it can launch here. When it cannot, `available` is `false` and
`unavailable_reason` names the missing fact:

| `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 |

`run-once --execute` fails closed on that verdict: status `unavailable`, no host
invocation, no Journal write, and no quota slot spend. An explicitly selected
individual host (`--host codex-cli`, `--host claude-code`) is billed to that
individual CLI login and makes no launchability claim (`available: null`).

### Five Questions For Any Agent CLI

Before wiring Trae CLI, Codex CLI, or another host, answer these five questions:
Expand Down
3 changes: 3 additions & 0 deletions examples/control_plane/cli-output-probe-runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ def _receipt_row(
"reward_memory_outcome_prompt_revision": (
semantics.reward_memory_outcome_prompt_revision(text)
),
"managed_executor_binding_revision": (
semantics.managed_executor_binding_revision(text)
),
"guided_todo_delta_schema_versions": (
semantics.guided_todo_delta_schema_versions(payload)
if isinstance(payload, dict)
Expand Down
Loading