);
}
diff --git a/apps/web/components/task-create-dialog-form-body.test.tsx b/apps/web/components/task-create-dialog-form-body.test.tsx
index 2d18ec0012..3cd07c5859 100644
--- a/apps/web/components/task-create-dialog-form-body.test.tsx
+++ b/apps/web/components/task-create-dialog-form-body.test.tsx
@@ -1,6 +1,6 @@
import { createRef } from "react";
-import { render, screen } from "@testing-library/react";
-import { describe, expect, it, vi } from "vitest";
+import { cleanup, render, screen } from "@testing-library/react";
+import { afterEach, describe, expect, it, vi } from "vitest";
import {
CreateEditSelectors,
DialogPromptSection,
@@ -8,12 +8,22 @@ import {
} from "./task-create-dialog-form-body";
import type { DialogFormState, TaskFormInputsHandle } from "./task-create-dialog-types";
+afterEach(cleanup);
+
vi.mock("@/components/workflow-selector-row", () => ({
WorkflowSelectorRow: ({ selectedWorkflowId }: { selectedWorkflowId: string | null }) => (
),
}));
+vi.mock("@/components/task-create-dialog-dependencies", () => ({
+ TaskCreateDependencies: ({ value }: { value: string[] }) => (
+
+ ),
+}));
+
// Capture every render of TaskFormInputs so passthrough-related assertions can
// inspect the props that DialogPromptSection forwards to the textarea.
const taskFormInputsCalls: Array> = [];
@@ -46,7 +56,7 @@ function renderWorkflowSection(effectiveWorkflowId: string | null) {
);
}
-describe("WorkflowSection", () => {
+describe("WorkflowSection workflow rendering", () => {
it("keeps the selector reachable when no effective workflow is selected", () => {
renderWorkflowSection(null);
@@ -54,9 +64,52 @@ describe("WorkflowSection", () => {
});
it("does not show redundant selector for a selected single workflow without overrides", () => {
- const { container } = renderWorkflowSection("wf-1");
+ renderWorkflowSection("wf-1");
- expect(container.textContent).toBe("");
+ expect(screen.queryByRole("button", { name: /workflow selector wf-1/i })).toBeNull();
+ expect(screen.queryByTestId("task-create-dependencies-trigger")).toBeNull();
+ });
+});
+
+describe("WorkflowSection", () => {
+ const secondWorkflow = { id: "wf-2", name: "Support" };
+
+ function renderWorkflowSection(
+ effectiveWorkflowId: string | null,
+ workflows = [workflow, secondWorkflow],
+ ) {
+ return render(
+ {}}
+ agentProfiles={[]}
+ />,
+ );
+ }
+
+ it("renders the workflow selector without an inline dependency slot", () => {
+ renderWorkflowSection("wf-1");
+
+ expect(screen.getByRole("button", { name: /workflow selector wf-1/i })).toBeTruthy();
+ expect(screen.queryByTestId("task-create-dependencies-trigger")).toBeNull();
+ });
+
+ it("does not render a workflow row for a single workflow without overrides", () => {
+ renderWorkflowSection("wf-1", [workflow]);
+
+ expect(screen.queryByRole("button", { name: /workflow selector wf-1/i })).toBeNull();
+ expect(screen.queryByTestId("task-create-dependencies-trigger")).toBeNull();
+ });
+
+ it("keeps the workflow section independent from advanced dependencies", () => {
+ renderWorkflowSection("wf-1");
+
+ expect(screen.getByRole("button", { name: /workflow selector wf-1/i })).toBeTruthy();
+ expect(screen.queryByTestId("task-create-dependency-slot")).toBeNull();
});
});
diff --git a/apps/web/components/task-create-dialog-form-body.tsx b/apps/web/components/task-create-dialog-form-body.tsx
index 00f58df0de..57ae72c77d 100644
--- a/apps/web/components/task-create-dialog-form-body.tsx
+++ b/apps/web/components/task-create-dialog-form-body.tsx
@@ -283,7 +283,7 @@ type WorkflowSectionProps = {
workflowLocked?: boolean;
};
-export const WorkflowSection = memo(function WorkflowSection({
+function renderWorkflowSection({
isCreateMode,
isTaskStarted,
workflows: allWorkflows,
@@ -351,6 +351,11 @@ export const WorkflowSection = memo(function WorkflowSection({
}
return null;
+}
+
+export const WorkflowSection = memo(function WorkflowSection(workflowProps: WorkflowSectionProps) {
+ if (!workflowProps.isCreateMode || workflowProps.isTaskStarted) return null;
+ return renderWorkflowSection(workflowProps);
});
export type DialogPromptSectionProps = {
diff --git a/apps/web/components/task-create-dialog.test.tsx b/apps/web/components/task-create-dialog.test.tsx
index db4bc56f0e..ecf34229bf 100644
--- a/apps/web/components/task-create-dialog.test.tsx
+++ b/apps/web/components/task-create-dialog.test.tsx
@@ -85,6 +85,7 @@ vi.mock("@/components/task-create-dialog-repo-chips", () => ({
}));
vi.mock("@/hooks/use-task-create-dialog-popover-container", () => ({
+ useTaskCreateDialogPopoverContainer: () => null,
TaskCreateDialogPopoverContainerProvider: ({ children }: { children: ReactNode }) => (
<>{children}>
),
diff --git a/apps/web/components/task-create-dialog.tsx b/apps/web/components/task-create-dialog.tsx
index 824c427411..5e0126fd9b 100644
--- a/apps/web/components/task-create-dialog.tsx
+++ b/apps/web/components/task-create-dialog.tsx
@@ -16,13 +16,13 @@ import {
DialogPromptSection,
} from "@/components/task-create-dialog-form-body";
import { CreateModeSelectors } from "@/components/task-create-dialog-create-mode-selectors";
-import { TaskCreateDependencies } from "@/components/task-create-dialog-dependencies";
import {
AgentSelector,
ExecutorProfileSelector,
InlineTaskName,
} from "@/components/task-create-dialog-selectors";
import { RepoChipsRow } from "@/components/task-create-dialog-repo-chips";
+import { TaskCreateAdvancedSettings } from "@/components/task-create-dialog-advanced-settings";
import type {
DialogFormBodyProps,
TaskCreateDialogProps,
@@ -111,13 +111,6 @@ function CreateModeBody(props: DialogFormBodyProps) {
onComposerSubmit={props.onComposerSubmit}
/>
- {isCreateMode && !isTaskStarted && (
-
- )}
{props.bottomSlot}
>
);
@@ -190,6 +183,13 @@ function DialogFormBody(props: DialogFormBodyProps) {
agentProfiles={props.agentProfiles}
workflowLocked={props.workflowLocked}
/>
+
);
}
diff --git a/apps/web/e2e/tests/task/create-task-dependency-selector.spec.ts b/apps/web/e2e/tests/task/create-task-dependency-selector.spec.ts
new file mode 100644
index 0000000000..ed85d057de
--- /dev/null
+++ b/apps/web/e2e/tests/task/create-task-dependency-selector.spec.ts
@@ -0,0 +1,163 @@
+import { expect, test } from "../../fixtures/test-base";
+import { useRegularMode } from "../../helpers/regular-mode";
+import { KanbanPage } from "../../pages/kanban-page";
+
+useRegularMode();
+
+const DEPENDENCY_TRIGGER = "task-create-dependencies-trigger";
+const DEPENDENCY_OPTION_PREFIX = "task-create-dependency-option-";
+
+function taskIdFromUrl(url: string): string {
+ const match = url.match(/\/t\/([^/?]+)/);
+ if (!match) throw new Error(`Task route missing from ${url}`);
+ return match[1];
+}
+
+test.describe("Task-create dependency selector", () => {
+ test("selects, clears, and persists multiple predecessor tasks", async ({
+ testPage,
+ apiClient,
+ seedData,
+ }) => {
+ const extraWorkflow = await apiClient.createWorkflow(
+ seedData.workspaceId,
+ "Dependency selector workflow",
+ "simple",
+ );
+ const taskOptions = {
+ workflow_id: seedData.workflowId,
+ workflow_step_id: seedData.startStepId,
+ repository_ids: [seedData.repositoryId],
+ };
+ const alpha = await apiClient.createTask(seedData.workspaceId, "Dependency Alpha", taskOptions);
+ const beta = await apiClient.createTask(seedData.workspaceId, "Dependency Beta", taskOptions);
+ const archived = await apiClient.createTask(
+ seedData.workspaceId,
+ "Archived dependency",
+ taskOptions,
+ );
+ await apiClient.archiveTask(archived.id);
+
+ try {
+ const kanban = new KanbanPage(testPage);
+ await kanban.goto();
+ await kanban.createTaskButton.first().click();
+
+ const dialog = testPage.getByTestId("create-task-dialog");
+ await expect(dialog).toBeVisible();
+ const advancedSettings = dialog.getByTestId("task-create-advanced-settings");
+ const advancedTrigger = advancedSettings.getByTestId("task-create-advanced-settings-trigger");
+ await expect(advancedTrigger).toBeVisible();
+ await expect(advancedTrigger).toHaveAttribute("aria-expanded", "false");
+ await expect(dialog.getByTestId(DEPENDENCY_TRIGGER)).toHaveCount(0);
+ await expect(dialog.getByTestId("agent-profile-selector")).toBeVisible();
+ await expect(dialog.getByTestId("executor-profile-selector")).toBeVisible();
+ const workflowSelector = dialog.getByTestId("workflow-selector-trigger");
+ await expect(workflowSelector).toBeVisible();
+ expect(
+ await advancedSettings.evaluate((element) => {
+ const dialogRoot = element.closest('[data-testid="create-task-dialog"]');
+ if (!dialogRoot) return false;
+ return [
+ "agent-profile-selector",
+ "executor-profile-selector",
+ "workflow-selector-trigger",
+ ].every((testId) => {
+ const control = dialogRoot.querySelector(`[data-testid="${testId}"]`);
+ return (
+ control !== null &&
+ Boolean(control.compareDocumentPosition(element) & Node.DOCUMENT_POSITION_FOLLOWING)
+ );
+ });
+ }),
+ ).toBe(true);
+ await advancedTrigger.click();
+ await expect(advancedTrigger).toHaveAttribute("aria-expanded", "true");
+ await expect(
+ advancedSettings.getByTestId("task-create-dependency-setting-label"),
+ ).toContainText("Depends on");
+ const settingGrid = advancedSettings.getByTestId("task-create-advanced-settings-grid");
+ const settingGridBox = await settingGrid.boundingBox();
+ const settingRow = advancedSettings.getByTestId("task-create-dependency-setting-row");
+ const settingRowBox = await settingRow.boundingBox();
+ const settingLabel = advancedSettings.getByTestId("task-create-dependency-setting-label");
+ const settingLabelBox = await settingLabel.boundingBox();
+ const selectorContainer = advancedSettings.getByTestId(
+ "task-create-dependency-selector-container",
+ );
+ const selectorContainerBox = await selectorContainer.boundingBox();
+ expect(settingGridBox).not.toBeNull();
+ expect(settingRowBox).not.toBeNull();
+ expect(settingLabelBox).not.toBeNull();
+ expect(selectorContainerBox).not.toBeNull();
+ expect(settingRowBox!.width).toBeLessThan(settingGridBox!.width * 0.75);
+ expect(selectorContainerBox!.width).toBeLessThan(settingGridBox!.width * 0.75);
+ expect(selectorContainerBox!.x).toBeGreaterThan(settingLabelBox!.x + settingLabelBox!.width);
+ expect(Math.abs(selectorContainerBox!.y - settingLabelBox!.y)).toBeLessThanOrEqual(4);
+ const settingInfo = advancedSettings.getByTestId("task-create-dependency-setting-info");
+ await settingInfo.hover();
+ await expect(testPage.locator('[data-slot="tooltip-content"]:visible').last()).toContainText(
+ "This task waits until every selected task completes successfully.",
+ );
+
+ const dependency = dialog.getByTestId(DEPENDENCY_TRIGGER);
+ await expect(dependency).toBeVisible();
+ await expect(dependency).toContainText("No dependency");
+ await dependency.click();
+
+ const picker = dialog.getByTestId("task-create-dependencies-popover");
+ await expect(picker).toBeVisible();
+ const info = picker.getByTestId("task-create-dependency-info");
+ await expect(info).toBeVisible();
+ await info.hover();
+ await expect(testPage.locator('[data-slot="tooltip-content"]:visible').last()).toContainText(
+ "This task waits until every selected task completes successfully.",
+ );
+
+ const search = picker.getByPlaceholder("Search tasks...");
+ await search.fill("Dependency Alpha");
+ const alphaOption = picker.getByTestId(`${DEPENDENCY_OPTION_PREFIX}${alpha.id}`);
+ await expect(alphaOption).toBeVisible();
+ await expect(alphaOption.getByTestId("task-create-dependency-task-icon")).toBeVisible();
+ await expect(picker.getByText("Archived dependency")).toHaveCount(0);
+ await alphaOption.click();
+ await expect(dependency).toContainText("Dependency Alpha");
+
+ await search.fill("Dependency Beta");
+ const betaOption = picker.getByTestId(`${DEPENDENCY_OPTION_PREFIX}${beta.id}`);
+ await expect(betaOption).toBeVisible();
+ await betaOption.click();
+ await expect(dependency).toContainText("2 dependencies");
+
+ await search.fill("");
+ await picker.getByTestId("task-create-no-dependency").click();
+ await expect(dependency).toContainText("No dependency");
+
+ await dependency.click();
+ await search.fill("Dependency Alpha");
+ await picker.getByTestId(`${DEPENDENCY_OPTION_PREFIX}${alpha.id}`).click();
+ await search.fill("Dependency Beta");
+ await picker.getByTestId(`${DEPENDENCY_OPTION_PREFIX}${beta.id}`).click();
+ await testPage.keyboard.press("Escape");
+
+ await dialog.getByTestId("task-title-input").fill("Task with two dependencies");
+ await dialog
+ .getByTestId("task-description-input")
+ .fill("Created from the dependency selector");
+ await expect(dialog.getByTestId("submit-start-agent")).toBeEnabled({ timeout: 30_000 });
+ await dialog.getByTestId("submit-start-agent-chevron").click();
+ await testPage.getByTestId("submit-create-without-agent").click();
+ await expect(dialog).not.toBeVisible({ timeout: 15_000 });
+ await expect(testPage).toHaveURL(/\/t\//, { timeout: 15_000 });
+
+ const createdTask = await apiClient.getTask(taskIdFromUrl(testPage.url()));
+ const dependencies = await apiClient.getTaskDependencies(createdTask.id);
+ expect(dependencies.depends_on).toHaveLength(2);
+ expect(dependencies.depends_on?.map((dependencyRef) => dependencyRef.id)).toEqual(
+ expect.arrayContaining([alpha.id, beta.id]),
+ );
+ } finally {
+ await apiClient.deleteWorkflow(extraWorkflow.id).catch(() => {});
+ }
+ });
+});
diff --git a/apps/web/e2e/tests/task/mobile-create-task-dependency-selector.spec.ts b/apps/web/e2e/tests/task/mobile-create-task-dependency-selector.spec.ts
new file mode 100644
index 0000000000..05e9af609e
--- /dev/null
+++ b/apps/web/e2e/tests/task/mobile-create-task-dependency-selector.spec.ts
@@ -0,0 +1,95 @@
+import { expect, test } from "../../fixtures/test-base";
+import {
+ assertLocatorWithinViewportX,
+ assertNoDocumentHorizontalOverflow,
+ assertNoElementHorizontalOverflow,
+} from "../../helpers/layout-assertions";
+import { useRegularMode } from "../../helpers/regular-mode";
+import { MobileKanbanPage } from "../../pages/mobile-kanban-page";
+
+useRegularMode();
+
+test.describe("Create task dependency selector on mobile", () => {
+ test("keeps the selector contained and supports touch selection and help", async ({
+ testPage,
+ apiClient,
+ seedData,
+ }) => {
+ const predecessor = await apiClient.createTask(
+ seedData.workspaceId,
+ "Mobile dependency predecessor with a long title",
+ {
+ workflow_id: seedData.workflowId,
+ workflow_step_id: seedData.startStepId,
+ repository_ids: [seedData.repositoryId],
+ },
+ );
+
+ const mobile = new MobileKanbanPage(testPage);
+ await mobile.goto();
+ await mobile.mobileFab.tap();
+
+ const dialog = testPage.getByTestId("create-task-dialog");
+ await expect(dialog).toBeVisible();
+ const advancedTrigger = dialog.getByTestId("task-create-advanced-settings-trigger");
+ const advancedTriggerBox = await advancedTrigger.boundingBox();
+ expect(advancedTriggerBox).not.toBeNull();
+ expect(advancedTriggerBox!.height).toBeGreaterThanOrEqual(44);
+ await assertLocatorWithinViewportX(advancedTrigger, "mobile advanced settings trigger");
+ await expect(dialog.getByTestId("task-create-dependencies-trigger")).toHaveCount(0);
+
+ await advancedTrigger.tap();
+ await expect(advancedTrigger).toHaveAttribute("aria-expanded", "true");
+ const settingLabel = dialog.getByTestId("task-create-dependency-setting-label");
+ await expect(settingLabel).toContainText("Depends on");
+ const settingRow = dialog.getByTestId("task-create-dependency-setting-row");
+ const settingRowBox = await settingRow.boundingBox();
+ const settingLabelBox = await settingLabel.boundingBox();
+ const selectorContainer = dialog.getByTestId("task-create-dependency-selector-container");
+ const selectorContainerBox = await selectorContainer.boundingBox();
+ expect(settingRowBox).not.toBeNull();
+ expect(settingLabelBox).not.toBeNull();
+ expect(selectorContainerBox).not.toBeNull();
+ expect(selectorContainerBox!.x).toBeGreaterThan(settingLabelBox!.x + settingLabelBox!.width);
+ expect(Math.abs(selectorContainerBox!.y - settingLabelBox!.y)).toBeLessThanOrEqual(4);
+ const settingInfo = dialog.getByTestId("task-create-dependency-setting-info");
+ const settingInfoBox = await settingInfo.boundingBox();
+ expect(settingInfoBox).not.toBeNull();
+ expect(settingInfoBox!.height).toBeGreaterThanOrEqual(44);
+ expect(settingInfoBox!.width).toBeGreaterThanOrEqual(44);
+ await settingInfo.tap();
+ await expect(testPage.locator('[data-slot="tooltip-content"]:visible').last()).toContainText(
+ "This task waits until every selected task completes successfully.",
+ );
+ const trigger = dialog.getByTestId("task-create-dependencies-trigger");
+ const triggerBox = await trigger.boundingBox();
+ expect(triggerBox).not.toBeNull();
+ expect(triggerBox!.height).toBeGreaterThanOrEqual(44);
+ await assertLocatorWithinViewportX(trigger, "mobile dependency trigger");
+ await assertNoElementHorizontalOverflow(trigger, "mobile dependency trigger text");
+
+ await trigger.tap();
+ const picker = dialog.getByTestId("task-create-dependencies-popover");
+ await expect(picker).toBeVisible();
+ await assertLocatorWithinViewportX(picker, "mobile dependency picker");
+ await assertNoElementHorizontalOverflow(picker, "mobile dependency picker");
+ await assertNoDocumentHorizontalOverflow(testPage, "mobile dependency picker");
+
+ const info = picker.getByTestId("task-create-dependency-info");
+ const infoBox = await info.boundingBox();
+ expect(infoBox).not.toBeNull();
+ expect(infoBox!.height).toBeGreaterThanOrEqual(44);
+ expect(infoBox!.width).toBeGreaterThanOrEqual(44);
+ await info.tap();
+ await expect(testPage.locator('[data-slot="tooltip-content"]:visible').last()).toContainText(
+ "This task waits until every selected task completes successfully.",
+ );
+
+ const option = picker.getByTestId(`task-create-dependency-option-${predecessor.id}`);
+ await expect(option).toBeVisible();
+ await expect(option.getByTestId("task-create-dependency-task-icon")).toBeVisible();
+ await option.tap();
+ await expect(trigger).toContainText("Mobile dependency predecessor");
+ await assertNoDocumentHorizontalOverflow(testPage, "mobile dependency selection");
+ });
+});
diff --git a/apps/web/src/locales/en/task.json b/apps/web/src/locales/en/task.json
index ce01c0b7b5..69acd45ca8 100644
--- a/apps/web/src/locales/en/task.json
+++ b/apps/web/src/locales/en/task.json
@@ -41,6 +41,7 @@
"addedRemoved": "{{added}} added · {{removed}} removed",
"adding": "Adding…",
"advanced": "Advanced",
+ "advancedSettings": "Advanced settings",
"afterDuration": " after {{duration}}",
"agent": "Agent",
"agentBootFailedToResume": "Failed to resume agent {{agentName}}",
@@ -340,6 +341,10 @@
"dependencyCountBlockedBy_other": "{{count}} blockers",
"dependencyCountBlocks_one": "blocks {{count}}",
"dependencyCountBlocks_other": "blocks {{count}}",
+ "dependencyCount_one": "{{count}} dependency",
+ "dependencyCount_other": "{{count}} dependencies",
+ "dependencyInfo": "This task waits until every selected task completes successfully. If you start an agent, it starts automatically when all dependencies are resolved.",
+ "dependencyInfoLabel": "About task dependencies",
"dependsOn": "Depends on",
"dependsOnWillAutoStart": "This task waits for the tasks above. If you start an agent, it runs automatically once every one of them completes successfully.",
"describeWhatNeedsToChange": "Describe what needs to change",
@@ -794,6 +799,7 @@
"noContent": "No content",
"noDecisionYet": "No decision yet",
"noDependencies": "No dependencies",
+ "noDependency": "No dependency",
"noDocumentsFound": "No documents found.",
"noDocumentsYet": "No documents yet.",
"noEditorsAvailable": "No editors available",
diff --git a/apps/web/src/locales/pseudo/task.json b/apps/web/src/locales/pseudo/task.json
index 4385211214..ed817e2b47 100644
--- a/apps/web/src/locales/pseudo/task.json
+++ b/apps/web/src/locales/pseudo/task.json
@@ -41,6 +41,7 @@
"addedRemoved": "{{added}} àďďēď · {{removed}} ŕēḿōvēď",
"adding": "Àďďĩńĝ…",
"advanced": "Àďvàńćēď",
+ "advancedSettings": "Àďvàńćēď śēţţĩńĝś",
"afterDuration": " àƒţēŕ {{duration}}",
"agent": "Àĝēńţ",
"agentBootFailedToResume": "Ƒàĩĺēď ţō ŕēśũḿē àĝēńţ {{agentName}}",
@@ -340,6 +341,10 @@
"dependencyCountBlockedBy_other": "{{count}} ƀĺōćķēŕś",
"dependencyCountBlocks_one": "ƀĺōćķś {{count}}",
"dependencyCountBlocks_other": "ƀĺōćķś {{count}}",
+ "dependencyCount_one": "{{count}} ďēƥēńďēńćŷ",
+ "dependencyCount_other": "{{count}} ďēƥēńďēńćĩēś",
+ "dependencyInfo": "Ţĥĩś ţàśķ ŵàĩţś ũńţĩĺ ēvēŕŷ śēĺēćţēď ţàśķ ćōḿƥĺēţēś śũććēśśƒũĺĺŷ. Ĩƒ ŷōũ śţàŕţ àń àĝēńţ, ĩţ śţàŕţś àũţōḿàţĩćàĺĺŷ ŵĥēń àĺĺ ďēƥēńďēńćĩēś àŕē ŕēśōĺvēď.",
+ "dependencyInfoLabel": "Àƀōũţ ţàśķ ďēƥēńďēńćĩēś",
"dependsOn": "Ďēƥēńďś ōń",
"dependsOnWillAutoStart": "Ţĥĩś ţàśķ ŵàĩţś ƒōŕ ţĥē ţàśķś àƀōvē. Ĩƒ ŷōũ śţàŕţ àń àĝēńţ, ĩţ ŕũńś àũţōḿàţĩćàĺĺŷ ōńćē ēvēŕŷ ōńē ōƒ ţĥēḿ ćōḿƥĺēţēś śũććēśśƒũĺĺŷ.",
"describeWhatNeedsToChange": "Ďēśćŕĩƀē ŵĥàţ ńēēďś ţō ćĥàńĝē",
@@ -794,6 +799,7 @@
"noContent": "Ńō ćōńţēńţ",
"noDecisionYet": "Ńō ďēćĩśĩōń ŷēţ",
"noDependencies": "Ńō ďēƥēńďēńćĩēś",
+ "noDependency": "Ńō ďēƥēńďēńćŷ",
"noDocumentsFound": "Ńō ďōćũḿēńţś ƒōũńď.",
"noDocumentsYet": "Ńō ďōćũḿēńţś ŷēţ.",
"noEditorsAvailable": "Ńō ēďĩţōŕś àvàĩĺàƀĺē",
diff --git a/docs/plans/task-create-advanced-settings/plan.md b/docs/plans/task-create-advanced-settings/plan.md
new file mode 100644
index 0000000000..5c24f4747e
--- /dev/null
+++ b/docs/plans/task-create-advanced-settings/plan.md
@@ -0,0 +1,133 @@
+---
+spec: docs/specs/task-dependencies/create-dialog-advanced-settings.md
+created: 2026-08-13
+status: implemented
+---
+
+# Implementation Plan: Task-create advanced settings disclosure
+
+## Overview
+
+Wrap the existing task-create dependency selector in a compact, collapsed
+advanced-settings disclosure. Keep dependency state, selector behavior, and
+the `blocked_by` payload unchanged while reducing the default form height and
+leaving a contained region for future uncommon create options.
+
+This is a frontend-only presentation change. It builds on the implemented
+dependency selector refinement in
+`docs/specs/task-dependencies/create-dialog-dependency-selector.md` and does
+not change the backend, API client, persistence, or WebSocket contracts.
+
+## Frontend composition
+
+### Advanced settings component
+
+- Add a focused `TaskCreateAdvancedSettings` component in
+ `apps/web/components/task-create-dialog-advanced-settings.tsx`.
+- Use the existing `@kandev/ui/collapsible` primitive. Keep the disclosure
+ uncontrolled or locally controlled with a collapsed initial value so its
+ open state is presentation-only and does not enter `DialogFormState`.
+- Render a semantic trigger with localized `Advanced settings` copy, muted
+ styling, a very subtle text size, a direction indicator, `aria-expanded`,
+ and a mobile hitbox of at least 44 CSS pixels.
+- Render the existing `TaskCreateDependencies` in a responsive option grid
+ with the localized `Depends on` label and contextual help to the left of the
+ selector in the same column. Use two columns on desktop so future advanced options can
+ share a row, and collapse to one column on narrow screens. Keep the content
+ wrapper ready for future sibling controls without introducing a speculative
+ registry or new state shape.
+- Preserve the dependency selector's `value`, `onChange`, and disabled props.
+
+### Dialog placement
+
+- Update `apps/web/components/task-create-dialog.tsx` so the advanced section
+ renders at the bottom of the create-task form, below the model, executor, and
+ workflow selector controls.
+- Keep `renderWorkflowSection` and all workflow visibility, locking, and
+ single-workflow override behavior unchanged. Refactor the old paired
+ workflow/dependency wrapper into a workflow-only render path if needed, then
+ mount the advanced section where the dependency slot was previously shown.
+- Keep the advanced component out of session mode, edit mode, and started-task
+ rendering.
+- Keep the dialog body as the only outer form scroll owner. Do not add a nested
+ scrolling container around the disclosure.
+
+### Localization
+
+- Add the new trigger label to
+ `apps/web/src/locales/en/task.json`.
+- Regenerate or update `apps/web/src/locales/pseudo/task.json` using the
+ repository's i18n tooling.
+- Add other locale values only through the repository's established catalog
+ workflow. Do not hardcode the label in JSX or tests that exercise translated
+ rendering.
+
+## Tests
+
+### Component tests
+
+- Add `apps/web/components/task-create-dialog-advanced-settings.test.tsx` for
+ the default collapsed state, expanded state, semantic attributes, touch-safe
+ trigger class, dependency label/help, dependency mounting, and state
+ preservation across collapse and reopen.
+- Update
+ `apps/web/components/task-create-dialog-form-body.test.tsx` to cover the
+ workflow-only path and ensure the advanced dependency section does not remove
+ workflow visibility rules.
+- Keep the existing
+ `apps/web/components/task-create-dialog-dependencies.test.tsx` coverage
+ green. It remains the source of truth for selector internals.
+- Preserve existing payload tests for multiple `blockedBy` IDs and the empty
+ array case.
+
+## E2E tests
+
+- Extend `apps/web/e2e/tests/task/create-task-dependency-selector.spec.ts` to
+ assert that the create dialog starts with a collapsed advanced row below the
+ model, executor, and workflow controls, the dependency trigger is hidden
+ until expansion, the labeled setting help is available, and the existing
+ selection and create-payload behavior remains intact.
+- Extend `apps/web/e2e/tests/task/mobile-create-task-dependency-selector.spec.ts`
+ to tap the advanced row before opening the dependency selector, check the
+ row's touch box and expanded state, and retain picker containment, help,
+ touch selection, and horizontal-overflow assertions.
+- Use existing managed `chromium` and `mobile-chrome` projects. No container
+ or backend behavior is required for this presentation change beyond the
+ existing task-create fixture.
+
+## Implementation waves
+
+Wave 1 (sequential):
+
+- [x] [Task 01: Add the advanced settings disclosure](task-01-advanced-settings-ui.md)
+
+Wave 2 (sequential, depends on Task 01):
+
+- [x] [Task 02: Verify disclosure behavior on desktop and mobile](task-02-advanced-settings-e2e.md)
+
+No task is parallel-safe because the browser selectors and placement depend on
+the final component composition.
+
+## Verification commands
+
+The implementation task owns focused component, typecheck, lint, i18n, and
+diff checks. The E2E task owns the managed desktop and mobile browser runs.
+The exact commands are recorded in the individual task files.
+
+## Open questions
+
+None. The disclosure is intentionally limited to presentation state, and the
+existing dependency selector remains the only advanced option in this change.
+
+## Verification results
+
+- Component tests: 40 tests passed across the advanced-settings, form-body,
+ dependency-selector, and helper suites.
+- TypeScript typecheck, focused ESLint, `i18n:check`, `i18n:ratchet`, and
+ `git diff --check` passed. `i18n:check` still reports the repository's
+ existing advisory pt-pt and zh-cn catalog parity findings.
+- Managed Chromium E2E passed for collapsed-by-default rendering, expansion,
+ dependency selection, clearing, help, search, and persistence.
+- Managed mobile-chrome E2E passed for touch expansion, the 44 CSS pixel
+ disclosure hitbox, picker containment, help, selection, and horizontal
+ overflow.
diff --git a/docs/plans/task-create-advanced-settings/task-01-advanced-settings-ui.md b/docs/plans/task-create-advanced-settings/task-01-advanced-settings-ui.md
new file mode 100644
index 0000000000..73c2b90517
--- /dev/null
+++ b/docs/plans/task-create-advanced-settings/task-01-advanced-settings-ui.md
@@ -0,0 +1,113 @@
+---
+id: "01-advanced-settings-ui"
+title: "Add the advanced settings disclosure"
+status: completed
+wave: 1
+depends_on: []
+plan: "plan.md"
+spec: "../../specs/task-dependencies/create-dialog-advanced-settings.md"
+---
+
+# Task 01: Add the advanced settings disclosure
+
+Implement the compact collapsed disclosure around the existing task-create
+dependency selector. Preserve the current workflow behavior, dependency state,
+selector semantics, and payload path.
+
+## Acceptance
+
+- A create-mode, unstarted task dialog shows a localized, muted, very small
+ `Advanced settings` trigger at the bottom of the form, below the model,
+ executor, and workflow selector controls, and the trigger is collapsed by
+ default.
+- The trigger is a semantic collapsible control with `aria-expanded`, a stable
+ test identity, and a mobile hitbox of at least 44 CSS pixels.
+- The dependency selector is absent while collapsed and appears inside the
+ expanded content with the existing `No dependency` default, icon, picker,
+ task rows, info help, and multi-selection behavior. The expanded content uses
+ a two-column desktop option grid, with the localized `Depends on` label and
+ contextual help to the left of the selector in the same column. The grid
+ collapses to one column on narrow screens.
+- Collapsing and reopening the section does not clear selected predecessor IDs.
+- Workflow visibility, workflow locking, agent/executor behavior, and the
+ existing `blockedBy` to `blocked_by` payload path remain unchanged.
+- Session mode, edit mode, and started-task forms do not gain the disclosure.
+- New copy is localized in the task namespace, and English plus pseudo catalogs
+ pass the repository checks.
+- Component tests cover collapsed and expanded rendering, semantic state,
+ touch-safe sizing, selector mounting, and selection persistence.
+
+## TDD sequence
+
+1. Add failing component tests for collapsed state, expansion, and persistence.
+2. Add the disclosure component and wire it into the existing dependency area.
+3. Refactor workflow rendering only as needed to keep its behavior independent
+ from the dependency presentation.
+4. Add localized copy, run focused tests, then clean up styling and test IDs.
+
+## Verification
+
+```bash
+cd apps
+pnpm install --frozen-lockfile
+pnpm --filter @kandev/web test -- task-create-dialog-advanced-settings task-create-dialog-form-body task-create-dialog-dependencies task-create-dialog-helpers
+pnpm --filter @kandev/web run typecheck
+pnpm --filter @kandev/web exec eslint --max-warnings 0 components/task-create-dialog-advanced-settings.tsx components/task-create-dialog-advanced-settings.test.tsx components/task-create-dialog-form-body.tsx components/task-create-dialog-form-body.test.tsx components/task-create-dialog.tsx
+pnpm --filter @kandev/web run i18n:check
+pnpm --filter @kandev/web run i18n:ratchet
+git diff --check
+```
+
+## Files likely touched
+
+- `apps/web/components/task-create-dialog-advanced-settings.tsx`
+- `apps/web/components/task-create-dialog-advanced-settings.test.tsx`
+- `apps/web/components/task-create-dialog-form-body.tsx`
+- `apps/web/components/task-create-dialog-form-body.test.tsx`
+- `apps/web/components/task-create-dialog.tsx`
+- `apps/web/src/locales/en/task.json`
+- `apps/web/src/locales/pseudo/task.json`
+
+## Dependencies and risks
+
+None. This task depends on the implemented dependency selector and should not
+change its API. The main risk is accidentally moving or hiding the workflow
+selector while extracting the old paired row, so the workflow visibility tests
+must remain explicit.
+
+## Parallelism
+
+`sequential`. The disclosure placement and component contract define the E2E
+selectors used by Task 02.
+
+## Inputs
+
+- Spec: `docs/specs/task-dependencies/create-dialog-advanced-settings.md`
+- Plan: `docs/plans/task-create-advanced-settings/plan.md`
+- Existing dependency behavior in
+ `apps/web/components/task-create-dialog-dependencies.tsx`
+- Existing workflow rendering in
+ `apps/web/components/task-create-dialog-form-body.tsx`
+- Existing mobile picker and touch-target expectations in the implemented
+ dependency selector tests
+
+## Output contract
+
+Report the component and dialog files changed, focused test results, i18n and
+typecheck results, any placement or accessibility risks, and the updated task
+and plan status before starting Task 02.
+
+## Results
+
+- Added `TaskCreateAdvancedSettings` as an inline, collapsed disclosure below
+ the model, executor, and workflow controls. It keeps the dependency selector
+ inside an extensible content region, labels the setting with contextual help,
+ and preserves `blockedBy` state and disabled behavior.
+- Kept workflow rendering independent and unchanged for its existing visibility,
+ locking, and single-workflow rules.
+- Added localized English and pseudo-locale copy plus component coverage for
+ collapsed and expanded semantics, the mobile-safe hitbox, dependency
+ mounting, state persistence, and unavailable modes.
+- Focused component tests passed: 40 tests. Typecheck, focused ESLint, i18n
+ checks, and `git diff --check` passed. No remaining placement or accessibility
+ risk was found after the managed mobile run validated the 44 CSS pixel target.
diff --git a/docs/plans/task-create-advanced-settings/task-02-advanced-settings-e2e.md b/docs/plans/task-create-advanced-settings/task-02-advanced-settings-e2e.md
new file mode 100644
index 0000000000..67a435cba8
--- /dev/null
+++ b/docs/plans/task-create-advanced-settings/task-02-advanced-settings-e2e.md
@@ -0,0 +1,85 @@
+---
+id: "02-advanced-settings-e2e"
+title: "Verify disclosure behavior on desktop and mobile"
+status: completed
+wave: 2
+depends_on: ["01-advanced-settings-ui"]
+plan: "plan.md"
+spec: "../../specs/task-dependencies/create-dialog-advanced-settings.md"
+---
+
+# Task 02: Verify disclosure behavior on desktop and mobile
+
+Extend the existing dependency-selector browser coverage to prove the new
+collapsed default, expansion path, mobile touch behavior, and unchanged task
+creation payload.
+
+## Acceptance
+
+- Desktop E2E proves the advanced row is collapsed on first render below the
+ model, executor, and workflow controls, the dependency trigger is hidden
+ until expansion, and the selector appears after expansion.
+- Desktop E2E keeps the existing selector checks for the `No dependency`
+ default, labeled setting help, task icons, search, info help, multiple
+ selection, clearing, and `blocked_by` persistence after creation. It also
+ verifies the two-column option grid keeps the label to the left of the selector
+ on the same horizontal row and makes the option narrower than the full desktop grid.
+- Mobile E2E expands the section with touch input, verifies the disclosure hit
+ box and setting help control are at least 44 CSS pixels, verifies the label
+ and selector remain on the same horizontal row with the label to the selector's
+ left, and retains picker containment, touch
+ selection, help readability, and no-horizontal-overflow checks.
+- The managed desktop and mobile runs pass against a fresh production build
+ with no stale frontend artifacts.
+
+## Verification
+
+```bash
+cd apps
+pnpm install --frozen-lockfile
+cd web
+pnpm e2e:run --project chromium e2e/tests/task/create-task-dependency-selector.spec.ts
+pnpm e2e:run --project mobile-chrome e2e/tests/task/mobile-create-task-dependency-selector.spec.ts
+```
+
+## Files likely touched
+
+- `apps/web/e2e/tests/task/create-task-dependency-selector.spec.ts`
+- `apps/web/e2e/tests/task/mobile-create-task-dependency-selector.spec.ts`
+
+## Dependencies and risks
+
+Task 01. The exact disclosure test ID and final placement are outputs of the UI
+implementation. If the mobile hitbox is reduced because the visual label is
+small, the E2E test should catch it before the change is considered complete.
+
+## Parallelism
+
+`sequential` after Task 01. The E2E files are independent of backend changes,
+but they depend on the final UI contract.
+
+## Inputs
+
+- Scenarios and mobile contract in
+ `docs/specs/task-dependencies/create-dialog-advanced-settings.md`
+- Existing desktop coverage in
+ `apps/web/e2e/tests/task/create-task-dependency-selector.spec.ts`
+- Existing mobile coverage in
+ `apps/web/e2e/tests/task/mobile-create-task-dependency-selector.spec.ts`
+- Layout helpers in `apps/web/e2e/helpers/layout-assertions.ts`
+
+## Output contract
+
+Report the exact managed commands, pass counts, viewport and overflow results,
+artifacts, blockers, and the final Task 02 and plan status.
+
+## Results
+
+- `pnpm e2e:run --project chromium e2e/tests/task/create-task-dependency-selector.spec.ts`
+ passed 1 test on a fresh production build.
+- `pnpm e2e:run --project mobile-chrome e2e/tests/task/mobile-create-task-dependency-selector.spec.ts`
+ passed 1 test on a fresh production build. The test covered the 44 CSS pixel
+ disclosure hitbox, picker containment, touch selection, help readability,
+ and no horizontal overflow.
+- No E2E artifacts or blockers remain. The runner cleaned its temporary fixture
+ and test-result directories after each managed run.
diff --git a/docs/plans/task-create-dependency-selector/plan.md b/docs/plans/task-create-dependency-selector/plan.md
new file mode 100644
index 0000000000..5b5f6783c6
--- /dev/null
+++ b/docs/plans/task-create-dependency-selector/plan.md
@@ -0,0 +1,151 @@
+---
+spec: docs/specs/task-dependencies/create-dialog-dependency-selector.md
+created: 2026-08-13
+status: implemented
+---
+
+# Implementation Plan: Task-create dependency selector refinement
+
+## Overview
+
+Replace the task-create dialog's separate dependency action and chips with one
+searchable, multi-select control that matches the agent and executor selector
+visual language. Pair it with the workflow selector on desktop and keep the
+same data derivation and `blocked_by` submission path. Add focused component
+tests plus desktop and mobile browser coverage for selection, teaching copy,
+placement, and viewport containment.
+
+This is a frontend-only refinement. It does not change dependency persistence,
+the task API, or the existing `blockedBy` state shape.
+
+## Frontend
+
+### Dependency selector
+
+- `apps/web/components/task-create-dialog-dependencies.tsx`
+ - Replace the separate label, Add dependency button, and removable chips with
+ one full-width selector trigger.
+ - Preserve `useBoardTasks`, archived-task filtering, and both board-slice
+ sources.
+ - Keep multi-predecessor toggling in `blockedBy`, add the `No dependency`
+ clearing entry, task icons, selected-state indicators, and localized
+ trigger summaries.
+ - Add the search-row info action with an accessible tooltip/help message and
+ stable test IDs for the trigger, dropdown, task entries, and help control.
+
+### Workflow/dependency layout
+
+- `apps/web/components/task-create-dialog.tsx`
+ - Stop rendering the dependency control as an independent block below the
+ agent and executor row.
+- `apps/web/components/task-create-dialog-form-body.tsx`
+ - Render the workflow and dependency controls in a shared responsive row.
+ - Keep the dependency selector visible when the workflow selector is hidden
+ for a single enforced workflow or a locked workflow.
+ - Stack workflow first and dependency second below the mobile breakpoint.
+
+### Localization
+
+- `apps/web/src/locales/en/task.json`
+- `apps/web/src/locales/pseudo/task.json` (regenerated with the repository
+ pseudo-locale script)
+
+Add the default label, search placeholder, empty result, dependency count, and
+help text. Keep all copy in the task namespace and remove or leave legacy keys
+only after checking for other consumers.
+
+## State and API
+
+No state shape, API client, backend, persistence, or WebSocket changes. The
+selector continues to call `onChange` with the complete predecessor ID array,
+and `buildCreateTaskPayload` continues to emit `blocked_by` only when the array
+is non-empty.
+
+## Tests
+
+- **What:** The dependency selector shows its no-dependency default, toggles
+ several task entries, clears all entries, excludes archived tasks, renders
+ task icons, and exposes the info help control.
+ **File:** `apps/web/components/task-create-dialog-dependencies.test.tsx`
+ **How:** Render the component with mocked Kanban board and snapshot state;
+ interact with the command menu and assert `onChange` values and visible
+ labels/test IDs.
+- **What:** Workflow and dependency controls share the desktop row while the
+ dependency control remains visible without a workflow trigger.
+ **File:** `apps/web/components/task-create-dialog-form-body.test.tsx`
+ **How:** Render `WorkflowSection` or the extracted paired row with both a
+ visible workflow and a single enforced workflow; assert the dependency slot
+ remains present and ordering is stable.
+- **What:** Existing create payload behavior remains intact for multiple
+ predecessors.
+ **File:** `apps/web/components/task-create-dialog-helpers.test.ts`
+ **How:** Retain and, if needed, extend the pure payload test for two
+ `blockedBy` IDs and the omitted empty-array case.
+
+## E2E Tests
+
+- **Scenario:** GIVEN two non-archived predecessor tasks, WHEN the user opens
+ the desktop create dialog, searches for both, and toggles both entries, THEN
+ the single dependency trigger shows the selected count and the created task
+ reports both predecessor IDs.
+ **File:** `apps/web/e2e/tests/task/create-task-dependency-selector.spec.ts`
+ **What to verify:** Default `No dependency` state, workflow/dependency row,
+ task icons, search, info help, multi-selection, and `blocked_by` persistence
+ after UI submission.
+- **Scenario:** GIVEN a Pixel 5 viewport, WHEN the user opens the task-create
+ dialog and dependency picker, THEN the selector and help action are
+ touch-usable, the picker is contained, and the document has no horizontal
+ overflow.
+ **File:** `apps/web/e2e/tests/task/mobile-create-task-dependency-selector.spec.ts`
+ **What to verify:** Full-width mobile trigger, `.tap()` selection, readable
+ help content, picker containment, 44px active controls, and overflow safety.
+
+## Mobile parity contract
+
+- Desktop outcome: choose zero or more predecessor tasks while creating a task.
+- Mobile entry point: the dependency selector in the create dialog's form,
+ immediately after the workflow context.
+- Closest exemplar: mobile task-create repository picker / `Pill` command
+ surface for contained search, touch targets, and overflow checks.
+- Mobile primary action: open the dependency selector and toggle task rows.
+- Presentation: one full-width trigger and a contained searchable popover; no
+ desktop-only hover path is required for selecting a dependency.
+- Scroll ownership: the command list owns long candidate scrolling; the dialog
+ body owns form scrolling when the popover is closed.
+- Shared logic: task candidates, archived filtering, selected IDs, and payload
+ state are shared between desktop and mobile.
+
+## Verification Results
+
+- Focused frontend unit tests passed: `pnpm --filter @kandev/web test --
+ task-create-dialog-dependencies task-create-dialog-form-body
+ task-create-dialog-helpers` (4 files, 62 tests).
+- Frontend typecheck passed: `pnpm run typecheck` from `apps/web`.
+- Focused frontend and E2E-file ESLint passed with `--max-warnings 0`.
+- `pnpm run i18n:check` passed with the repository's existing real-locale
+ parity advisories; `pnpm run i18n:ratchet` passed with zero new violations.
+- `git diff --check` passed.
+- Desktop managed E2E passed: `pnpm e2e:run --project chromium
+ e2e/tests/task/create-task-dependency-selector.spec.ts` (1 test).
+- Mobile managed E2E passed: `pnpm e2e:run --project mobile-chrome
+ e2e/tests/task/mobile-create-task-dependency-selector.spec.ts` (1 test).
+- The first mobile run found a 43.56px rem-based trigger; the final 48px
+ mobile control sizing and rerun passed.
+
+## Implementation Waves And Parallel Candidates
+
+Wave 1 (sequential):
+
+- [x] [Task 01: Implement the selector and layout](task-01-selector-ui.md)
+
+Wave 2 (sequential, depends on Task 01):
+
+- [x] [Task 02: Verify desktop and mobile flows](task-02-selector-e2e.md)
+
+No task is parallel-safe because the browser coverage depends on the final
+selector test IDs and responsive composition.
+
+## Open Questions
+
+None. The selector preserves multiple predecessor selection after user
+confirmation.
diff --git a/docs/plans/task-create-dependency-selector/task-01-selector-ui.md b/docs/plans/task-create-dependency-selector/task-01-selector-ui.md
new file mode 100644
index 0000000000..6e443272d4
--- /dev/null
+++ b/docs/plans/task-create-dependency-selector/task-01-selector-ui.md
@@ -0,0 +1,103 @@
+---
+id: "01-selector-ui"
+title: "Implement the selector and layout"
+status: completed
+wave: 1
+depends_on: []
+plan: "plan.md"
+spec: "../../specs/task-dependencies/create-dialog-dependency-selector.md"
+---
+
+# Task 01: Implement the selector and layout
+
+Implement the searchable multi-select dependency control and pair it with the
+workflow selector while preserving the existing `blockedBy` state and payload.
+
+## Acceptance
+
+- The create dialog shows one dependency selector with the `No dependency`
+ default, task icons, archived-task filtering, multiple selection, clear-all
+ behavior, and an info help control beside the search field.
+- The workflow and dependency controls share a desktop row and stack in the
+ intended order on mobile. The dependency selector remains present when the
+ workflow picker is hidden or locked.
+- Component tests cover selection, clearing, task candidates, help copy, and
+ layout visibility. New copy is localized in English and pseudo catalogs, and
+ the existing `blocked_by` payload tests remain green.
+
+## Verification
+
+```bash
+cd apps
+pnpm install --frozen-lockfile
+pnpm --filter @kandev/web test -- task-create-dialog-dependencies task-create-dialog-form-body task-create-dialog-helpers
+pnpm --filter @kandev/web run typecheck
+pnpm --filter @kandev/web lint
+pnpm --filter @kandev/web run i18n:check
+pnpm --filter @kandev/web run i18n:ratchet
+```
+
+## Files likely touched
+
+- `apps/web/components/task-create-dialog-dependencies.tsx`
+- `apps/web/components/task-create-dialog.tsx`
+- `apps/web/components/task-create-dialog-form-body.tsx`
+- `apps/web/components/task-create-dialog-dependencies.test.tsx`
+- `apps/web/components/task-create-dialog-form-body.test.tsx`
+- `apps/web/components/task-create-dialog-helpers.test.ts`
+- `apps/web/src/locales/en/task.json`
+- `apps/web/src/locales/pseudo/task.json`
+
+## Dependencies
+
+None.
+
+## Parallelism
+
+`sequential`. The layout and selector share the same dialog composition and
+must be verified together.
+
+## Inputs
+
+- Spec: `docs/specs/task-dependencies/create-dialog-dependency-selector.md`
+- Plan: `docs/plans/task-create-dependency-selector/plan.md`, Frontend and
+ Mobile parity sections
+- Existing candidate derivation and payload behavior in
+ `task-create-dialog-dependencies.tsx` and
+ `task-create-dialog-helpers.ts`
+- Existing selector and mobile picker patterns in `combobox.tsx`,
+ `task-create-dialog-selectors.tsx`, and `task-create-dialog-pill.tsx`
+
+## Results
+
+- Implemented the full-width searchable multi-select selector with a `No
+ dependency` trigger, dependency icon, task icons, archived-task filtering,
+ clear-all entry, selected-count summaries, and an accessible tooltip beside
+ the search field.
+- Moved workflow and dependency controls into a responsive row. The workflow
+ selector renders first on desktop, the dependency selector renders second,
+ and dependencies remain visible when a single or locked workflow hides the
+ workflow picker.
+- Preserved the existing `blockedBy` state and `blocked_by` payload behavior.
+- Added `apps/web/components/task-create-dialog-dependencies.test.tsx` and
+ paired-row coverage in `task-create-dialog-form-body.test.tsx`.
+- Updated English and generated pseudo-locale task copy.
+
+Verification:
+
+```text
+pnpm --filter @kandev/web test -- task-create-dialog-dependencies task-create-dialog-form-body task-create-dialog-helpers: pass, 62 tests
+pnpm --filter @kandev/web run typecheck: pass
+pnpm exec eslint --max-warnings 0 components/task-create-dialog-dependencies.tsx components/task-create-dialog-dependencies.test.tsx components/task-create-dialog-form-body.tsx components/task-create-dialog-form-body.test.tsx components/task-create-dialog.tsx: pass
+pnpm run i18n:check: pass; existing advisory real-locale parity warnings remain
+pnpm run i18n:ratchet: pass
+git diff --check: pass
+```
+
+Remaining risk: browser coverage still needs to verify the final selector
+against the managed desktop and mobile runners.
+
+## Output contract
+
+Report the implementation summary, files changed, tests run, blockers, and
+task/plan status updates in the same conversation.
diff --git a/docs/plans/task-create-dependency-selector/task-02-selector-e2e.md b/docs/plans/task-create-dependency-selector/task-02-selector-e2e.md
new file mode 100644
index 0000000000..f86e35751c
--- /dev/null
+++ b/docs/plans/task-create-dependency-selector/task-02-selector-e2e.md
@@ -0,0 +1,82 @@
+---
+id: "02-selector-e2e"
+title: "Verify desktop and mobile flows"
+status: done
+wave: 2
+depends_on: ["01-selector-ui"]
+plan: "plan.md"
+spec: "../../specs/task-dependencies/create-dialog-dependency-selector.md"
+---
+
+# Task 02: Verify desktop and mobile flows
+
+Add browser coverage for the final dependency selector through the real task
+creation dialog and verify the mobile composition with the configured
+`mobile-chrome` project.
+
+## Acceptance
+
+- Desktop E2E proves the default state, workflow/dependency placement, task
+ icons, search, info help, multiple selection, clearing, and creation with
+ the selected `blocked_by` IDs.
+- Mobile E2E uses touch interaction to select a predecessor, verifies the help
+ action is reachable, checks picker and control containment, and proves there
+ is no document-level horizontal overflow.
+- The exact managed desktop and mobile E2E commands pass against a fresh
+ production build with no stale frontend artifacts.
+
+## Verification
+
+```bash
+cd apps
+pnpm install --frozen-lockfile
+cd web
+pnpm e2e:run --project chromium e2e/tests/task/create-task-dependency-selector.spec.ts
+pnpm e2e:run --project mobile-chrome e2e/tests/task/mobile-create-task-dependency-selector.spec.ts
+```
+
+## Files likely touched
+
+- `apps/web/e2e/tests/task/create-task-dependency-selector.spec.ts`
+- `apps/web/e2e/tests/task/mobile-create-task-dependency-selector.spec.ts`
+
+## Dependencies
+
+Task 01. The E2E selectors and responsive composition are outputs of the UI
+implementation.
+
+## Parallelism
+
+`sequential`.
+
+## Inputs
+
+- Spec scenarios and Mobile design contract in
+ `docs/specs/task-dependencies/create-dialog-dependency-selector.md`
+- Plan E2E Tests and Mobile parity contract in `plan.md`
+- `apps/web/e2e/fixtures/test-base.ts`, `pages/kanban-page.ts`, and
+ `pages/mobile-kanban-page.ts`
+- Existing task creation coverage in `apps/web/e2e/tests/task/create-task.spec.ts`
+ and mobile repository picker coverage
+
+## Results
+
+- Desktop managed E2E passed: `pnpm e2e:run --project chromium
+ e2e/tests/task/create-task-dependency-selector.spec.ts` (1 test passed in
+ 4.6s). The run rebuilt the backend and pseudo-locale Vite assets, and the
+ task creation API assertion confirmed both selected predecessor IDs.
+- Mobile managed E2E passed: `pnpm e2e:run --project mobile-chrome
+ e2e/tests/task/mobile-create-task-dependency-selector.spec.ts` (1 test
+ passed in 3.8s). The run rebuilt the backend and pseudo-locale Vite assets,
+ and verified the mobile selector, contained picker, touch selection, help
+ copy, and horizontal overflow contract.
+- The first mobile run exposed a 43.56px rem-based trigger in the configured
+ viewport. Mobile controls now use the 48px spacing step, with desktop
+ controls retaining their compact sizes. The rerun passed.
+- The managed runner cleaned its test results and PR asset directories before
+ each run. No failure artifacts remain from the passing reruns.
+
+## Output contract
+
+Report the E2E scenarios, commands, outcomes, artifacts, blockers, and
+task/plan status updates in the same conversation.
diff --git a/docs/specs/INDEX.md b/docs/specs/INDEX.md
index 334f23c39a..c00d1a698c 100644
--- a/docs/specs/INDEX.md
+++ b/docs/specs/INDEX.md
@@ -81,6 +81,8 @@ Kandev's task model: documents, execution stages, labels, blocker escalation, su
| [subtask-reparenting-drag-drop](tasks/subtask-reparenting-drag-drop.md) | building |
| [subtask-completion-trigger](tasks/subtask-completion-trigger.md) | draft |
| [task-dependencies](task-dependencies/spec.md) | draft |
+| [task-dependencies - create dialog selector](task-dependencies/create-dialog-dependency-selector.md) | implemented |
+| [task-dependencies - create dialog advanced settings](task-dependencies/create-dialog-advanced-settings.md) | shipped |
| [subtree-controls](tasks/subtree-controls.md) | shipped |
| [blocked-task-escalation](tasks/blocked-task-escalation.md) | draft |
| [runtime-cleanup](tasks/runtime-cleanup.md) | draft |
diff --git a/docs/specs/task-dependencies/create-dialog-advanced-settings.md b/docs/specs/task-dependencies/create-dialog-advanced-settings.md
new file mode 100644
index 0000000000..99a3a5f448
--- /dev/null
+++ b/docs/specs/task-dependencies/create-dialog-advanced-settings.md
@@ -0,0 +1,135 @@
+---
+status: shipped
+created: 2026-08-13
+owner: kandev
+---
+
+# Task-create advanced settings disclosure
+
+## Why
+
+The searchable dependency selector is useful, but it is not needed for most
+new tasks. Keeping it visible in the main form adds a full selector row to a
+dialog whose primary job is to collect the task request and workspace context.
+The create dialog should keep the common path compact while preserving a clear
+place for dependency selection and future less-common options.
+
+## What
+
+- Add a compact, collapsed `Advanced settings` disclosure to the bottom of the
+ create-task form, below the model, executor, and workflow selector controls.
+- Render the disclosure label in muted, very small text with a subtle chevron.
+ The whole row remains a semantic button so the small visual label does not
+ reduce the interaction target.
+- Start the disclosure collapsed for a new create-dialog instance. Expanding
+ it reveals the existing dependency selector. The selector keeps its current
+ `No dependency` default, task icon treatment, search, help action, and
+ multiple-predecessor behavior.
+- Show the dependency selector with a muted `Depends on` label and a contextual
+ help control that explains the dependency wait and automatic-start behavior.
+- Keep the label and selector in the same setting column. On desktop, render
+ advanced settings as a two-column option grid so each row can hold two
+ settings; on narrow screens, collapse the grid to one column.
+- Keep the dependency selector's `blockedBy` state and disabled behavior
+ unchanged. Collapsing the section must not clear a selected dependency, and
+ reopening the section must show the same selector value.
+- Keep the existing workflow selector and its visibility rules unchanged. The
+ new disclosure replaces only the dependency's always-visible presentation.
+- Make the expanded content a single extensible advanced-options region. Future
+ advanced controls can be appended inside that region without adding another
+ top-level row to the dialog. Do not add placeholder future controls in this
+ change.
+- Show the disclosure only for an unstarted task in create mode, matching the
+ dependency selector's existing availability. Session mode, edit mode, and
+ started-task forms do not gain a new advanced-settings row.
+- Keep all new trigger copy localized through the task translation namespace.
+
+## Interaction contract
+
+### Collapsed state
+
+- The row is visible at the bottom of the create-task settings, below the model,
+ executor, and workflow selector controls.
+- The row shows the localized `Advanced settings` label in a muted, subtle
+ size and a direction indicator.
+- The dependency trigger and its `No dependency` text are not visible while
+ the section is collapsed.
+- The row exposes `aria-expanded="false"` and a stable control/test identity.
+
+### Expanded state
+
+- Activating the row with pointer, touch, Enter, or Space expands the content.
+- The dependency selector is visible inside the content with its existing
+ searchable picker behavior. Its trigger uses the available row width on
+ narrow screens and a compact, constrained width on desktop.
+- The selector is introduced by a localized `Depends on` label with an
+ accessible help control. Hovering or focusing the control explains the
+ dependency wait and automatic-start behavior.
+- The row exposes `aria-expanded="true"`, and the expanded content is connected
+ to it through the normal collapsible relationship.
+- Closing the section preserves every selected predecessor. Reopening it
+ reveals the existing selected title or localized count.
+- The selector's search-row info control continues to explain dependency wait
+ behavior without changing the disclosure state or selection.
+
+## Mobile design contract
+
+- Desktop outcome: the create dialog keeps the workspace or worktree context,
+ then provides a compact advanced-settings entry that reveals dependencies.
+- Mobile entry point: the same inline disclosure in the full-screen task-create
+ form. A new drawer or separate mobile navigation surface is not needed for
+ one short advanced field.
+- The nearest shipped mobile exemplars are the task-create selector controls,
+ `task-create-dialog-pill.tsx`, and the existing dependency picker. Reuse the
+ project's contained popover and command-list behavior.
+- The disclosure trigger has a mobile hitbox of at least 44 CSS pixels even
+ though its label uses a subtle text size. The expanded dependency trigger and
+ dependency help control and task rows retain their existing touch-safe sizing.
+- The task-create form remains the outer scroll owner when the collapsible is
+ closed or expanded. The dependency command list remains the inner scroll
+ owner while its picker is open.
+- The expanded content uses a responsive option grid. On desktop, each row can
+ contain two settings, and each setting keeps its label/help to the left of its
+ selector in the same column. On narrow screens, the grid collapses to one
+ column and must not introduce document-level horizontal overflow.
+- State, selection logic, candidate filtering, and payload behavior are shared
+ across desktop and mobile. Only the disclosure geometry and touch
+ presentation are responsive.
+
+## Scenarios
+
+- **GIVEN** a new task create dialog, **WHEN** the form first renders, **THEN**
+ the advanced-settings row is visible and collapsed, and the dependency
+ trigger is not visible.
+- **GIVEN** the collapsed advanced-settings row, **WHEN** the user activates it,
+ **THEN** the row reports expanded and the dependency selector appears below
+ the model, executor, and workflow selector controls.
+- **GIVEN** the expanded selector with no predecessors, **THEN** its trigger
+ shows the existing `No dependency` label and dependency icon.
+- **GIVEN** a selected predecessor, **WHEN** the user collapses and reopens the
+ advanced section, **THEN** the selected task title or localized dependency
+ count remains visible in the selector and the form state is unchanged.
+- **GIVEN** a workflow selector that is visible, hidden for a single workflow,
+ or locked by a caller, **WHEN** the create dialog renders, **THEN** the
+ workflow's existing behavior is preserved and the advanced dependency
+ control remains available under the same create-mode rules.
+- **GIVEN** session mode, edit mode, or a started task, **WHEN** the form
+ renders, **THEN** no advanced-settings disclosure is added.
+- **GIVEN** a mobile create dialog, **WHEN** the user taps the disclosure and
+ opens the dependency picker, **THEN** the controls remain reachable, the
+ picker is contained in the viewport, and the document has no horizontal
+ overflow.
+- **GIVEN** selected predecessors, **WHEN** the user submits the task after
+ using the disclosure, **THEN** the existing `blocked_by` payload contains the
+ same IDs and no dependency API contract changes.
+
+## Out of scope
+
+- Changing dependency persistence, AND semantics, candidate derivation,
+ archived-task filtering, or automatic task-start behavior.
+- Changing the dependency selector's search, task icons, info help, or picker
+ interaction except where needed to mount it inside the disclosure.
+- Adding dependency editing to task detail, Kanban card menus, or MCP.
+- Adding or designing future advanced controls beyond the extensible content
+ region.
+- Changing workflow, agent, executor, repository, or branch selector behavior.
diff --git a/docs/specs/task-dependencies/create-dialog-dependency-selector.md b/docs/specs/task-dependencies/create-dialog-dependency-selector.md
new file mode 100644
index 0000000000..4fd6c34c4d
--- /dev/null
+++ b/docs/specs/task-dependencies/create-dialog-dependency-selector.md
@@ -0,0 +1,105 @@
+---
+status: implemented
+created: 2026-08-13
+owner: kandev
+---
+
+# Task-create dependency selector refinement
+
+## Why
+
+The task-create dialog currently presents dependencies as a small action beside
+a separate label and then renders selected tasks as chips below it. This makes
+the control look different from the agent, executor, and workflow selectors,
+and the dependency behavior is easy to miss when a user is planning an ordered
+set of tasks.
+
+## What
+
+- In create mode, the dependency control appears in the row below the agent and
+ executor selectors, on the right of the workflow selector when that selector
+ is visible.
+- The dependency control is one searchable selector. It keeps the existing
+ ability to choose multiple predecessor tasks by toggling task entries in the
+ same selector.
+- With no predecessor selected, the trigger shows `No dependency` and the
+ dependency icon. With one predecessor selected, it shows that task's title.
+ With multiple predecessors selected, it shows a localized dependency count.
+- The selector includes a `No dependency` entry that clears every selected
+ predecessor. A selected task can be removed by toggling its entry off.
+- Every task entry in the selector displays a task icon. Archived tasks are not
+ offered as candidates, and the existing candidate sources from both Kanban
+ board slices remain available.
+- The selector's search row has an info control on its right side. Hovering or
+ focusing the control explains that dependencies wait for all selected tasks
+ to finish successfully and that starting an agent starts this task
+ automatically after they resolve. The control has an accessible name and is
+ usable with touch and keyboard input.
+- The existing `blockedBy` form state and `blocked_by` create payload remain
+ unchanged. Selecting several predecessors keeps the existing AND semantics.
+- The dependency selector is disabled while the create flow is creating a
+ session, matching the current dependency control behavior.
+- The selector is available only for an unstarted task in create mode. It does
+ not add an edge editor to task detail or edit mode.
+- All new trigger labels, search copy, empty states, count labels, and help
+ copy use the task translation namespace. No new user-facing literal is
+ hardcoded in a component.
+
+## Mobile design contract
+
+- Desktop entry point: the dependency selector in the task-create dialog row
+ beside the workflow selector. Mobile entry point: the same full-width
+ selector in the dialog's vertically scrolling form.
+- The nearest shipped mobile exemplar is the task-create repository picker and
+ its `Pill` command surface. Reuse its contained searchable picker geometry,
+ touch-safe actions, and no-horizontal-overflow expectations while keeping the
+ dependency selector's full-width selector trigger consistent with the agent
+ and executor controls.
+- Mobile hierarchy is workflow first, dependency second, followed by the rest
+ of the form. The dependency trigger and each task row are the primary touch
+ targets for this surface.
+- The picker remains a viewport-contained searchable popover with an internal
+ command-list scroll owner. The dialog form remains the outer scroll owner
+ when the picker is closed. No document-level horizontal scrolling is added.
+- The selector shares task derivation, filtering, selection, and `blockedBy`
+ mutation logic across viewports. Only layout and touch presentation vary.
+
+## Scenarios
+
+- **GIVEN** a new task dialog with no selected predecessors, **WHEN** the user
+ views the workflow/dependency row, **THEN** the dependency trigger is on the
+ workflow row's right side and shows `No dependency` with its icon.
+- **GIVEN** the workflow selector is hidden because a single workflow is
+ already enforced, **WHEN** the user opens the create dialog, **THEN** the
+ dependency selector remains available in the same row position instead of
+ disappearing with the workflow control.
+- **GIVEN** the dependency trigger, **WHEN** the user opens it, **THEN** the
+ search field, the info control, the `No dependency` entry, and all non-archived
+ board tasks are available.
+- **GIVEN** two non-archived candidate tasks, **WHEN** the user selects both
+ entries, **THEN** both entries are marked selected, the trigger shows a
+ localized count, and the form retains both task IDs in `blockedBy`.
+- **GIVEN** selected predecessors, **WHEN** the user selects `No dependency`,
+ **THEN** the trigger returns to its default state and the form's `blockedBy`
+ value is empty.
+- **GIVEN** the selector's info control, **WHEN** the user hovers, focuses, or
+ taps it, **THEN** the dependency explanation is readable without changing
+ the current task selection, and Escape or outside interaction dismisses it.
+- **GIVEN** an archived board task, **WHEN** the user searches the dependency
+ selector, **THEN** the archived task is not offered.
+- **GIVEN** a Pixel 5-sized viewport, **WHEN** the user opens the create dialog
+ and dependency selector, **THEN** the trigger and task rows remain reachable,
+ the picker stays within the viewport, and the document has no horizontal
+ overflow.
+- **GIVEN** a task with selected predecessors, **WHEN** the user submits the
+ create dialog, **THEN** the request still contains the selected IDs in
+ `blocked_by`; no dependency API or backend contract changes.
+
+## Out of scope
+
+- Changing the dependency graph, auto-start semantics, or backend/API payload.
+- Limiting a task to one predecessor. Multiple predecessors and AND semantics
+ remain supported.
+- Adding dependency editing to task detail, Kanban card menus, or MCP.
+- Adding a new mobile navigation surface or replacing the task-create dialog.
+- Changing workflow, agent, executor, repository, or branch selector behavior.