refactor(jira): colocate shared contracts and capabilities (#32927)

* refactor(jira): colocate shared contracts and capabilities

* test(jira): validate title width against panel budget
This commit is contained in:
Neil
2026-10-23 14:31:05 -07:00
committed by GitHub
parent 2d06b6d6f9
commit aeb039938f
225 changed files with 283 additions and 249 deletions
+3 -3
View File
@@ -11494,11 +11494,11 @@
"src/shared/jira-issue-url.test.ts": 36,
"src/shared/jira-jql-predicate.test.ts": 38,
"src/shared/jira/jira-preset-jql.test.ts": 159,
"src/shared/jira-project-reference.test.ts": 278,
"src/shared/jira/jira-project-reference.test.ts": 278,
"src/shared/jira-review-title.test.ts": 93,
"src/shared/jira-saved-filters.test.ts": 34,
"src/shared/jira/jira-saved-filters.test.ts": 34,
"src/shared/jira/jira-search-input-jql.test.ts": 68,
"src/shared/jira-transition-fields.test.ts": 41,
"src/shared/jira/jira-transition-fields.test.ts": 41,
"src/shared/json-text-structure-limit.test.ts": 63,
"src/shared/json-token-reader.test.ts": 224,
"src/shared/keybindings-conflicts.test.ts": 83,
@@ -16,7 +16,7 @@ import { getMobileWorkspaceRepoBadgeColor } from './new-worktree-modal-types'
import { PickerListDrawer } from './PickerListDrawer'
import { SetupHookTrustDrawer, type SetupTrustPrompt } from './SetupHookTrustDrawer'
import { SmartWorkspaceSourceDrawer } from './SmartWorkspaceSourceDrawer'
import type { JiraSite, JiraSiteSelection } from '../../../src/shared/jira-types'
import type { JiraSite, JiraSiteSelection } from '../../../src/shared/jira/jira-types'
import type { NewWorktreeDrawerView } from './use-new-worktree-drawer-navigation'
type Composer = ReturnType<typeof useMobileComposerSource>
@@ -10,7 +10,7 @@ import {
} from 'react-native'
import type { RpcClient } from '../transport/rpc-client'
import type { SmartWorkspaceSourceRow as SourceRow } from '../../../src/shared/new-workspace/smart-workspace-source-results'
import type { JiraSite, JiraSiteSelection } from '../../../src/shared/jira-types'
import type { JiraSite, JiraSiteSelection } from '../../../src/shared/jira/jira-types'
import { isBlockingJiraUrlIntent } from '../../../src/shared/new-workspace/smart-workspace-source-results'
import {
MR_STATE_FILTER_OPTIONS,
@@ -2,7 +2,7 @@ import type { GitHubWorkItem } from '../../../src/shared/github/work-item-types'
import type { GitLabWorkItem } from '../../../src/shared/gitlab-types'
import type { LinearIssue } from '../../../src/shared/linear/issue-types'
import { getLinearIssueWorkspaceName } from '../../../src/shared/workspace-name'
import type { JiraIssue } from '../../../src/shared/jira-types'
import type { JiraIssue } from '../../../src/shared/jira/jira-types'
import {
buildGitHubWorkspaceSource,
buildGitLabWorkspaceSource,
+1 -1
View File
@@ -1,4 +1,4 @@
import type { JiraSite, JiraSiteSelection } from '../../../src/shared/jira-types'
import type { JiraSite, JiraSiteSelection } from '../../../src/shared/jira/jira-types'
import type { RpcOperationSender } from '../transport/rpc-operation-sender'
import type { RpcResponse } from '../transport/types'
import { jiraConnectionStatusSchema } from './jira-reply-schema'
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from 'vitest'
import type { JiraIssue, JiraSite } from '../../../src/shared/jira-types'
import type { JiraIssue, JiraSite } from '../../../src/shared/jira/jira-types'
import type { RpcOperationSender } from '../transport/rpc-operation-sender'
import { lookupJiraIssueByUrl } from './jira-mobile-url-lookup'
+1 -1
View File
@@ -1,4 +1,4 @@
import type { JiraIssue, JiraSite } from '../../../src/shared/jira-types'
import type { JiraIssue, JiraSite } from '../../../src/shared/jira/jira-types'
import {
getMatchingJiraSites,
isResolvedJiraIssueMatch,
@@ -1,4 +1,4 @@
import type { JiraIssueFilter } from '../../../src/shared/jira-types'
import type { JiraIssueFilter } from '../../../src/shared/jira/jira-types'
export const JIRA_FILTER_LABELS: Record<JiraIssueFilter, string> = {
assigned: 'My Issues',
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from 'vitest'
import type { JiraIssue } from '../../../src/shared/jira-types'
import type { JiraIssue } from '../../../src/shared/jira/jira-types'
import type { RpcResponse } from '../transport/types'
import { fetchJiraIssueDetail, fetchJiraTaskIssues } from './mobile-jira-task-source'
+5 -1
View File
@@ -1,4 +1,8 @@
import type { JiraIssue, JiraIssueFilter, JiraSiteSelection } from '../../../src/shared/jira-types'
import type {
JiraIssue,
JiraIssueFilter,
JiraSiteSelection
} from '../../../src/shared/jira/jira-types'
import type { RpcOperationSender } from '../transport/rpc-operation-sender'
import { toJiraDetailComments } from './jira-mobile-issue-read'
import {
@@ -1,4 +1,4 @@
import type { JiraIssueFilter } from '../../../src/shared/jira-types'
import type { JiraIssueFilter } from '../../../src/shared/jira/jira-types'
import type { TaskProvider } from '../../../src/shared/task-providers'
import type { PickerOption } from '../components/PickerModal'
import { JIRA_FILTER_LABELS } from './mobile-jira-issue-filters'
@@ -9,7 +9,7 @@ import type {
LinearFilter
} from './mobile-tasks-view-state-types'
import type { TaskItem } from './mobile-tasks-project-workspace-types'
import type { JiraIssue } from '../../../src/shared/jira-types'
import type { JiraIssue } from '../../../src/shared/jira/jira-types'
import type {
GitHubWorkItem,
GitLabTodo,
@@ -7,7 +7,7 @@ import type {
} from './mobile-tasks-provider-detail-types'
import type { WorkspaceAgentChoice, SparsePreset } from './mobile-tasks-dependencies'
import type { GitHubProjectRow } from './mobile-tasks-view-state-types'
import type { JiraIssue } from '../../../src/shared/jira-types'
import type { JiraIssue } from '../../../src/shared/jira/jira-types'
export type TaskItem =
| {
@@ -6,7 +6,7 @@ import type {
GitHubProjectRef
} from './mobile-tasks-dependencies'
import type { GitHubProjectSortDirection } from '../../../src/shared/github/project-types'
import type { JiraIssueFilter } from '../../../src/shared/jira-types'
import type { JiraIssueFilter } from '../../../src/shared/jira/jira-types'
export type GitHubTaskKind = 'issues' | 'prs'
+1 -1
View File
@@ -9,7 +9,7 @@ import {
import type { RpcClient } from '../transport/rpc-client'
import { isGitHubWorkItemsSshRemoteRequiredError } from '../../../src/shared/work-items'
import type { MrStateFilter } from './mobile-composer-source-types'
import type { JiraIssue, JiraSiteSelection } from '../../../src/shared/jira-types'
import type { JiraIssue, JiraSiteSelection } from '../../../src/shared/jira/jira-types'
import {
searchBranches,
searchGitHubItems,
@@ -3,7 +3,7 @@ import type { GitLabWorkItem } from '../../../src/shared/gitlab-types'
import type { LinearIssue } from '../../../src/shared/linear/issue-types'
import type { BaseRefSearchResult } from '../../../src/shared/repo-types'
import type { RpcClient } from '../transport/rpc-client'
import type { JiraIssue, JiraSiteSelection } from '../../../src/shared/jira-types'
import type { JiraIssue, JiraSiteSelection } from '../../../src/shared/jira/jira-types'
import { getJiraIssueSearchQuery } from '../../../src/shared/new-workspace/smart-workspace-source-results'
import {
buildJiraIssueKeyJql,
@@ -6,7 +6,7 @@ import { resolveComposerManualBranchNameChange } from '../../../src/shared/compo
import { resolveGitHubWorkItemIdentity } from '../../../src/shared/new-workspace/github-work-item-identity'
import { getForkPushWarning } from '../../../src/shared/new-workspace/fork-push-warning'
import type { RpcClient } from '../transport/rpc-client'
import type { JiraIssue } from '../../../src/shared/jira-types'
import type { JiraIssue } from '../../../src/shared/jira/jira-types'
import {
buildGitHubLinkedWorkItem,
buildGitLabLinkedWorkItem,
@@ -1,7 +1,7 @@
import { createElement } from 'react'
import { act, create, type ReactTestRenderer } from 'react-test-renderer'
import { afterEach, describe, expect, it, vi } from 'vitest'
import type { JiraIssue } from '../../../src/shared/jira-types'
import type { JiraIssue } from '../../../src/shared/jira/jira-types'
import { mountFixture } from '../test-support/rpc-recording/recorder-fixture-shape'
import { FakeSession } from '../transport/mobile-endpoint-supervisor-test-fakes'
import type { RepoSummary } from './mobile-tasks-provider-detail-types'
@@ -49,7 +49,7 @@ import {
} from './mobile-tasks-legacy-foundation'
import { useMobileTasksItemState } from './use-mobile-tasks-item-state'
import { useMobileJiraConnectionState } from './use-mobile-jira-connection-state'
import type { JiraIssueFilter } from '../../../src/shared/jira-types'
import type { JiraIssueFilter } from '../../../src/shared/jira/jira-types'
export function useMobileTasksRouteAndItemState() {
const { hostId, taskSource } = useLocalSearchParams<{ hostId: string; taskSource?: string }>()
@@ -8,7 +8,7 @@ import {
type SmartNameMode,
type SmartWorkspaceSourceRow
} from '../../../src/shared/new-workspace/smart-workspace-source-results'
import type { JiraIssue, JiraSite, JiraSiteSelection } from '../../../src/shared/jira-types'
import type { JiraIssue, JiraSite, JiraSiteSelection } from '../../../src/shared/jira/jira-types'
import type { RpcClient } from '../transport/rpc-client'
import { fanOutSmartSearch, type SmartFanOutResult } from './smart-source-fan-out'
import { lookupJiraIssueByUrl } from './jira-mobile-url-lookup'
+1 -1
View File
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from 'vitest'
import { JIRA_AGENT_ACCESS_RUNTIME_CAPABILITY } from '../../shared/jira-agent-capability'
import { JIRA_AGENT_ACCESS_RUNTIME_CAPABILITY } from '../../shared/jira/jira-agent-capability'
import { RuntimeClientError } from '../runtime-client'
import { JIRA_WRITE_HANDLERS } from './jira-write'
+1 -1
View File
@@ -5,7 +5,7 @@ import type {
JiraMutationResult,
JiraProject,
JiraTransition
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
import type { CommandHandler, HandlerContext } from '../dispatch'
import { readCommandBody } from '../command-body-input'
import {
+1 -1
View File
@@ -9,7 +9,7 @@ import type {
JiraProject,
JiraTransition,
JiraUser
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
import { isResolvedJiraIssueMatch, parseJiraIssueUrl } from '../../shared/jira-issue-url'
import type { CommandHandler, HandlerContext } from '../dispatch'
import {
+1 -1
View File
@@ -27,7 +27,7 @@ vi.mock('child_process', async () => {
import { main } from './index'
import { okFixture } from './test-fixtures'
import { pairRuntimeEnvironment, useWorktreeAwarenessEnvironment } from './index-test-harness'
import { JIRA_AGENT_ACCESS_RUNTIME_CAPABILITY } from '../shared/jira-agent-capability'
import { JIRA_AGENT_ACCESS_RUNTIME_CAPABILITY } from '../shared/jira/jira-agent-capability'
import { RuntimeClientError } from './runtime/types'
const site = {
+1 -1
View File
@@ -29,7 +29,7 @@ import { main } from './index'
import { pairRuntimeEnvironment, useWorktreeAwarenessEnvironment } from './index-test-harness'
import { buildWorktree, okFixture } from './test-fixtures'
import { RuntimeClientError } from './runtime/types'
import { JIRA_AGENT_ACCESS_RUNTIME_CAPABILITY } from '../shared/jira-agent-capability'
import { JIRA_AGENT_ACCESS_RUNTIME_CAPABILITY } from '../shared/jira/jira-agent-capability'
import { WORKTREE_LINKED_ITEMS_DELTA_RUNTIME_CAPABILITY } from '../shared/workspace-attachment-capabilities'
import {
getWorkspaceReferenceIdentity,
+1 -1
View File
@@ -7,7 +7,7 @@ import type {
JiraIssueType,
JiraTransition,
JiraUser
} from '../shared/jira-types'
} from '../shared/jira/jira-types'
function issueHeadline(issue: JiraIssue): string {
return `${issue.key} ${issue.title}`
+2 -2
View File
@@ -1,6 +1,6 @@
import type { JiraConnectionStatus, JiraSite } from '../shared/jira-types'
import type { JiraConnectionStatus, JiraSite } from '../shared/jira/jira-types'
import type { RuntimeStatus } from '../shared/runtime-types'
import { JIRA_AGENT_ACCESS_RUNTIME_CAPABILITY } from '../shared/jira-agent-capability'
import { JIRA_AGENT_ACCESS_RUNTIME_CAPABILITY } from '../shared/jira/jira-agent-capability'
import {
getMatchingJiraSites,
JIRA_ISSUE_KEY_PATTERN,
+1 -1
View File
@@ -1,6 +1,6 @@
import type { WorkspaceAttachment } from '../shared/worktree/types'
import type { RuntimeStatus } from '../shared/runtime-types'
import type { JiraIssue } from '../shared/jira-types'
import type { JiraIssue } from '../shared/jira/jira-types'
import {
isResolvedJiraIssueMatch,
JIRA_ISSUE_KEY_PATTERN,
+1 -1
View File
@@ -1,4 +1,4 @@
import type { JiraIssueUpdate, JiraSiteSelection } from '../../../shared/jira-types'
import type { JiraIssueUpdate, JiraSiteSelection } from '../../../shared/jira/jira-types'
export function normalizeJiraSiteId(value: unknown): string | undefined {
return typeof value === 'string' && value.trim() ? value.trim() : undefined
+1 -1
View File
@@ -5,7 +5,7 @@ import {
listPriorities
} from '../../jira/jira-issue-create-metadata'
import { listProjects } from '../../jira/jira-project-queries'
import type { JiraSiteSelection } from '../../../shared/jira-types'
import type { JiraSiteSelection } from '../../../shared/jira/jira-types'
export function registerJiraProjectMetadataHandlers(
normalizeSiteId: (value: unknown) => string | undefined
+1 -1
View File
@@ -26,7 +26,7 @@ import type {
JiraIssueListFilters,
JiraIssueUpdate,
JiraSiteSelection
} from '../../../shared/jira-types'
} from '../../../shared/jira/jira-types'
const VALID_FILTERS = new Set<JiraIssueFilter>(['assigned', 'reported', 'all', 'done'])
const issueSummaryRequests = new JiraCancellableRequests()
+1 -1
View File
@@ -3,7 +3,7 @@ import { JiraQuickFilterStateParam } from '../../shared/rpc-contract/jira-quick-
import {
normalizeJiraSavedFilterState,
mutateJiraSavedFilterState
} from '../../shared/jira-saved-filters'
} from '../../shared/jira/jira-saved-filters'
import { JiraSavedFilterMutationParam } from '../../shared/rpc-contract/jira-saved-filter-params'
import { BrowserWindow, ipcMain, webContents, type WebContents } from 'electron'
import type { Store } from '../persistence'
+1 -1
View File
@@ -1,4 +1,4 @@
import type { JiraSite } from '../../../shared/jira-types'
import type { JiraSite } from '../../../shared/jira/jira-types'
import { apiBasePath } from '../authenticated-request'
import { isJiraGatewayBaseUrl } from '../gateway-base-url'
import type { AttachmentMeta } from './meta'
+1 -1
View File
@@ -1,7 +1,7 @@
import { ensureElectronProxyFromEnvironment } from '../network/proxy-settings'
import { getMainHttpClient } from '../network/http-client'
import { withSpan } from '../observability/tracer'
import type { JiraAuthType, JiraSite } from '../../shared/jira-types'
import type { JiraAuthType, JiraSite } from '../../shared/jira/jira-types'
import { isJiraGatewayBaseUrl } from './gateway-base-url'
import { JiraApiError, toJiraApiError } from './jira-api-error'
+1 -1
View File
@@ -6,7 +6,7 @@ import type {
JiraSite,
JiraSiteSelection,
JiraViewer
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
import { clearAttachmentImagesForSite } from './attachments/image-cache'
import { acquire, release } from './request-queue'
import {
+1 -1
View File
@@ -1,4 +1,4 @@
import type { JiraAuthType, JiraViewer } from '../../shared/jira-types'
import type { JiraAuthType, JiraViewer } from '../../shared/jira/jira-types'
import { JiraApiError, requestWithCredentials } from './authenticated-request'
import { resolveJiraGatewayBaseUrl } from './cloud-gateway'
import { toViewer } from './site-identity'
+1 -1
View File
@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { JiraClientForSite } from './authenticated-request'
import { getAgileFieldIds, pickAgileFieldIds } from './jira-agile-fields'
import { mapJiraIssue, mapSprint } from './jira-issue-mapping'
import type { JiraSite } from '../../shared/jira-types'
import type { JiraSite } from '../../shared/jira/jira-types'
const { jiraRequestMock, acquireMock, releaseMock } = vi.hoisted(() => ({
jiraRequestMock: vi.fn(),
+1 -1
View File
@@ -1,5 +1,5 @@
import { requireStrictJiraSite } from './jira-read-failure'
import type { JiraComment } from '../../shared/jira-types'
import type { JiraComment } from '../../shared/jira/jira-types'
import {
JIRA_IMAGE_MAX_BYTES,
JIRA_IMAGE_MAX_REFERENCES,
+1 -1
View File
@@ -4,7 +4,7 @@ import type {
JiraIssueType,
JiraPriority,
JiraUser
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
import { acquire, release } from './request-queue'
import { apiBasePath, jiraRequest } from './authenticated-request'
import { clearToken, getClients, isAuthError } from './client'
+1 -1
View File
@@ -8,7 +8,7 @@ import type {
JiraSite,
JiraStatus,
JiraUser
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
import { adfToMarkdownText, textToAdf, type AdfToMarkdownOptions } from './adf-markdown'
import {
asRecord,
+1 -1
View File
@@ -4,7 +4,7 @@ import type {
JiraIssueUpdate,
JiraMutationResult,
JiraSite
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
import { acquire, release } from './request-queue'
import { apiBasePath, jiraRequest } from './authenticated-request'
import { clearToken, getClients, isAuthError } from './client'
+1 -1
View File
@@ -1,4 +1,4 @@
import type { JiraIssue, JiraSiteSelection } from '../../shared/jira-types'
import type { JiraIssue, JiraSiteSelection } from '../../shared/jira/jira-types'
import type { JiraMediaFormat } from '../../shared/jira/jira-attachment-image'
import { JiraSummaryLookupError } from '../../shared/jira-summary-lookup'
import { acquire, release } from './request-queue'
+1 -1
View File
@@ -4,7 +4,7 @@ import type {
JiraIssueFilter,
JiraIssueListFilters,
JiraSiteSelection
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
import { buildJiraPresetJql } from '../../shared/jira/jira-preset-jql'
import { acquire, release } from './request-queue'
import { apiBasePath, jiraRequest, type JiraClientForSite } from './authenticated-request'
+1 -1
View File
@@ -1,5 +1,5 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import type { JiraIssueFilter } from '../../shared/jira-types'
import type { JiraIssueFilter } from '../../shared/jira/jira-types'
import type { JiraClientForSite } from './authenticated-request'
const { getClients, jiraRequest, clearToken } = vi.hoisted(() => ({
+1 -1
View File
@@ -1,4 +1,4 @@
import type { JiraProject, JiraSiteSelection } from '../../shared/jira-types'
import type { JiraProject, JiraSiteSelection } from '../../shared/jira/jira-types'
import { acquire, release } from './request-queue'
import { apiBasePath, jiraRequest, type JiraClientForSite } from './authenticated-request'
import { clearToken, getClients, isAuthError } from './client'
+1 -1
View File
@@ -1,5 +1,5 @@
import type { JiraClientForSite } from './authenticated-request'
import type { JiraSiteSelection } from '../../shared/jira-types'
import type { JiraSiteSelection } from '../../shared/jira/jira-types'
export type JiraIssueSearchFailure = {
error: unknown
+1 -1
View File
@@ -1,5 +1,5 @@
import { requireStrictJiraSite } from './jira-read-failure'
import type { JiraProjectStatusOrder, JiraTransition } from '../../shared/jira-types'
import type { JiraProjectStatusOrder, JiraTransition } from '../../shared/jira/jira-types'
import { acquire, release } from './request-queue'
import { apiBasePath, JiraApiError, jiraRequest } from './authenticated-request'
import { clearToken, getClients, isAuthError } from './client'
+1 -1
View File
@@ -4,7 +4,7 @@ import { join } from 'node:path'
import { writeEncryptedCredential } from '../integration-credential-file'
import { readCredentialFileProtection } from '../credential-file-protection'
import type { SecretAtRestProtection } from '../../shared/secret-at-rest-protection'
import type { JiraSite, JiraSiteSelection } from '../../shared/jira-types'
import type { JiraSite, JiraSiteSelection } from '../../shared/jira/jira-types'
import { createIntegrationStateFileCache } from '../integration-state-file-cache'
import { isJiraGatewayBaseUrl } from './gateway-base-url'
import { createIntegrationTokenFileCache } from '../integration-token-file-cache'
+1 -1
View File
@@ -1,5 +1,5 @@
import { createHash } from 'node:crypto'
import type { JiraSite, JiraViewer } from '../../shared/jira-types'
import type { JiraSite, JiraViewer } from '../../shared/jira/jira-types'
export function normalizeJiraSiteUrl(siteUrl: string): string {
const trimmed = siteUrl.trim()
@@ -3,7 +3,7 @@ import { join } from 'node:path'
import { tmpdir } from 'node:os'
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import { closeTestStores, createStore, testState } from './persistence-test-harness'
import { normalizeJiraSavedFilterState } from '../shared/jira-saved-filters'
import { normalizeJiraSavedFilterState } from '../shared/jira/jira-saved-filters'
vi.mock('electron', () => ({ app: { getPath: () => testState.dir } }))
vi.mock('./telemetry/client', () => ({ track: vi.fn() }))
beforeEach(() => {
@@ -4,7 +4,7 @@ import { getDefaultRepoHookSettings } from '../../../shared/constants'
import { isFolderRepo } from '../../../shared/repo-kind'
import { sanitizeRepoIcon } from '../../../shared/repo-icon'
import { normalizeGhAccountBinding } from '../../../shared/github/account-binding'
import { normalizeJiraProjectReference } from '../../../shared/jira-project-reference'
import { normalizeJiraProjectReference } from '../../../shared/jira/jira-project-reference'
import { normalizeRepoSourceControlAiOverrides } from '../../../shared/source-control-ai'
import {
sanitizeForkSyncMode,
@@ -4,7 +4,7 @@ import type { GitRemoteIdentity } from '../../../shared/git-remote-identity'
import { normalizeRepoBadgeColor } from '../../../shared/repo-badge-color'
import { sanitizeRepoIcon } from '../../../shared/repo-icon'
import { normalizeGhAccountBinding } from '../../../shared/github/account-binding'
import { normalizeJiraProjectReference } from '../../../shared/jira-project-reference'
import { normalizeJiraProjectReference } from '../../../shared/jira/jira-project-reference'
import type { GhAccountBinding } from '../../../shared/github/account-binding'
import {
normalizeCustomWorktreeVisibilitySources,
+1 -1
View File
@@ -3,7 +3,7 @@ import { JiraQuickFilterStateParam } from '../../../../shared/rpc-contract/jira-
import {
normalizeJiraSavedFilterState,
mutateJiraSavedFilterState
} from '../../../../shared/jira-saved-filters'
} from '../../../../shared/jira/jira-saved-filters'
import { JiraSavedFilterMutationParam } from '../../../../shared/rpc-contract/jira-saved-filter-params'
import {
omitPairingLocalUiFields,
+1 -1
View File
@@ -14,7 +14,7 @@ import type {
JiraIssueListFilters,
JiraIssueUpdate,
JiraSiteSelection
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
import type { JiraMediaFormat } from '../../shared/jira/jira-attachment-image'
import { connect, disconnect, getStatus, selectSite, testConnection } from '../jira/client'
import { listFavouriteFilters } from '../jira/favourite-filters'
+1 -1
View File
@@ -22,7 +22,7 @@ import type {
JiraTransition,
JiraUser,
JiraViewer
} from '../../shared/jira-types'
} from '../../shared/jira/jira-types'
export type JiraApi = {
connect: (args: {
+1 -1
View File
@@ -4,7 +4,7 @@ import type {
JiraIssueSummaryGenerationCancellation
} from '../../shared/jira/jira-issue-summary-generation'
import { ipcRenderer } from 'electron'
import type { JiraIssueListFilters, JiraProjectStatusOrder } from '../../shared/jira-types'
import type { JiraIssueListFilters, JiraProjectStatusOrder } from '../../shared/jira/jira-types'
import type { PreloadApi } from '../api-types'
export const jiraApi = {
+4 -1
View File
@@ -3,7 +3,10 @@ import type {
RuntimeFileOpenPosition
} from '../../shared/runtime-file-contracts'
import type { JiraQuickFilterState } from '../../shared/jira-quick-filters'
import type { JiraSavedFilterState, JiraSavedFilterMutation } from '../../shared/jira-saved-filters'
import type {
JiraSavedFilterState,
JiraSavedFilterMutation
} from '../../shared/jira/jira-saved-filters'
import type { MarkdownDocument } from '../../shared/filesystem-entry-types'
import type { PersistedUIState } from '../../shared/persisted-ui-state-types'
import type { TuiAgent } from '../../shared/tui-agent'
@@ -17,7 +17,7 @@ import {
} from '@/components/ui/dropdown-menu'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { translate } from '@/i18n/i18n'
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
import { copyJiraTextToClipboard } from './jira-issue-workspace-actions'
import { buildJiraIssuePrompt } from './jira-prompt-templates'
import { Popover, PopoverAnchor } from '@/components/ui/popover'
@@ -7,7 +7,7 @@ import type {
JiraIssue,
JiraMutationResult,
JiraUser
} from '../../../shared/jira-types'
} from '../../../shared/jira/jira-types'
import {
getTaskSourceCacheScope,
type TaskSourceContext
@@ -16,7 +16,7 @@ import {
} from './__mocks__/jira-issue-workspace-edit-fixture'
import { act, fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
import type { RuntimeClientTarget } from '../../../shared/runtime-client-target'
describe('JiraIssueWorkspace reopened issue edits', () => {
@@ -12,7 +12,7 @@ import {
} from './__mocks__/jira-issue-workspace-edit-fixture'
import { act, fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
describe('JiraIssueWorkspace rollback baselines', () => {
it.each([
@@ -16,7 +16,7 @@ import {
} from './__mocks__/jira-issue-workspace-edit-fixture'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import type { JiraIssue, JiraMutationResult } from '../../../shared/jira-types'
import type { JiraIssue, JiraMutationResult } from '../../../shared/jira/jira-types'
import type { RuntimeClientTarget } from '../../../shared/runtime-client-target'
import { getDefaultSettings } from '../../../shared/constants'
import { getProviderRuntimeContextKey } from '@/lib/provider-runtime-context'
@@ -11,7 +11,7 @@ import {
} from './__mocks__/jira-issue-workspace-edit-fixture'
import { act, fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it } from 'vitest'
import type { JiraTransition } from '../../../shared/jira-types'
import type { JiraTransition } from '../../../shared/jira/jira-types'
describe('JiraIssueWorkspace queued status metadata', () => {
it('reloads transitions on a reopened issue when its earlier status save completes', async () => {
@@ -2,7 +2,11 @@
import type { ComponentProps, ReactNode } from 'react'
import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { JiraConnectionStatus, JiraIssue, JiraTransition } from '../../../shared/jira-types'
import type {
JiraConnectionStatus,
JiraIssue,
JiraTransition
} from '../../../shared/jira/jira-types'
import { taskSourceRuntimeTarget } from '@/lib/task-source-runtime-target'
import type { AppState } from '@/store/types'
import type { TaskSourceContext } from '../../../shared/task-source-context'
@@ -5,7 +5,7 @@ import { Sheet, SheetContent, SheetDescription, SheetTitle } from '@/components/
import { hasBoundedCommentBodyText } from '@/lib/comment-body-submit-state'
import { useAppStore } from '@/store'
import { jiraGetIssueForTarget, jiraUpdateIssueForTarget } from '@/runtime/runtime-jira-client'
import type { JiraIssue, JiraMutationResult } from '../../../shared/jira-types'
import type { JiraIssue, JiraMutationResult } from '../../../shared/jira/jira-types'
import {
getTaskSourceCacheScope,
type TaskSourceContext
@@ -8,7 +8,7 @@ import {
DropdownMenuTrigger
} from '@/components/ui/dropdown-menu'
import { translate } from '@/i18n/i18n'
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
import type { Worktree } from '../../../shared/worktree/types'
export function JiraLinkedWorkspaceAction({
@@ -11,7 +11,7 @@ import {
} from '@/components/ui/select'
import { Textarea } from '@/components/ui/textarea'
import { translate } from '@/i18n/i18n'
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
import { copyJiraTextToClipboard } from './jira-issue-workspace-actions'
import {
getJiraPromptTemplates,
@@ -6,7 +6,7 @@ import {
MAX_JIRA_SAVED_FILTER_NAME_LENGTH,
MAX_JIRA_SAVED_FILTERS,
type JiraSavedFilter
} from '../../../shared/jira-saved-filters'
} from '../../../shared/jira/jira-saved-filters'
import { translate } from '@/i18n/i18n'
import {
Command,
@@ -7,7 +7,7 @@ import {
getJiraStatusCatalogScopeKey,
includeSelectedJiraStatuses
} from './task-page-jira-status-catalog'
import { restrictJiraQueryToProject } from '../../../shared/jira-project-reference'
import { restrictJiraQueryToProject } from '../../../shared/jira/jira-project-reference'
import type { TaskPageComposerActionsModel } from './use-task-page-composer-actions'
export function TaskPageJiraStatusFilters({
@@ -1,7 +1,7 @@
import { useLayoutEffect, useState } from 'react'
import { act, cleanup, fireEvent, screen } from '@testing-library/react'
import { afterEach, beforeEach, vi, type Mock } from 'vitest'
import type { JiraIssue } from '../../../../shared/jira-types'
import type { JiraIssue } from '../../../../shared/jira/jira-types'
import type { GlobalSettings } from '../../../../shared/global-settings-types'
import {
getTaskSourceCacheScope,
@@ -1,8 +1,8 @@
import { useMemo, useRef } from 'react'
import { vi, type Mock } from 'vitest'
import type { ExecutionHostId } from '../../../../shared/execution-host'
import type { JiraIssue } from '../../../../shared/jira-types'
import type { JiraSavedFilterState } from '../../../../shared/jira-saved-filters'
import type { JiraIssue } from '../../../../shared/jira/jira-types'
import type { JiraSavedFilterState } from '../../../../shared/jira/jira-saved-filters'
import type { TaskPageLinearViewStateModel } from '../task-page/linear/use-task-page-linear-view-state'
import type { TaskPageLinearCollectionEffectsModel } from '../task-page/linear/use-task-page-linear-collection-effects'
import { useTaskPageJiraListState } from '../use-task-page-jira-list-state'
@@ -1,6 +1,6 @@
import type { GitHubWorkItem } from '../../../../shared/github/work-item-types'
import type { GitLabWorkItem } from '../../../../shared/gitlab-types'
import type { JiraIssue } from '../../../../shared/jira-types'
import type { JiraIssue } from '../../../../shared/jira/jira-types'
import type { LinearIssue } from '../../../../shared/linear/issue-types'
import {
getTaskSourceCacheScope,
@@ -1,4 +1,4 @@
import type { JiraIssue } from '../../../../shared/jira-types'
import type { JiraIssue } from '../../../../shared/jira/jira-types'
import type { TaskSourceContext } from '../../../../shared/task-source-context'
import { makeCmdJTaskSearchResult } from './task-search-results'
@@ -1,7 +1,7 @@
// @vitest-environment happy-dom
import { fireEvent, render, screen, cleanup, waitFor } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { JiraConnectionStatus } from '../../../shared/jira-types'
import type { JiraConnectionStatus } from '../../../shared/jira/jira-types'
import { JiraConnectDialog } from './jira-connect-dialog'
import { getEnvironmentRuntimeContextKey } from '@/lib/provider-runtime-context'
@@ -3,7 +3,7 @@ import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-libra
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { RuntimeClientTarget } from '../../../shared/runtime-client-target'
import { taskSourceRuntimeTarget } from '@/lib/task-source-runtime-target'
import type { JiraConnectionStatus, JiraIssue, JiraUser } from '../../../shared/jira-types'
import type { JiraConnectionStatus, JiraIssue, JiraUser } from '../../../shared/jira/jira-types'
import type { TaskSourceContext } from '../../../shared/task-source-context'
import type { AppState } from '@/store/types'
import { JiraIssueMetadataBar } from './jira-issue-workspace-chrome'
@@ -12,7 +12,7 @@ import {
type TaskSourceContext
} from '../../../shared/task-source-context'
import type { RuntimeClientTarget } from '../../../shared/runtime-client-target'
import type { JiraIssue, JiraIssueUpdate, JiraUser } from '../../../shared/jira-types'
import type { JiraIssue, JiraIssueUpdate, JiraUser } from '../../../shared/jira/jira-types'
export function JiraIssueAssigneeControl({
issue,
@@ -1,4 +1,4 @@
import type { JiraIssue, JiraMutationResult } from '../../../shared/jira-types'
import type { JiraIssue, JiraMutationResult } from '../../../shared/jira/jira-types'
import type { GlobalSettings } from '../../../shared/global-settings-types'
import type { TaskSourceContext } from '../../../shared/task-source-context'
import { getJiraReadIdentity } from '@/store/slices/jira-read-coordination'
@@ -1,5 +1,5 @@
import type { JiraListColumnId } from './jira-list-columns'
import type { JiraIssue, JiraPriority } from '../../../shared/jira-types'
import type { JiraIssue, JiraPriority } from '../../../shared/jira/jira-types'
import { compareNumericLocaleText } from '../../../shared/locale-text-collators'
export type JiraIssueSortColumn = JiraListColumnId
@@ -2,7 +2,7 @@
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { JiraIssueTransitionControl } from './jira-issue-transition-control'
import type { JiraIssue, JiraTransition } from '../../../shared/jira-types'
import type { JiraIssue, JiraTransition } from '../../../shared/jira/jira-types'
vi.mock('@/i18n/i18n', () => ({
translate: (_key: string, fallback: string, values?: Record<string, string>) =>
@@ -3,14 +3,14 @@ import { ChevronDown, CircleAlert, ExternalLink, Loader2 } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { translate } from '@/i18n/i18n'
import { classifyTransitionRequirements } from '../../../shared/jira-transition-fields'
import { classifyTransitionRequirements } from '../../../shared/jira/jira-transition-fields'
import { JiraTransitionFieldsForm } from './jira-transition-fields-form'
import type {
JiraIssue,
JiraIssueUpdate,
JiraMutationResult,
JiraTransition
} from '../../../shared/jira-types'
} from '../../../shared/jira/jira-types'
type Props = {
issue: JiraIssue
@@ -2,7 +2,11 @@ import { useCallback, useMemo } from 'react'
import { Clipboard, ExternalLink, GitBranch } from 'lucide-react'
import { toast } from 'sonner'
import { translate } from '@/i18n/i18n'
import type { JiraIssue, JiraIssueUpdate, JiraMutationResult } from '../../../shared/jira-types'
import type {
JiraIssue,
JiraIssueUpdate,
JiraMutationResult
} from '../../../shared/jira/jira-types'
import { applyJiraIssueKeyCasing } from '../../../shared/workspace-name'
import type { WorkspaceSeedNameOptions } from '../../../shared/workspace-name'
import { getJiraIssueKeyCasingSeedOptions } from '@/lib/jira-issue-key-casing'
@@ -14,7 +14,7 @@ import type {
JiraMutationResult,
JiraPriority,
JiraTransition
} from '../../../shared/jira-types'
} from '../../../shared/jira/jira-types'
/** Header row for an open Jira issue: key, summary, and workspace actions. */
export function JiraIssueWorkspaceHeader({
@@ -8,7 +8,7 @@ import { Input } from '@/components/ui/input'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { translate } from '@/i18n/i18n'
import { formatUiRelativeTimeFromDate } from '@/i18n/relative-time-format'
import type { JiraComment, JiraIssue } from '../../../shared/jira-types'
import type { JiraComment, JiraIssue } from '../../../shared/jira/jira-types'
export type JiraIssueWorkspaceAction = {
label: string
@@ -1,4 +1,4 @@
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
const EDITABLE_JIRA_ISSUE_FIELDS = ['title', 'labels', 'status', 'priority', 'assignee'] as const
export type EditableJiraIssueField = (typeof EDITABLE_JIRA_ISSUE_FIELDS)[number]
@@ -3,7 +3,7 @@
import { act, type ComponentProps, type ReactNode } from 'react'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { JiraComment, JiraIssue, JiraTransition } from '../../../shared/jira-types'
import type { JiraComment, JiraIssue, JiraTransition } from '../../../shared/jira/jira-types'
import type { TaskSourceContext } from '../../../shared/task-source-context'
import type { RuntimeClientTarget } from '../../../shared/runtime-client-target'
import type { AppState } from '../store/types'
@@ -3,7 +3,7 @@
import { act, StrictMode, type ComponentProps, type ReactNode } from 'react'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { JiraComment, JiraIssue, JiraTransition } from '../../../shared/jira-types'
import type { JiraComment, JiraIssue, JiraTransition } from '../../../shared/jira/jira-types'
import type { TaskSourceContext } from '../../../shared/task-source-context'
import type { AppState } from '../store/types'
import type {
@@ -1,4 +1,4 @@
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
import {
buildJiraIssueKeyJql,
buildJiraTextMatchJql
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import type { JiraProject } from '../../../shared/jira-types'
import type { JiraProject } from '../../../shared/jira/jira-types'
import {
JIRA_PROJECT_PICKER_QUERY_MAX_BYTES,
filterJiraProjectPickerProjects,
@@ -1,5 +1,5 @@
import { isClipboardTextByteLengthOverLimit } from '../../../shared/clipboard-text'
import type { JiraProject } from '../../../shared/jira-types'
import type { JiraProject } from '../../../shared/jira/jira-types'
export const JIRA_PROJECT_PICKER_QUERY_MAX_BYTES = 2 * 1024
@@ -1,11 +1,11 @@
import { useState } from 'react'
import { Check, ChevronsUpDown } from 'lucide-react'
import type { JiraProject } from '../../../shared/jira-types'
import type { JiraProject } from '../../../shared/jira/jira-types'
import {
normalizeJiraProjectReference,
matchesJiraProject,
type JiraProjectReference
} from '../../../shared/jira-project-reference'
} from '../../../shared/jira/jira-project-reference'
import { Button } from './ui/button'
import { Popover, PopoverContent, PopoverTrigger } from './ui/popover'
import { Command, CommandInput, CommandList, CommandEmpty, CommandItem } from './ui/command'
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
import {
renderJiraPromptTemplate,
getJiraPromptTemplates,
@@ -1,4 +1,4 @@
import type { JiraIssue } from '../../../shared/jira-types'
import type { JiraIssue } from '../../../shared/jira/jira-types'
import { translate } from '@/i18n/i18n'
export function buildJiraIssuePrompt(issue: JiraIssue): string {
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import type { JiraConnectionStatus } from '../../../shared/jira-types'
import type { JiraConnectionStatus } from '../../../shared/jira/jira-types'
import { getJiraSelfUser } from './jira-self-user'
const viewer = {
@@ -1,4 +1,4 @@
import type { JiraConnectionStatus, JiraUser } from '../../../shared/jira-types'
import type { JiraConnectionStatus, JiraUser } from '../../../shared/jira/jira-types'
// Site identities take precedence over the active site's viewer.
export function getJiraSelfUser(
@@ -16,8 +16,8 @@ import {
classifyTransitionRequirements,
transitionAllowedValueKey,
transitionAllowedValueLabel
} from '../../../shared/jira-transition-fields'
import type { JiraIssueUpdate, JiraTransition } from '../../../shared/jira-types'
} from '../../../shared/jira/jira-transition-fields'
import type { JiraIssueUpdate, JiraTransition } from '../../../shared/jira/jira-types'
type Props = {
transition: JiraTransition
@@ -5,7 +5,7 @@ import { Input } from '@/components/ui/input'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { jiraSearchUsers, type RuntimeJiraSettings } from '@/runtime/runtime-jira-client'
import { translate } from '@/i18n/i18n'
import type { JiraUser } from '../../../shared/jira-types'
import type { JiraUser } from '../../../shared/jira/jira-types'
const USER_SEARCH_DEBOUNCE_MS = 250
@@ -3,7 +3,7 @@
import React, { act } from 'react'
import { cleanup, createEvent, fireEvent, render, screen } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { JiraIssue } from '../../../../shared/jira-types'
import type { JiraIssue } from '../../../../shared/jira/jira-types'
import SmartWorkspaceNameField from './SmartWorkspaceNameField'
import type { SmartWorkspaceNameSelection } from './smart-workspace-name-field-model'
@@ -13,7 +13,7 @@ import type SmartWorkspaceNameField from './SmartWorkspaceNameField'
import type { SmartWorkspaceNameSelection } from '@/components/new-workspace/smart-workspace-name-field-model'
import type { GitHubWorkItem } from '../../../../shared/github/work-item-types'
import type { GitLabWorkItem } from '../../../../shared/gitlab-types'
import type { JiraIssue } from '../../../../shared/jira-types'
import type { JiraIssue } from '../../../../shared/jira/jira-types'
import type { LinearIssue } from '../../../../shared/linear/issue-types'
import type { OrcaHooks, SetupAgentStartupPolicy } from '../../../../shared/orca-yaml-hook-types'
import type { SparsePreset } from '../../../../shared/worktree/create-types'
@@ -3,7 +3,7 @@ import type { useAppStore } from '@/store'
import type { parseGitHubIssueOrPRLink, RepoSlug } from '@/lib/github-links'
import type { GitHubWorkItem } from '../../../../shared/github/work-item-types'
import type { GitLabWorkItem } from '../../../../shared/gitlab-types'
import type { JiraIssue, JiraSite } from '../../../../shared/jira-types'
import type { JiraIssue, JiraSite } from '../../../../shared/jira/jira-types'
import type { LinearIssue } from '../../../../shared/linear/issue-types'
import type { BaseRefSearchResult } from '../../../../shared/repo-types'
import type { TaskSourceContext } from '../../../../shared/task-source-context'
@@ -11,7 +11,7 @@ import { LinearIcon } from '@/components/icons/LinearIcon'
import { JiraIcon } from '@/components/icons/JiraIcon'
import { cn } from '@/lib/utils'
import { translate } from '@/i18n/i18n'
import type { JiraSite } from '../../../../shared/jira-types'
import type { JiraSite } from '../../../../shared/jira/jira-types'
import type { RowEntry, SmartWorkspaceNameSelection } from './smart-workspace-name-field-model'
const ROW_ITEM_CLASS_NAME = 'gap-2 px-3 py-2 text-xs'

Some files were not shown because too many files have changed in this diff Show More