diff --git a/notes/host-context-implementation-checklist.md b/notes/host-context-implementation-checklist.md
index de831348e5a..300cc9d4ccf 100644
--- a/notes/host-context-implementation-checklist.md
+++ b/notes/host-context-implementation-checklist.md
@@ -219,6 +219,7 @@ Done means: reviewers and future agents can understand the vision, implementatio
- [x] 2026-06-12: Tightened the project-first design doc so host-aware Add Project is the current path for browse/import, clone, and create, while bulk setup and cloud VM provisioning are future host-onboarding work. Re-verified shared host-model tests covering local/SSH/runtime host kinds, runtime capability gating, SSH reconnect/disconnect actions, host settings overrides, and task source host scopes.
- [x] 2026-06-12: Tightened runtime project-host setup availability so remote servers must advertise both `project-host-setup.v1` and `workspace-run-context.v1` before users can choose them for project setup/workspace creation; verified with focused setup option tests, targeted oxlint, `git diff --check`, and full `pnpm run typecheck`.
- [x] 2026-06-13: Verified Linear Tasks in the live Electron app with the connected legacy Linear API-key workspace: the visible Linear list rendered 36 issues, source-scoped cache keys included both the legacy local account key and an explicit `linear:local:...` task-source cache key, and screenshot evidence was added to the dark verification report. Jira remains unverified because this profile has no connected Jira account.
+- [x] 2026-06-13: Added Automations detail source-context display so saved automations show their provider source/account/host separately from run location; verified with focused source-display tests, targeted oxlint, `git diff --check`, and full `pnpm run typecheck`.
- [x] 2026-06-12: Live-verified Add Project disconnected-host UX in Electron by simulating the SSH target as disconnected in renderer state: the Host picker defaulted to Local Mac and showed the SSH host as a disabled muted row; restored SSH to connected and added screenshot evidence to `notes/multihost-remote-verification-report.html`.
- [x] 2026-06-12: Audited Settings ownership for Source Control AI defaults, repository Source Control AI overrides, agent launch defaults, quick commands, workspace directories, and provider accounts; added a tested settings-ownership helper and surfaced the ownership language in Settings while preserving the existing Windows/WSL account and agent-location pattern. Verified with focused settings tests and web typecheck.
- [x] 2026-06-12: Improved remote-server Settings version-skew diagnostics by showing the exact compatibility explanation plus named runtime capabilities instead of only a capability count; verified with `RuntimeEnvironmentsPane` tests and web typecheck.
diff --git a/src/renderer/src/components/automations/AutomationDetail.tsx b/src/renderer/src/components/automations/AutomationDetail.tsx
index 1ab6f87c4fa..7c346aa27f4 100644
--- a/src/renderer/src/components/automations/AutomationDetail.tsx
+++ b/src/renderer/src/components/automations/AutomationDetail.tsx
@@ -14,6 +14,7 @@ import {
summarizeAutomationRunUsage
} from './automation-usage-model'
import type { AutomationTargetAvailability } from './automation-target-availability'
+import { getAutomationSourceDisplay } from './automation-source-display'
import { translate } from '@/i18n/i18n'
type AutomationDetailProps = {
@@ -30,11 +31,21 @@ type AutomationDetailProps = {
onDelete: (automation: Automation) => void
}
-function DetailMetric({ label, value }: { label: string; value: string }): React.JSX.Element {
+function DetailMetric({
+ label,
+ value,
+ title
+}: {
+ label: string
+ value: string
+ title?: string
+}): React.JSX.Element {
return (
{label}
-
{value}
+
+ {value}
+
)
}
@@ -118,6 +129,7 @@ export function AutomationDetail({
automation.workspaceMode === 'new_per_run'
? (automation.baseBranch ?? projectDefaultBaseRef ?? 'Project default')
: workspaceName
+ const sourceDisplay = getAutomationSourceDisplay(automation.sourceContext)
const runNowDisabled = runNowAvailability?.canRunNow === false
return (
@@ -235,6 +247,13 @@ export function AutomationDetail({
label={translate('auto.components.automations.AutomationDetail.15ea446b93', 'Session')}
value={automation.reuseSession ? 'Reuse live session' : 'Fresh each run'}
/>
+ {sourceDisplay ? (
+
+ ) : null}
{
+ it('summarizes repo-backed source context separately from run location', () => {
+ const sourceContext: TaskSourceContext = {
+ kind: 'task-source',
+ provider: 'github',
+ hostId: 'ssh:devbox',
+ projectId: 'github:stablyai/orca',
+ projectHostSetupId: 'setup-devbox',
+ repoId: 'repo-devbox',
+ accountLabel: 'dev@example.com',
+ providerIdentity: {
+ provider: 'github',
+ owner: 'stablyai',
+ repo: 'orca'
+ }
+ }
+
+ expect(getAutomationSourceDisplay(sourceContext)).toEqual({
+ label: 'GitHub · devbox · stablyai/orca',
+ title: 'GitHub source · Host: devbox · Account: dev@example.com · Source: stablyai/orca'
+ })
+ })
+
+ it('uses account identity for Linear sources', () => {
+ const sourceContext: TaskSourceContext = {
+ kind: 'task-source',
+ provider: 'linear',
+ hostId: 'local',
+ projectId: 'repo-1',
+ projectHostSetupId: 'setup-local',
+ repoId: 'repo-1',
+ accountLabel: 'Linear API key',
+ providerIdentity: {
+ provider: 'linear',
+ workspaceId: 'legacy',
+ workspaceName: 'Saved Linear workspace'
+ }
+ }
+
+ expect(getAutomationSourceDisplay(sourceContext)).toEqual({
+ label: 'Linear · Local Mac · Saved Linear workspace',
+ title:
+ 'Linear source · Host: Local Mac · Account: Linear API key · Source: Saved Linear workspace'
+ })
+ })
+
+ it('returns null when no source context is saved', () => {
+ expect(getAutomationSourceDisplay(null)).toBeNull()
+ })
+})
diff --git a/src/renderer/src/components/automations/automation-source-display.ts b/src/renderer/src/components/automations/automation-source-display.ts
new file mode 100644
index 00000000000..5e1166e6d9b
--- /dev/null
+++ b/src/renderer/src/components/automations/automation-source-display.ts
@@ -0,0 +1,62 @@
+import { getExecutionHostLabel } from '../../../../shared/execution-host'
+import type { TaskSourceContext } from '../../../../shared/task-source-context'
+
+export type AutomationSourceDisplay = {
+ label: string
+ title: string
+}
+
+export function getAutomationSourceDisplay(
+ sourceContext: TaskSourceContext | null | undefined
+): AutomationSourceDisplay | null {
+ if (!sourceContext) {
+ return null
+ }
+ const providerLabel = getProviderLabel(sourceContext.provider)
+ const hostLabel = getExecutionHostLabel(sourceContext.hostId)
+ const identityLabel = getSourceIdentityLabel(sourceContext)
+ const label = [providerLabel, hostLabel, identityLabel]
+ .filter((part): part is string => Boolean(part))
+ .join(' · ')
+ const title = [
+ `${providerLabel} source`,
+ `Host: ${hostLabel}`,
+ sourceContext.accountLabel ? `Account: ${sourceContext.accountLabel}` : null,
+ identityLabel ? `Source: ${identityLabel}` : null
+ ]
+ .filter((part): part is string => Boolean(part))
+ .join(' · ')
+ return { label, title }
+}
+
+function getProviderLabel(provider: TaskSourceContext['provider']): string {
+ switch (provider) {
+ case 'github':
+ return 'GitHub'
+ case 'gitlab':
+ return 'GitLab'
+ case 'linear':
+ return 'Linear'
+ case 'jira':
+ return 'Jira'
+ }
+}
+
+function getSourceIdentityLabel(sourceContext: TaskSourceContext): string | null {
+ const identity = sourceContext.providerIdentity
+ if (identity) {
+ switch (identity.provider) {
+ case 'github':
+ return `${identity.owner}/${identity.repo}`
+ case 'gitlab':
+ return identity.namespace && identity.project
+ ? `${identity.namespace}/${identity.project}`
+ : (identity.projectId ?? null)
+ case 'linear':
+ return identity.workspaceName ?? identity.workspaceId ?? null
+ case 'jira':
+ return identity.siteUrl ?? identity.siteId ?? null
+ }
+ }
+ return sourceContext.accountLabel ?? sourceContext.repoId ?? null
+}