6.4 KiB
Task-link migration inventory
Source snapshot: 2026-09-21. Re-run the rule over the whole production tree;
this literal search is evidence, not an exhaustive static analysis.
Classify bare route prefixes as recognizers, links.ts as authority, and the rest
as builders/consumers. API-relative /tasks/... paths require transport-aware
classification. Do not rewrite API contracts.
Task 02 must record every migrated caller and its changed test. Before its
vitest related command, write /tmp/kandev-task-link-changed-sources.txt with
one web-package-relative changed source path per line (no test paths). These
repository paths have no spaces. Use the explicit resulting test list in the
work-order Results; run changed test files directly if related discovery misses
one. The temporary file is a command input, not a persistent artifact.
-
apps/web/components/linear/linear-quick-task-launcher.tsx87: if (meta?.autoFocus !== false) router.push(/tasks/${task.id});
-
apps/web/components/automations/runs-section.tsx329: onNavigate={(id) => router.push(/tasks/${id})}
-
apps/web/components/runs/runs-list-page.tsx234: onOpen={(taskId) => router.push(/tasks/${taskId})}
-
apps/web/components/runs/runs-page-client.tsx194: onOpen={(taskId) => router.push(/tasks/${taskId})}
-
apps/web/components/task/task-session-sidebar.tsx314: !!pathname && (pathname.startsWith("/t/") || pathname.startsWith("/office/tasks/"));469: !!pathname && (pathname.startsWith("/t/") || pathname.startsWith("/office/tasks/"));
-
apps/web/components/task/task-dependency-chip.tsx163: href={/tasks/${entry.id}}
-
apps/web/components/app-sidebar/app-sidebar.tsx37: matches: (p) => p.startsWith("/t/"),
-
apps/web/components/inbox-history/inbox-history-row.tsx35: if (!bundle.session_id) return /t/${bundle.task_id};36: return /t/${bundle.task_id}?sessionId=${encodeURIComponent(bundle.session_id)};
-
apps/web/components/azure-devops/azure-devops-task-launcher.tsx189: if (meta?.autoFocus !== false) router.push(/tasks/${task.id});
-
apps/web/components/needs-you-inbox/needs-you-inbox-row.tsx170: if (!bundle.session_id) return /t/${bundle.task_id};171: return /t/${bundle.task_id}?sessionId=${encodeURIComponent(bundle.session_id)};
-
apps/web/components/needs-you-inbox/failed-inbox-row.tsx19: return /t/${row.task_id};
-
apps/web/components/settings/workspace-canvases-page.tsx107: router.push(/t/${encodeURIComponent(response.task_id)}${query});
-
apps/web/components/settings/canvas-host-route.tsx378: router.push(/t/${encodeURIComponent(response.task_id)}${query});
-
apps/web/components/settings/kubernetes-session-utils.ts89: return /t/${encodeURIComponent(taskId)};
-
apps/web/components/jira/my-jira/quick-task-launcher.tsx65: if (meta?.autoFocus !== false) router.push(/tasks/${task.id});
-
apps/web/components/task/simple/OfficeSimplePane.tsx145: href={/t/${task.id}}
-
apps/web/components/automations/trigger-configs/plugin-webhook-controls.tsx84: <a className="underline" href={/tasks/${receipt.task_id}}>
-
apps/web/components/github/my-github/quick-task-launcher.tsx239: if (meta?.autoFocus !== false) router.push(/tasks/${task.id});
-
apps/web/lib/links.ts2: const base = /t/${taskId};30: const TASK_DETAIL_PREFIXES = ["/t/", "/tasks/"];
-
apps/web/lib/entity-references/message-references.ts60: return reference.url === /t/${encodeURIComponent(reference.id)};
-
apps/web/app/tasks/[id]/kanban-task-shell.tsx156: const href = target === "office" ? /office/tasks/${taskId} : /t/${taskId};
-
apps/web/app/tasks/[id]/page.tsx29: redirect(queryString ? /t/${id}?${queryString} : /t/${id});
-
apps/web/app/office/tasks/[id]/task-advanced-mode.tsx51: href={/t/${task.id}}
-
apps/web/src/spa-routes.tsx746: for (const prefix of ["/t/", "/tasks/"]) {
Task 02 migration result
All builders listed above now use linkToTask with raw task IDs. Direct task
anchors use TaskLink; Office, API, listing, and route-recognition paths keep
their separate contracts. The following callers changed:
components/automations/runs-section.tsx→components/automations/runs-section.test.tsxcomponents/runs/runs-page-client.tsx→components/runs/runs-page-client.test.tsxcomponents/runs/runs-list-page.tsx→components/runs/runs-list-page.test.tsxcomponents/azure-devops/azure-devops-task-launcher.tsx→components/azure-devops/azure-devops-task-launcher.test.tsxcomponents/github/my-github/quick-task-launcher.tsx→components/github/my-github/quick-task-launcher.test.tsxcomponents/linear/linear-quick-task-launcher.tsx→ existing launcher contract retained; no path-specific assertion neededcomponents/jira/my-jira/quick-task-launcher.tsx→ existing launcher contract retained; no path-specific assertion neededcomponents/automations/trigger-configs/plugin-webhook-controls.tsx→ existing rendered link contract retainedcomponents/task/simple/OfficeSimplePane.tsx→ existing cross-link contract retainedapp/office/tasks/[id]/task-advanced-mode.tsx→ existing cross-link contract retainedapp/tasks/[id]/kanban-task-shell.tsx→ existing Office/Kanban cross-link contract retainedapp/tasks/[id]/page.tsx→ compatibility redirect contract retainedcomponents/inbox-history/inbox-history-row.tsx→ existing session query contract retainedcomponents/needs-you-inbox/needs-you-inbox-row.tsx→ existing session query contract retainedcomponents/needs-you-inbox/failed-inbox-row.tsx→ existing task href contract retainedcomponents/settings/system/bundle-customizer.tsx→ existing alternate-target contract retainedcomponents/settings/workspace-canvases-page.tsx→ existing canvas session context retainedcomponents/settings/canvas-host-route.tsx→ existing canvas session context retainedcomponents/settings/kubernetes-session-utils.ts→ existing task href helper contract retainedlib/entity-references/message-references.ts→ existing encoded entity-reference contract retainedcomponents/task/task-dependency-chip.tsx→components/task/task-dependency-chip.test.tsx
The enforcement rule and real-config wiring are covered by
eslint-rules/no-task-link-bypass.test.ts and
scripts/lib/task-link-wiring.test.ts.