Files
orca/notes/host-model-tasks-automations-plan.html
T
2026-06-12 18:24:21 -07:00

1384 lines
47 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Orca Host Model: Tasks, Automations, Provider Identity</title>
<style>
:root {
color-scheme: dark;
--background: #111111;
--foreground: #f4f4f5;
--card: #161618;
--popover: #18181b;
--muted: #1d1d20;
--muted-foreground: #a1a1aa;
--border: #2a2a2f;
--accent: #242429;
--accent-foreground: #fafafa;
--input: #18181b;
--ring: #d4d4d8;
--sidebar: #141416;
--sidebar-accent: #232327;
--sidebar-border: #2b2b30;
--success: #7dd3a7;
--warning: #f4c56a;
--danger: #f08c8c;
--info: #9dbcfb;
}
* {
box-sizing: border-box;
}
html {
background: var(--background);
}
body {
margin: 0;
background: var(--background);
color: var(--foreground);
font-family:
Geist,
ui-sans-serif,
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif;
letter-spacing: 0.01em;
line-height: 1.5;
}
main {
max-width: 1240px;
margin: 0 auto;
padding: 42px 24px 72px;
}
header {
border-bottom: 1px solid var(--border);
padding-bottom: 28px;
margin-bottom: 30px;
}
h1,
h2,
h3,
h4 {
letter-spacing: 0;
line-height: 1.15;
}
h1 {
margin: 8px 0 12px;
font-size: 34px;
}
h2 {
margin: 34px 0 14px;
font-size: 22px;
}
h3 {
margin: 22px 0 10px;
font-size: 16px;
}
h4 {
margin: 0 0 8px;
font-size: 13px;
}
p {
margin: 0 0 12px;
}
ul {
margin: 8px 0 0;
padding-left: 18px;
}
li {
margin: 6px 0;
}
code {
border: 1px solid var(--border);
border-radius: 6px;
background: var(--muted);
color: var(--foreground);
font-family:
SFMono-Regular,
Consolas,
"Liberation Mono",
monospace;
font-size: 0.92em;
padding: 1px 5px;
}
button,
input,
select {
font: inherit;
}
.eyebrow {
color: var(--muted-foreground);
font-size: 11px;
font-weight: 650;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.lede {
max-width: 900px;
color: var(--muted-foreground);
font-size: 14px;
}
.grid {
display: grid;
gap: 12px;
}
.grid-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.panel {
border: 1px solid var(--border);
border-radius: 8px;
background: var(--card);
padding: 16px;
}
.panel.compact {
padding: 12px;
}
.callout {
border: 1px solid color-mix(in srgb, var(--info) 28%, var(--border));
border-radius: 8px;
background: color-mix(in srgb, var(--info) 8%, var(--card));
padding: 14px 16px;
}
.muted {
color: var(--muted-foreground);
}
.tiny {
color: var(--muted-foreground);
font-size: 12px;
}
.status {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--muted-foreground);
font-size: 12px;
}
.dot {
width: 7px;
height: 7px;
border-radius: 999px;
background: var(--muted-foreground);
}
.dot.online {
background: var(--success);
}
.dot.warning {
background: var(--warning);
}
.dot.offline {
background: #73737c;
}
.tag-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.tag {
display: inline-flex;
align-items: center;
gap: 6px;
min-height: 24px;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--muted);
color: var(--muted-foreground);
padding: 2px 9px;
font-size: 12px;
}
.tag.strong {
color: var(--foreground);
background: var(--accent);
}
.checklist {
display: grid;
gap: 8px;
margin-top: 10px;
}
.check-row {
display: grid;
grid-template-columns: 22px minmax(0, 1fr) auto;
gap: 10px;
align-items: start;
border: 1px solid var(--border);
border-radius: 8px;
background: color-mix(in srgb, var(--card) 86%, var(--muted));
padding: 10px 12px;
}
.box {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
margin-top: 2px;
border: 1px solid var(--border);
border-radius: 4px;
color: var(--success);
font-size: 12px;
}
.priority {
color: var(--muted-foreground);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.mock-shell {
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--background);
}
.mock-titlebar {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 38px;
border-bottom: 1px solid var(--border);
background: #151518;
padding: 0 12px;
}
.window-dots {
display: flex;
gap: 6px;
}
.window-dots span {
width: 10px;
height: 10px;
border-radius: 999px;
background: #3a3a40;
}
.mock-app {
display: grid;
grid-template-columns: 238px minmax(0, 1fr);
min-height: 520px;
}
.sidebar {
border-right: 1px solid var(--sidebar-border);
background: var(--sidebar);
padding: 12px;
}
.sidebar-header,
.side-section-title {
color: var(--muted-foreground);
font-size: 11px;
font-weight: 650;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.side-section-title {
margin: 16px 6px 7px;
}
.side-row {
display: grid;
grid-template-columns: 18px minmax(0, 1fr) auto;
gap: 8px;
align-items: center;
min-height: 32px;
border-radius: 6px;
padding: 6px 8px;
color: var(--muted-foreground);
font-size: 13px;
}
.side-row.current,
.side-row:hover {
background: var(--sidebar-accent);
color: var(--foreground);
}
.side-count {
color: var(--muted-foreground);
font-size: 11px;
}
.content {
min-width: 0;
background: var(--background);
}
.toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
border-bottom: 1px solid var(--border);
padding: 12px 16px;
}
.toolbar-main {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.tabs {
display: inline-flex;
align-items: center;
border: 1px solid var(--border);
border-radius: 7px;
background: var(--muted);
padding: 2px;
}
.tab {
min-height: 26px;
border: 0;
border-radius: 5px;
background: transparent;
color: var(--muted-foreground);
padding: 0 10px;
font-size: 12px;
cursor: pointer;
}
.tab.active {
background: var(--accent);
color: var(--foreground);
}
.select-like,
.button-like {
display: inline-flex;
align-items: center;
justify-content: space-between;
gap: 8px;
min-height: 32px;
border: 1px solid var(--border);
border-radius: 7px;
background: var(--input);
color: var(--foreground);
padding: 0 10px;
font-size: 12px;
}
.button-like {
background: var(--accent);
cursor: pointer;
}
.list {
padding: 10px 14px 14px;
}
.task-row,
.automation-row,
.settings-row {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
gap: 12px;
align-items: center;
border-bottom: 1px solid color-mix(in srgb, var(--border) 75%, transparent);
padding: 12px 2px;
}
.task-title,
.automation-title {
overflow: hidden;
color: var(--foreground);
font-size: 13px;
text-overflow: ellipsis;
white-space: nowrap;
}
.meta-line {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 4px;
color: var(--muted-foreground);
font-size: 12px;
}
.identity-pill {
display: inline-flex;
align-items: center;
gap: 6px;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--muted);
color: var(--muted-foreground);
padding: 2px 8px;
font-size: 11px;
white-space: nowrap;
}
.split {
display: grid;
grid-template-columns: minmax(0, 1.1fr) minmax(280px, 0.9fr);
gap: 12px;
padding: 14px;
}
.form {
display: grid;
gap: 12px;
}
.field {
display: grid;
gap: 6px;
}
.label {
color: var(--muted-foreground);
font-size: 11px;
font-weight: 650;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.input-row {
display: flex;
gap: 8px;
}
.input-row .select-like {
flex: 1;
min-width: 0;
}
.notice {
border: 1px solid color-mix(in srgb, var(--warning) 30%, var(--border));
border-radius: 8px;
background: color-mix(in srgb, var(--warning) 7%, var(--card));
color: var(--muted-foreground);
padding: 10px 12px;
font-size: 12px;
}
.mock-caption {
margin: 10px 0 0;
color: var(--muted-foreground);
font-size: 12px;
}
.table {
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
}
.table-row {
display: grid;
grid-template-columns: 170px minmax(0, 1fr) 180px;
gap: 12px;
border-bottom: 1px solid var(--border);
padding: 10px 12px;
font-size: 12px;
}
.table-row:last-child {
border-bottom: 0;
}
.table-head {
background: var(--muted);
color: var(--muted-foreground);
font-weight: 650;
}
.hidden {
display: none;
}
@media (max-width: 900px) {
main {
padding-inline: 16px;
}
.grid-2,
.grid-3,
.split {
grid-template-columns: 1fr;
}
.mock-app {
grid-template-columns: 1fr;
}
.sidebar {
display: none;
}
.toolbar {
align-items: stretch;
flex-direction: column;
}
.toolbar-main {
flex-wrap: wrap;
}
.table-row {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<main>
<header>
<div class="eyebrow">Planning artifact · Host model follow-up</div>
<h1>Tasks, Automations, and Provider Identity Under One Host Model</h1>
<p class="lede">
The project-first migration gives Orca the durable shape
<code>Project -> ProjectHostSetup -> Workspace</code>. The remaining product gap is
that Tasks, Automations, and provider integrations still route through different
ownership rules. This plan makes <strong>Host</strong> the user-facing concept across
Local Mac, SSH machines, Remote Servers, and future Orca cloud VMs.
</p>
<div class="tag-row">
<span class="tag strong">Host = Local / SSH / Remote Server / Cloud VM</span>
<span class="tag">Project identity stays above hosts</span>
<span class="tag">Provider accounts become host-scoped where needed</span>
<span class="tag">Automations get explicit run location</span>
</div>
</header>
<section>
<h2>Short Answer</h2>
<div class="callout">
<p>
We should keep the model simple for users: a project can be available on one or more
hosts, and every host can have its own filesystem, terminals, provider CLIs, auth, and
runtime capabilities. Tasks and Automations should stop relying on ambient global state
where the host matters.
</p>
<p>
The big change is not “make SSH and Remote Server the same internally.” It is “present
both as hosts, then route each workflow through the selected host’s capabilities.”
</p>
</div>
</section>
<section>
<h2>Host Boundaries</h2>
<div class="table">
<div class="table-row table-head">
<div>Host kind</div>
<div>What explicit task context means</div>
<div>Boundary</div>
</div>
<div class="table-row">
<div>Local Mac</div>
<div>
Provider calls, repo discovery, task launch, and workspace creation use the local
desktop environment.
</div>
<div>Baseline path.</div>
</div>
<div class="table-row">
<div>SSH host</div>
<div>
The Tasks page should know the selected project setup lives on an SSH machine and show
whether provider data is served by the SSH host or temporarily by the desktop client.
</div>
<div>
SSH is first-class host context, but support is capability-based: filesystem,
terminal, git, and provider CLI/token execution may arrive independently.
</div>
</div>
<div class="table-row">
<div>Remote Server / runtime</div>
<div>
Provider calls should route through the remote Orca runtime when that runtime owns
the selected project setup and advertises the needed capability.
</div>
<div>
Richer host with runtime RPC, version/capability negotiation, web/mobile handoff, and
more durable background services.
</div>
</div>
<div class="table-row">
<div>Future Cloud VM</div>
<div>
Same user-facing host model: a project setup on that VM can serve Tasks and create
Automations once the VM exposes the required host capabilities.
</div>
<div>Provisioning lifecycle remains separate from task/provider routing.</div>
</div>
</div>
</section>
<section>
<h2>Task Source vs Run Host</h2>
<div class="callout">
<p>
A logical project can exist on multiple hosts, but provider data still has to be fetched
through one credential context. That source context must be explicit or at least visible.
“Project: orca” is not enough information when Local Mac has GitHub account A and
openclaw 2 has GitHub account B.
</p>
</div>
<div class="grid grid-2">
<div class="panel">
<div class="eyebrow">Task source context</div>
<h3>Where issues/PRs are fetched from</h3>
<p class="tiny">
This answers: which host's GitHub/GitLab/Linear/Jira credentials serve the list? It
affects private repo access, rate limits, viewer-specific filters like “assigned to
me,” review requests, notifications, and mutation permissions.
</p>
</div>
<div class="panel">
<div class="eyebrow">Run host</div>
<h3>Where the workspace is created</h3>
<p class="tiny">
This answers: when the user starts work from a task, which project-host setup creates
the workspace? It may default to the task source host, but the user can choose another
ready setup when the project exists there.
</p>
</div>
</div>
<div class="notice" style="margin-top: 12px">
Recommendation: default the task source to the active workspace host or the last-used host
for that project/provider, show the serving account beside the picker, and require an
explicit choice when combining hosts would make “me” ambiguous.
</div>
</section>
<section>
<h2>What Needs To Change</h2>
<div class="checklist">
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Unify provider request ownership around Host.</strong>
<div class="tiny">
GitHub currently has per-repo runtime routing, while SSH/local are desktop-owned.
Linear/Jira use active runtime. GitLab uses desktop IPC with SSH-aware repo paths.
We need a shared provider request target: <code>{ provider, hostId, projectHostSetupId? }</code>.
</div>
</div>
<span class="priority">P0</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Make Tasks choose an explicit host context.</strong>
<div class="tiny">
Applies to Local, SSH, Remote Server, and future Cloud VM hosts. The Tasks page
should show which host/account is serving results. Multi-project and multi-host
selections should either group by host or require a selected host when provider
identity can differ.
</div>
</div>
<span class="priority">P0</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Store Automations as project + run-host, not repo-id pretending to be project-id.</strong>
<div class="tiny">
Existing automations store <code>projectId</code> as a repo id. New automations
should target a logical project and either an existing workspace or a
<code>projectHostSetupId</code> for fresh workspaces.
</div>
</div>
<span class="priority">P0</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Add host-scoped provider settings.</strong>
<div class="tiny">
Settings should answer “which GitHub/GitLab/Linear/Jira account is active on this
host?” without confusing client settings with server/SSH settings.
</div>
</div>
<span class="priority">P0</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Gate UI by host capabilities and connection state.</strong>
<div class="tiny">
Remote Servers can expose runtime RPC capabilities. SSH hosts may support filesystem,
terminal, git, and provider CLI execution through Orca’s SSH bridge. Disconnected or
incompatible hosts should be visible but disabled where action would fail.
</div>
</div>
<span class="priority">P1</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Extend CLI/API language to match the product model.</strong>
<div class="tiny">
Commands should accept <code>--project</code> plus <code>--host</code> or
<code>--project-host-setup</code> for workflows that create workspaces or automations.
Keep repo selectors as compatibility aliases.
</div>
</div>
<span class="priority">P1</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Audit adjacent surfaces that already have host-specific state.</strong>
<div class="tiny">
Source-control AI model choices, task resume state, PR/review caches, setup scripts,
notification actions, direct launch-from-task flows, and run history should include
enough host identity to avoid cross-machine leakage.
</div>
</div>
<span class="priority">P1</span>
</div>
</div>
</section>
<section>
<h2>Model</h2>
<div class="grid grid-3">
<div class="panel">
<div class="eyebrow">Host</div>
<h3>One user-facing bucket</h3>
<p class="tiny">
Local Mac, SSH target, Remote Server/runtime, and future Cloud VM all appear as
hosts. The user chooses where work runs; Orca chooses the transport.
</p>
</div>
<div class="panel">
<div class="eyebrow">Project setup</div>
<h3>Project on a host</h3>
<p class="tiny">
A logical project may have setup rows on multiple hosts. Each row owns path,
readiness, default worktree location, and setup method.
</p>
</div>
<div class="panel">
<div class="eyebrow">Provider identity</div>
<h3>Account where the request runs</h3>
<p class="tiny">
GitHub/GitLab/Linear/Jira identity should be explicit: local desktop account,
SSH-host CLI/token, or Remote Server account.
</p>
</div>
</div>
</section>
<section>
<h2>Tasks Mock</h2>
<div class="mock-shell" data-mock="tasks">
<div class="mock-titlebar">
<div class="window-dots"><span></span><span></span><span></span></div>
<div class="tiny">Tasks · provider context is visible</div>
<div class="tiny">⌘K</div>
</div>
<div class="mock-app">
<aside class="sidebar">
<div class="sidebar-header">Workspaces</div>
<div class="side-section-title">Local Mac</div>
<div class="side-row current">
<span class="dot online"></span>
<span>orca</span>
<span class="side-count">4</span>
</div>
<div class="side-section-title">openclaw 2</div>
<div class="side-row">
<span class="dot online"></span>
<span>orca</span>
<span class="side-count">2</span>
</div>
<div class="side-section-title">build-vm</div>
<div class="side-row">
<span class="dot warning"></span>
<span>orca</span>
<span class="side-count">auth</span>
</div>
</aside>
<section class="content">
<div class="toolbar">
<div class="toolbar-main">
<strong>Tasks</strong>
<div class="tabs" role="tablist">
<button class="tab active" data-tab-target="github">GitHub</button>
<button class="tab" data-tab-target="linear">Linear</button>
<button class="tab" data-tab-target="gitlab">GitLab</button>
</div>
</div>
<div class="toolbar-main">
<span class="select-like">Project: orca</span>
<span class="select-like" id="task-host-select">Host: Local Mac</span>
<span class="identity-pill"><span class="dot online"></span><span id="task-identity">GitHub: @jinwoo</span></span>
</div>
</div>
<div class="list" id="task-list-github">
<div class="task-row">
<div>
<div class="task-title">#5071 Review multi-host project setup flow</div>
<div class="meta-line">
<span>orca · GitHub</span>
<span>served by Local Mac</span>
<span>account @jinwoo</span>
</div>
</div>
<span class="button-like">Start on Local Mac</span>
</div>
<div class="task-row">
<div>
<div class="task-title">#5068 Add runtime compatibility copy</div>
<div class="meta-line">
<span>orca · GitHub</span>
<span>also available on openclaw 2</span>
<span>2 host contexts</span>
</div>
</div>
<span class="button-like">Choose host…</span>
</div>
<div class="notice">
Host context is a first-class filter. If openclaw 2 has a different GitHub
account, switching Host changes the request owner and the rows can legitimately differ.
</div>
</div>
<div class="list hidden" id="task-list-linear">
<div class="task-row">
<div>
<div class="task-title">ORC-1842 Confirm SSH add-project path polish</div>
<div class="meta-line">
<span>Linear</span>
<span>served by selected host</span>
<span>workspace Stably Eng</span>
</div>
</div>
<span class="button-like">Create workspace</span>
</div>
<div class="notice">
Linear/Jira should no longer use only the ambient active runtime. The Tasks page
should pass an explicit host context to provider clients.
</div>
</div>
<div class="list hidden" id="task-list-gitlab">
<div class="task-row">
<div>
<div class="task-title">!92 Remote relay health checks</div>
<div class="meta-line">
<span>GitLab</span>
<span>served by openclaw 2</span>
<span>glab on SSH host</span>
</div>
</div>
<span class="button-like">Start on openclaw 2</span>
</div>
<div class="notice">
GitLab should gain the same host request target as GitHub instead of being only a
desktop IPC call with SSH-aware path resolution.
</div>
</div>
</section>
</div>
</div>
<p class="mock-caption">
Interaction: click GitHub / Linear / GitLab above. The important UI addition is the
visible Host + provider identity pair, not a separate “remote task” mode.
</p>
</section>
<section>
<h2>Automations Mock</h2>
<div class="mock-shell" data-mock="automations">
<div class="mock-titlebar">
<div class="window-dots"><span></span><span></span><span></span></div>
<div class="tiny">Automation editor · run location is explicit</div>
<div></div>
</div>
<div class="split">
<section class="panel">
<div class="eyebrow">Create Automation</div>
<h3>Daily issue triage</h3>
<div class="form">
<div class="field">
<div class="label">Project</div>
<div class="select-like">orca</div>
</div>
<div class="field">
<div class="label">Run on</div>
<div class="input-row">
<span class="select-like">openclaw 2</span>
<span class="identity-pill"><span class="dot online"></span>SSH host</span>
</div>
<div class="tiny">
Only hosts where this project is set up appear here. Add Project remains the way
to make the project available on another host.
</div>
</div>
<div class="field">
<div class="label">Workspace</div>
<div class="tabs">
<button class="tab active">New run</button>
<button class="tab">Existing worktree</button>
</div>
</div>
<div class="field">
<div class="label">Create from</div>
<div class="select-like">origin/main · resolved on openclaw 2</div>
</div>
<div class="field">
<div class="label">Agent</div>
<div class="select-like">Codex · model from openclaw 2 host settings</div>
</div>
<div class="field">
<div class="label">Provider context</div>
<div class="select-like">GitHub tasks: @deploy-bot on openclaw 2</div>
</div>
<div class="notice">
Stored target should be logical project + host setup. Existing workspace mode can
infer host from the workspace, but the editor should still display it.
</div>
</div>
</section>
<section class="panel">
<div class="eyebrow">Run history</div>
<div class="automation-row">
<div>
<div class="automation-title">Daily issue triage</div>
<div class="meta-line">
<span>orca</span>
<span>openclaw 2</span>
<span>auto-daily-20260612</span>
</div>
</div>
<span class="status"><span class="dot online"></span>Completed</span>
</div>
<div class="automation-row">
<div>
<div class="automation-title">Daily issue triage</div>
<div class="meta-line">
<span>orca</span>
<span>build-vm</span>
<span>interactive SSH auth needed</span>
</div>
</div>
<span class="status"><span class="dot warning"></span>Skipped</span>
</div>
<div class="notice">
Scheduled runs should preserve host and workspace display names so history remains
understandable after a host disconnects or a workspace is deleted.
</div>
</section>
</div>
</div>
</section>
<section>
<h2>Settings Mock</h2>
<div class="mock-shell" data-mock="settings">
<div class="mock-titlebar">
<div class="window-dots"><span></span><span></span><span></span></div>
<div class="tiny">Settings · host-scoped integrations</div>
<div></div>
</div>
<div class="mock-app">
<aside class="sidebar">
<div class="sidebar-header">Settings</div>
<div class="side-row current"><span>⌁</span><span>Hosts</span><span></span></div>
<div class="side-row"><span>○</span><span>Integrations</span><span></span></div>
<div class="side-row"><span>◇</span><span>Agents</span><span></span></div>
<div class="side-row"><span>□</span><span>Projects</span><span></span></div>
</aside>
<section class="content">
<div class="toolbar">
<div>
<strong>Host Settings</strong>
<div class="tiny">Settings that depend on where commands run</div>
</div>
<span class="select-like">Viewing: openclaw 2</span>
</div>
<div class="list">
<div class="settings-row">
<div>
<div class="task-title">GitHub</div>
<div class="meta-line">
<span>Account @deploy-bot</span>
<span>Served through SSH host CLI/token</span>
</div>
</div>
<span class="button-like">Reconnect</span>
</div>
<div class="settings-row">
<div>
<div class="task-title">GitLab</div>
<div class="meta-line">
<span>Not connected on this host</span>
<span>Tasks will be disabled for GitLab on openclaw 2</span>
</div>
</div>
<span class="button-like">Connect</span>
</div>
<div class="settings-row">
<div>
<div class="task-title">Default worktree location</div>
<div class="meta-line">
<span><code>~/orca/worktrees</code></span>
<span>Host filesystem path</span>
</div>
</div>
<span class="button-like">Change</span>
</div>
<div class="notice">
This does not need to become a huge second Settings app. Keep global client
preferences global, and add a host dropdown only on panes whose values truly live
on the selected host.
</div>
</div>
</section>
</div>
</div>
</section>
<section>
<h2>Implementation Breakdown</h2>
<div class="table">
<div class="table-row table-head">
<div>Area</div>
<div>Change</div>
<div>Verification</div>
</div>
<div class="table-row">
<div>Shared model</div>
<div>
Add a normalized provider runtime target keyed by <code>ExecutionHostId</code>. Keep
existing <code>ProjectHostSetup</code> as the project-on-host record.
</div>
<div>Unit tests for local, SSH, runtime, disconnected, old-runtime.</div>
</div>
<div class="table-row">
<div>GitHub Tasks</div>
<div>
Route SSH GitHub lookups through the selected SSH host when supported, or clearly
label them as desktop-served until support lands.
</div>
<div>Local account vs SSH account fixture must return different rows.</div>
</div>
<div class="table-row">
<div>GitLab Tasks</div>
<div>
Move from desktop-only IPC assumptions to explicit host provider target. Preserve
current SSH project-ref safeguards.
</div>
<div>GitLab local, SSH, and runtime provider smoke tests.</div>
</div>
<div class="table-row">
<div>Linear / Jira</div>
<div>
Replace ambient active-runtime routing in task surfaces with an explicit host context.
Settings can still default to the focused host.
</div>
<div>Switch host without changing project; account/status updates predictably.</div>
</div>
<div class="table-row">
<div>Automations schema</div>
<div>
Add logical <code>projectId</code>, <code>hostId</code>, and optional
<code>projectHostSetupId</code>. Migrate old repo-id automations by mapping the repo
to its project-host setup.
</div>
<div>Migration tests with old repo-backed automations.</div>
</div>
<div class="table-row">
<div>Automation dispatch</div>
<div>
Resolve host before precheck, worktree creation, terminal launch, provider session
observation, and usage collection.
</div>
<div>Scheduled run on local, SSH, runtime; disconnected SSH skip; auth-needed skip.</div>
</div>
<div class="table-row">
<div>CLI</div>
<div>
Add host-aware selectors for automation create/run and worktree creation while keeping
repo selectors compatible.
</div>
<div>CLI fixtures for <code>--project</code>, <code>--host</code>, old <code>--repo</code>.</div>
</div>
<div class="table-row">
<div>Telemetry / logs</div>
<div>
Track host kind and capability state, not hostnames, paths, repo names, or account
identifiers.
</div>
<div>Telemetry product gate review.</div>
</div>
</div>
</section>
<section>
<h2>Other Explicitness Gaps</h2>
<div class="checklist">
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Composer “Start from” and linked-work-item picker.</strong>
<div class="tiny">
The composer can fetch/link GitHub work items from the selected repo. In the new
model it should inherit or show the task source host/account, then choose a separate
run host when creating the workspace.
</div>
</div>
<span class="priority">P0</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Task row actions and issue/PR drawers.</strong>
<div class="tiny">
Mutations such as assign, comment, review-request, state change, merge, mark viewed,
and create issue need to run under the same explicit provider context that fetched
the row, not whichever host is currently focused later.
</div>
</div>
<span class="priority">P0</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Linear/Jira issue preview pages.</strong>
<div class="tiny">
These currently key heavily off active runtime and provider workspace ids. They need
a durable source host/account context so opening, editing, commenting, and starting a
workspace from an issue stay in the same provider identity.
</div>
</div>
<span class="priority">P0</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Hosted review / PR helper flows.</strong>
<div class="tiny">
Review creation, PR field generation, fix-checks launch, branch-to-PR lookup, and
direct launch from review/task need to carry project-host setup plus provider source
context. Otherwise the action can resolve against the wrong checkout or account.
</div>
</div>
<span class="priority">P1</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Settings and integrations entry points.</strong>
<div class="tiny">
Provider settings should say whether they are client-global, host-scoped, or
project-scoped. Opening settings from Tasks should land on the same host/account
context the user was just looking at.
</div>
</div>
<span class="priority">P1</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Persisted task UI state and caches.</strong>
<div class="tiny">
Recent selections, resume state, work item cache keys, PR detail caches, labels,
assignees, and partial-failure banners should be keyed by provider source context,
not only repo id or active runtime.
</div>
</div>
<span class="priority">P1</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Automation run history, reuse, and usage attribution.</strong>
<div class="tiny">
Runs should store logical project, project-host setup, source provider context, run
host, terminal/session ids, and display labels so history remains clear after host
disconnects, account changes, or workspace deletion.
</div>
</div>
<span class="priority">P1</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>CLI/API selectors.</strong>
<div class="tiny">
CLI commands that create workspaces, create automations, start from tasks, or fetch
provider data need explicit <code>--project</code>, <code>--host</code>, and/or
<code>--task-source-host</code> options. Existing <code>--repo</code> selectors can
remain compatibility aliases.
</div>
</div>
<span class="priority">P1</span>
</div>
<div class="check-row">
<span class="box">□</span>
<div>
<strong>Telemetry and diagnostics.</strong>
<div class="tiny">
Events/logs should include non-sensitive host kind and capability status so we can
debug routing without recording account names, hostnames, repo paths, or issue text.
</div>
</div>
<span class="priority">P2</span>
</div>
</div>
</section>
<section>
<h2>Subagent Audit Confirmation</h2>
<div class="callout">
<p>
A second codebase pass split across Tasks/provider routing, Automations,
Composer/PR launch, and Settings/cache/CLI agreed on the same core gap:
Orca needs an explicit <code>TaskSourceContext</code> separate from the
<code>ProjectHostSetup</code> used to run work.
</p>
</div>
<div class="grid grid-2">
<div class="panel compact">
<h4>Tasks/provider routing</h4>
<p class="tiny">
GitHub is partly host-scoped already, but Linear/Jira still route through active
runtime, GitLab is mostly repo-path/local-IPC based, and drawer mutations can lose the
source account. Report: <code>notes/subagent-tasks-provider-hosts-audit.md</code>.
</p>
</div>
<div class="panel compact">
<h4>Automations</h4>
<p class="tiny">
Automations still treat <code>projectId</code> as a repo id and do not snapshot
<code>hostId</code>, <code>projectHostSetupId</code>, provider source context, or
runtime capability/version on runs. Report:
<code>notes/subagent-automations-host-model-audit.md</code>.
</p>
</div>
<div class="panel compact">
<h4>Composer / PR launch</h4>
<p class="tiny">
Start-from flows use one <code>repoId</code> as both source item and run target.
Pending worktree creation stores linked numbers but not source host/account context.
Report: <code>notes/subagent-composer-pr-launch-hosts-audit.md</code>.
</p>
</div>
<div class="panel compact">
<h4>Settings / cache / CLI</h4>
<p class="tiny">
Some host foundations are strong, but GitLab selectors are repo-path-only, provider
diagnostics are still client-global, agent launch overrides are global, and CLI
automation selectors remain repo-first. Report:
<code>notes/subagent-settings-cache-cli-hosts-audit.md</code>.
</p>
</div>
</div>
</section>
<section>
<h2>Open Product Decisions</h2>
<div class="grid grid-2">
<div class="panel compact">
<h4>Do Tasks allow multi-host aggregation?</h4>
<p class="tiny">
Recommendation: yes for GitHub/GitLab rows when each row can show its serving host,
but default to one selected host for Linear/Jira until cross-host grouping is useful.
</p>
</div>
<div class="panel compact">
<h4>Should SSH provider auth run on the SSH machine?</h4>
<p class="tiny">
Recommendation: eventually yes. In the interim, label desktop-served SSH provider
calls explicitly to avoid misleading users with different accounts.
</p>
</div>
<div class="panel compact">
<h4>Are Remote Servers “better SSH”?</h4>
<p class="tiny">
Recommendation: explain them as richer hosts. SSH gives filesystem/terminal access to
a machine you already manage. Remote Server adds Orca runtime services, durable RPC,
web/mobile handoff, capability/version negotiation, and richer background behavior.
</p>
</div>
<div class="panel compact">
<h4>Do we need host onboarding now?</h4>
<p class="tiny">
Recommendation: no. Existing SSH/server settings can remain the entry point. This work
should make configured hosts behave correctly once present.
</p>
</div>
</div>
</section>
</main>
<script>
const tabs = document.querySelectorAll('[data-tab-target]');
const lists = {
github: document.getElementById('task-list-github'),
linear: document.getElementById('task-list-linear'),
gitlab: document.getElementById('task-list-gitlab')
};
const identity = document.getElementById('task-identity');
const host = document.getElementById('task-host-select');
const labels = {
github: ['Host: Local Mac', 'GitHub: @jinwoo'],
linear: ['Host: openclaw 2', 'Linear: Stably Eng on openclaw 2'],
gitlab: ['Host: openclaw 2', 'GitLab: glab on openclaw 2']
};
tabs.forEach((tab) => {
tab.addEventListener('click', () => {
const key = tab.dataset.tabTarget;
tabs.forEach((candidate) => candidate.classList.toggle('active', candidate === tab));
Object.entries(lists).forEach(([name, node]) => {
node.classList.toggle('hidden', name !== key);
});
host.textContent = labels[key][0];
identity.textContent = labels[key][1];
});
});
</script>
</body>
</html>