T-QO8E-new-hosts-claude-codex-cursor-under-lib-services-host-hosts
State: closed/done · Impact: medium · Complexity: large
New host implementations under lib/services/host/hosts/: claude
(Claude Code, via CLI or the desktop app’s launch-with-prompt entry),
codex (the Codex CLI or app), cursor (the cursor-agent CLI, or
opening the worktree in Cursor with the prompt). Each implements the
session/terminal parts with an available() probe.
Approach
Section titled “Approach”Three new hosts under solutions/ontological/lib/services/host/hosts/, each
implementing session ONLY (not terminal — Host extends Partial<HostParts>
already supports a partial host; arbitrary command-running isn’t these hosts’
job). Each is ENGINE-NATIVE: it hardcodes its own CLI and ignores
req.engine entirely — terminal/orca/cmux stay the WRAPPER hosts that
pick an AgentEngine’s binary via engineArgv. AgentEngine
(host/engines.ts) deliberately stays 'claude' | 'codex' — 'cursor' is a
HostName, never an AgentEngine member (see that file’s doc comment for
why).
The three new host modules share the same attribute set — available() probe,
session() mechanism, hostSessionId strategy, verification status:
| Host | available() | session() mechanism | hostSessionId strategy | Verified? |
|---|---|---|---|---|
hosts/claude.ts | onPath('claude') (the exported helper from hosts/terminal.ts) | claude --bg -n <title> <prompt> via spawnRunner('claude').run([...], {cwd, timeoutMs: 30_000}) — the command seam’s sync door, same shape as hosts/orca.ts/cmux.ts, since --bg backgrounds and returns quickly on its own | Best-effort parse from stdout; falls back to null rather than guessing wrong, never fails the launch on an unparsable id | UNVERIFIED — no local claude install to observe the real --bg stdout format |
hosts/codex.ts | onPath('codex') | codex has no background/detach flag (confirmed against codex --help/codex exec --help/codex resume --help), so this host detaches it itself: spawnRunnerAsync('codex').run([req.prompt], {cwd}), fired but NOT awaited (the promise only settles once the codex session ends) — the command seam’s long-lived-process door | A SHORT bounded, purely SYNCHRONOUS poll (up to ~10 reads, ~200ms apart via spawnRunner('sh').run(['-c','sleep …']), capped at ~2s) of ~/.codex/session_index.jsonl for the newest entry stamped after launch — best-effort and race-prone under concurrent codex launches, a documented known limitation rather than something solved here | CLI flags confirmed via --help; the session-index poll itself is not live-verified against a real run |
hosts/cursor.ts | True when cursor-agent OR (degraded) cursor (the editor’s own CLI shim) is on PATH — binary selection is injectable for tests | cursor-agent present: detached spawnRunnerAsync launch, same reasoning as codex. Only cursor present: cursor <cwd> opens the worktree folder in the editor but delivers no prompt — there is no documented cursor flag to seed the agent panel, a deliberate, accepted limitation, not a bug to route around with a clipboard/temp-file trick | Always null (no known local session-index file for cursor-agent, unlike codex — a documented gap pending live verification; real attach support may need cursor-agent ls/--resume, wired in once session attach exists, T-QMGC) | UNVERIFIED — cursor-agent is not installed on any development machine used for this task; everything here is from published Cursor CLI docs (cursor.com/docs/cli), not a live run |
Contract change these hosts required: HostParts.session’s return type
changed from a raw number to { exitCode: number; hostSessionId: string | null } (contract.ts) — a hard cutover across all 3 pre-existing hosts
(terminal/orca/cmux, which now return { exitCode, hostSessionId: null })
and both launchInteractive callers (session/ops/launch.ts,
pr/ops/review.ts). HostName also gained the three new members;
HOST_NAMES and a new HostNameSchema (z.enum over it) are the one
place that enumeration lives now, consumed by lib/config/load.ts’s
host.default/pr_review.host/orchestrator.workflows.<name>.host
fields and session launch’s/pr review’s own --host flags instead of
each hand-duplicating the literal union.
| Area | Note |
|---|---|
solutions/ontological/lib/services/host/hosts/claude.ts | New engine-native claude host (--bg, best-effort id parsing) |
solutions/ontological/lib/services/host/hosts/codex.ts | New engine-native codex host (detached spawn, session-index poll) |
solutions/ontological/lib/services/host/hosts/cursor.ts | New engine-native cursor host (cursor-agent / degraded cursor-editor fallback) |
solutions/ontological/lib/services/host/contract.ts | HostName +3, HostNameSchema, HostParts.session return-shape cutover |
solutions/ontological/lib/services/host/index.ts | hostRegistry() registers the three new hosts |
solutions/ontological/lib/services/session/ops/launch.ts, solutions/ontological/lib/services/pr/ops/review.ts | launchInteractive callers updated for the {exitCode, hostSessionId} shape |
solutions/ontological/lib/config/load.ts | host.default/pr_review.host/orchestrator.workflows.<name>.host consolidated onto HostNameSchema |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Each of claude/codex/cursor exports
available()and returns true only when that tool is actually present (proven via an injectable probe in unit tests — no real installed-tool dependency;cursor-agentin particular is not installed anywhere this task was implemented or tested). - AC-2: A
session()launch against each produces the argv/spawn shape documented above, proven with the command-seam’s injectableCommandRunner/AsyncCommandRunnerfakes (hosts/tests/hosts.test.ts) — NOT a live smoke test against a real installed tool, which the task’s testing constraints explicitly rule out (no real interactiveclaude/codex/cursor-agentprocess may be launched by a test).
Out of scope
Section titled “Out of scope”- Wiring
hostSessionIdinto.sdlc/sessions/<id>/record.jsonor asession attach/session listsurface — that isT-QMGC’s job. This task only makes the id available onsession()’s return value. - Verifying
claude --bg’s real stdout shape or installingcursor-agentto confirm its real CLI surface — both documented as UNVERIFIED, to be confirmed live in a follow-up once those tools are available.
Dependencies
Section titled “Dependencies”- none