From 3099bab308a4aeb97b4d25a50dce4d2367094938 Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Fri, 12 Jun 2026 22:26:23 -0700 Subject: [PATCH] Guard task source switching boundary Co-authored-by: Orca --- .../host-context-implementation-checklist.md | 3 +- .../task-page-source-switch-boundary.test.ts | 30 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/renderer/src/components/task-page-source-switch-boundary.test.ts diff --git a/notes/host-context-implementation-checklist.md b/notes/host-context-implementation-checklist.md index 4a1fc5b0966..6d3c82c5a89 100644 --- a/notes/host-context-implementation-checklist.md +++ b/notes/host-context-implementation-checklist.md @@ -45,7 +45,7 @@ Done means: if Machine A and Machine B have different provider accounts, every l - [x] Add an explicit source-context picker or display for Tasks that can represent host, provider account, and project/source. - [x] Decide and implement the default Tasks view when a logical project exists on multiple hosts. -- [~] Support switching the task source without changing the current run host. +- [x] Support switching the task source without changing the current run host. - [~] Show enough account/host metadata to make mismatched GitHub/GitLab/Linear/Jira accounts understandable. - [~] Persist task source context in task drawer URLs/state so refresh, deep links, and reopen preserve the same source. - [x] Ensure task drawer actions reuse the drawer item source context, not a global provider default. @@ -251,3 +251,4 @@ Done means: reviewers and future agents can understand the vision, implementatio - [x] 2026-06-12: Improved the Tasks project/source picker by removing the repo-row `SSH` tag and showing host-aware project detail (`Host ยท path`) when the picker is fed host context, so same-project-on-multiple-hosts is distinguishable without implying the project itself is SSH; verified with focused combobox tests, targeted oxlint, and full `pnpm run typecheck`. - [x] 2026-06-12: Marked the default Tasks multi-host behavior complete based on the existing implementation that selects one source per logical GitHub project, prefers Local Mac for duplicate logical projects, and preserves manual multi-host selection; evidence is `task-page-default-repo-selection.test.ts` plus the prior full typecheck. - [x] 2026-06-12: Made provider settings and API-budget scope copy point users to Settings > Active Server when they need to edit or inspect another Host's provider credentials/budgets, keeping the existing global Host selector discoverable without duplicating a per-card selector; verified with provider-scope, source-control card, tracker card, and rate-limit panel tests. +- [x] 2026-06-12: Added a TaskPage boundary regression proving source-provider switching updates only task source/default task source and does not mutate focused runtime, project-host setup, or workspace run context; this completes the task-source versus run-host switching row alongside the existing Composer host-context boundary tests. diff --git a/src/renderer/src/components/task-page-source-switch-boundary.test.ts b/src/renderer/src/components/task-page-source-switch-boundary.test.ts new file mode 100644 index 00000000000..65fbab86c79 --- /dev/null +++ b/src/renderer/src/components/task-page-source-switch-boundary.test.ts @@ -0,0 +1,30 @@ +import { readFileSync } from 'node:fs' +import { join } from 'node:path' +import { describe, expect, it } from 'vitest' + +const TASK_PAGE_SOURCE = readFileSync(join(__dirname, 'TaskPage.tsx'), 'utf8') + +function sourceBetween(source: string, startPattern: string, endPattern: string): string { + const start = source.indexOf(startPattern) + expect(start).toBeGreaterThanOrEqual(0) + const end = source.indexOf(endPattern, start + startPattern.length) + expect(end).toBeGreaterThan(start) + return source.slice(start, end) +} + +describe('TaskPage source switching host boundary', () => { + it('switches task source without mutating the focused run host', () => { + const section = sourceBetween( + TASK_PAGE_SOURCE, + '{visibleSourceOptions.map((source) => {', + "{taskSource === 'linear' && linearConnected ?" + ) + + expect(section).toContain('openTaskPage(') + expect(section).toContain('taskSource: source.id') + expect(section).toContain('defaultTaskSource: source.id') + expect(section).not.toContain('activeRuntimeEnvironmentId') + expect(section).not.toContain('projectHostSetupId') + expect(section).not.toContain('workspaceRunContext') + }) +})