Skip to content

Let me pin an automation so its latest workspace stays in the sidebar #6172

Open

Description

@jaseemts

I run 13 scheduled automations on a 24/7 host (SEO monitors, a CWV fixer, weekly release notes). Every run mints a fresh workspace, which is exactly what I want for isolation. The problem is visibility: pinning works at the workspace level, so a pin points at yesterday's dead run by the next morning, and pinning every run would flood the sidebar with stale entries.

Ideally I'd pin the automation itself and the sidebar entry would always resolve to its newest workspace. One row per automation, always current. An "Automations" group in the sidebar would work too.

Current workaround is the Workspaces page filtered to the host. It works, but it mixes automation runs with everything else, and there's no pin control in the CLI or API to script around this.

Happy to test a build if this lands.

Activity

  1. github-actions commented on Aug 5, 2026

    @github-actions
    Contributor

    Summary

    This is a feature request, not a bug, and the code matches the described behavior exactly. Superset's sidebar pin is a property of a workspace, and an automation running in "fresh workspace per run" mode mints a new workspace id on every dispatch, so a pin made today is attached to a workspace that will never be reused tomorrow. There is currently no entity in the sidebar model that can represent "an automation, resolved to its newest run," and no CLI/API surface for pinning at all — the pin lives only in renderer-local state on one machine.

    Affected code

    Pinning is workspace-scoped, renderer-local state

    • apps/desktop/src/renderer/routes/_authenticated/providers/CollectionsProvider/dashboardSidebarLocal/schema.ts:135 — sidebarState.pinnedAt (epoch ms, null = unpinned) on the per-workspace v2WorkspaceLocalState row. This is the only pin field in the app.
    • apps/desktop/src/renderer/routes/_authenticated/hooks/useDashboardSidebarState/useDashboardSidebarState.ts:449 — setWorkspacePinned(workspaceId, projectId, pinned); keyed by workspace id.
    • .../DashboardSidebar/hooks/useDashboardSidebarData/buildDashboardSidebarProjects.ts:59 and :114 — partitionSidebarWorkspacesByPinned / buildDashboardSidebarPinnedWorkspaces, both typed over SidebarWorkspaceInput.
    • .../DashboardSidebar/types.ts:71 — the sidebar row union is { type: "workspace" } | { type: "section" }, and DashboardSidebarPinnedSection.tsx:45-55 renders DashboardSidebarWorkspaceItem only.

    So "pin an automation" is not a flag flip; it needs a new pinnable row kind.

    Why the pin goes stale by morning

    • packages/trpc/src/router/automation/dispatch.ts:127 — workspaceId = automation.v2WorkspaceId ?? (await createFreshWorkspace()). With fresh-per-run (v2WorkspaceId null), createWorkspaceOnHost (dispatch.ts:262-317) creates a brand-new workspace with a timestamped branch on every dispatch.
    • The new id is recorded on the run row, not the automation: packages/db/src/schema/schema.ts:826 (automation_runs.v2_workspace_id). Nothing ever repoints a pinnedAt from run N to run N+1.
    • apps/desktop/src/renderer/routes/_authenticated/components/AgentHooks/hooks/usePlaceLocalWorktreesInSidebar/usePlaceLocalWorktreesInSidebar.ts:12-23 places every automation-created worktree into the sidebar as a normal row. Worth noting for triage: with 13 automations on a 24/7 host the sidebar already accumulates one row per run regardless of pinning — the pin flooding described is a subset of a broader retention gap.

    The existing near-miss (please don't close as already-supported)

    automations.v2_workspace_id (packages/db/src/schema/schema.ts:780) is already called the pinned workspace in the dispatcher — see the stale-pin recovery at dispatch.ts:133-158 — and it's settable via superset automations create --workspace <id> (packages/cli/src/commands/automations/create/command.ts:26, "existing v2 workspace id — reuses it every run"). That does yield one stable sidebar row, but it achieves it by reusing a single worktree forever, which trades away exactly the per-run isolation this request wants to keep. The two are different features.

    CLI/API pin control: confirmed absent

    packages/cli/src/commands/workspaces/update/command.ts:9-14 accepts only --name, --task-id, --clear-task. Pin state never leaves the renderer's local collection, and as the hook doc at usePlaceLocalWorktreesInSidebar.ts:14-16 notes, the CLI and automations go through the host service and "can't write renderer-local sidebar state." A scriptable pin therefore needs a server-side home for the pin, not just a new CLI flag. This also interacts with the persisted-state policy in apps/desktop/AGENTS.md (entity-keyed state belongs in SQLite; cross-machine deletes bypass UI cleanup) — today a pin is silently per-machine.

    Root cause

    Not a defect. The pin's identity key is the workspace id, and fresh-per-run mode makes that key ephemeral by design. There is no automationId → newest workspace indirection anywhere in the sidebar data path.

    Reproduction

    1. superset automations create --project <projectId> --agent <agent> with a short rrule (no --workspace, so each run mints a workspace).
    2. Let it dispatch twice.
    3. Right-click run 1's workspace in the sidebar → Pin.
    4. After run 2, the Pinned section still shows run 1's workspace; run 2 appears as a separate unpinned row under the project group.

    A unit-level characterization test fits next to buildDashboardSidebarProjects.test.ts: feed two SidebarWorkspaceInput rows from the same automation (only the first with pinnedAt) and assert the pinned partition contains the older one — which documents that nothing maps an automation to its latest workspace.

    Suggested direction

    The building block already exists: automation.listRuns (packages/trpc/src/router/automation/automation.ts:589-605) orders desc(automationRuns.createdAt) and returns v2WorkspaceId plus terminalSessionId/chatSessionId, backed by automation_runs_history_idx. The automation detail page already performs exactly the resolve-and-navigate this request wants, at PreviousRunsList.tsx:48-59.

    • Option A — dynamic pin. Store pinned automation ids in a small singleton local collection, resolve each via listRuns({ limit: 1 }), and render it through the existing workspace item with the automation's name as the label. Requires a new row kind in types.ts, a builder beside buildDashboardSidebarPinnedWorkspaces, and care that the resolved workspace is excluded from its project group so it doesn't double-render (the same invariant partitionSidebarWorkspacesByPinned maintains today).
    • Option B — "Automations" group (the alternative in the request, and likely cleaner). A top-level section fed by automation.list, each row deep-linking to the newest run. This leaves pin semantics untouched, which matters because pinning is both workspace-scoped and machine-local.
    • Companion fix either way: add retention/auto-hide for older automation worktrees in selectWorktreesToPlace, or one stable row will still sit above N stale ones.
    • For scripting: exposing the resolved newest workspace read-only (e.g. on automations get) is purely additive over listRuns and could ship independently of any pin write path.
  2. Kitenite commented on Aug 5, 2026

    @Kitenite
    Member

    Perhaps an automation group works best, we would need to be able to affect sidebar state from host service which shouldn't be crazy lift. I also run a ton of automations so having automations automatically add itself to a group makes sense

  3. jaseemts commented on Aug 5, 2026

    @jaseemts
    Author

    An automations group that self-populates would be exactly it. Two things would round it out: older run workspaces auto-hiding once a newer one lands (the retention gap the bot flagged), and the newest workspace id readable on automations get so the CLI can script against it. Happy to test a build.

  4. jaseemts commented on Aug 29, 2026

    @jaseemts
    Author

    Adding a piece to the automations-group direction: an unread badge, so the group works as an inbox rather than just a folder.

    Today every run lands as a normal sidebar row with no signal, so a new run is indistinguishable from thirty stale ones until I read each name. What would make the group usable at a glance:

    • The Automations group row shows an unread count (like a chat badge — "12 new runs since I last looked")
    • Opening or acting on a run marks it read and decrements the count; a "mark all read" on the group clears it in one action
    • Optionally per-automation counts inside the group

    This also addresses the broader annoyance behind my original report: I want every workspace — user- or automation-initiated — in the sidebar by default. Today some runs end up unlisted, and the only way to find them is the Workspaces page, filtering, and manually pinning each one. A self-populating group with a badge makes new runs instantly visible and old ones dismissible in bulk, instead of one-by-one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions