Add opt-in JIRA-backed workspace branch naming while preserving editable manual branch workflows. - add scoped JIRA configuration, secret resolution, and documented inheritance - expose a bounded JIRA issue client and branch-derivation API route - add settings and task-form controls with recoverable errors and coverage - derive sanitized branch names from configurable issue-key and summary templates Files changed: .changeset/fn-9165-jira-branch-name.md | 7 ++ docs/secrets.md | 4 + docs/settings-reference.md | 18 ++++ docs/workspaces.md | 4 + packages/core/src/__tests__/jira-config.test.ts | 6 ++ .../core/src/__tests__/settings-parity.test.ts | 12 +++ packages/core/src/config/settings-schema.ts | 14 +++ packages/core/src/index.ts | 2 + packages/core/src/jira/index.ts | 1 + packages/core/src/jira/jira-config.ts | 34 +++++++ packages/core/src/types/settings/settings-scope.ts | 16 ++++ .../app/__tests__/settings-save-split.test.ts | 43 +++++++++ .../dashboard/app/components/SettingsModal.tsx | 29 +++++- packages/dashboard/app/components/TaskForm.tsx | 23 ++++- .../app/components/__tests__/TaskForm.test.tsx | 31 +++++++ .../settings/__tests__/section-keys.test.ts | 2 + .../app/components/settings/save-split.ts | 64 ++++++++++++- .../app/components/settings/section-keys.ts | 1 + .../sections/SourceControlGlobalSection.search.ts | 9 ++ .../sections/SourceControlGlobalSection.tsx | 20 ++++- .../sections/SourceControlSection.search.ts | 9 ++ .../settings/sections/SourceControlSection.tsx | 12 +++ .../settings-default-descriptions.test.tsx | 7 ++ .../dashboard/src/__tests__/jira-client.test.ts | 58 ++++++++++++ .../src/__tests__/register-jira-routes.test.ts | 70 +++++++++++++++ packages/dashboard/src/jira-auth.ts | 18 ++++ packages/dashboard/src/jira.ts | 75 ++++++++++++++++ packages/dashboard/src/routes.ts | 2 + packages/dashboard/src/routes/README.md | 100 +++++++++++---------- .../src/routes/create-api-routes-mount-sequence.ts | 2 +- packages/dashboard/src/routes/register-jira.ts | 66 ++++++++++++++ packages/engine/src/index.ts | 2 + .../worktree/__tests__/jira-branch-name.test.ts | 7 ++ packages/engine/src/worktree/jira-branch-name.ts | 6 ++ packages/i18n/locales/en/app.json | 23 +++++ 35 files changed, 739 insertions(+), 58 deletions(-) Fusion-Task-Id: FN-9165 Fusion-Task-Lineage: 88ab5fa3-f66e-421d-8139-5c3e8917348d Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
106 lines
6.1 KiB
TypeScript
106 lines
6.1 KiB
TypeScript
/**
|
|
* Search entries for the Source Control · Project section.
|
|
*
|
|
* FNXC:SettingsSearch 2026-07-15-17:35:
|
|
* One entry per descriptor row the section renders, co-located so a setting and its index entry change in the same edit. Labels and help mirror the section's `t()` calls verbatim: the index matches on the copy operators actually read, so a paraphrase here would make search miss the words on screen.
|
|
*
|
|
* FNXC:SettingsSearch 2026-07-15-20:30:
|
|
* These entries moved here with their controls from GeneralSection.search.ts and MergeSection.search.ts. An entry's `sectionId` must track the section that actually RENDERS the row — a stale id would surface the result, jump to a section that no longer holds the anchor, and do nothing.
|
|
* The token rows are indexed for the first time: they were unindexable while they had to stay hand-rolled to avoid rendering a secret through a `type="text"` primitive, and SettingsTextRow's `type: "password"` support is what makes them addressable. The index stores their label and help copy only — never a value.
|
|
* Still absent by design: the tracking-mode select and the tracking-repo select are bespoke widgets with no descriptor `key`, so they carry no `data-settings-key` anchor to scroll to. They stay reachable via the section's `searchableText` in SETTINGS_SECTIONS.
|
|
*/
|
|
import type { SettingsSearchEntry } from "../search/types";
|
|
|
|
export const sourceControlSearchEntries: SettingsSearchEntry[] = [
|
|
{
|
|
sectionId: "source-control",
|
|
key: "githubLinkImportedIssuesToTracking",
|
|
labelKey: "settings.general.alwaysLinkImportedGitHubIssuesToTracking",
|
|
labelFallback: " Always link imported GitHub issues to GitHub tracking ",
|
|
helpKey: "settings.general.whenEnabledImportedGitHubIssuesUseTheirSource",
|
|
helpFallback:
|
|
"When enabled, GitHub issue imports become tracked tasks that adopt the source issue. This does not turn GitHub tracking on for ordinary new tasks. Default: disabled.",
|
|
keywords: ["adopt issue", "import"],
|
|
},
|
|
{
|
|
sectionId: "source-control",
|
|
key: "githubTrackingDedupEnabled",
|
|
labelKey: "settings.general.searchTheTrackingRepoForLikelyDuplicatesBefore",
|
|
labelFallback: " Search the tracking repo for likely duplicates before opening a new issue ",
|
|
helpKey: "settings.general.whenEnabledFusionChecksOpenAndClosedIssues",
|
|
helpFallback:
|
|
" When enabled, Fusion checks open and closed issues in the target repo for likely duplicates (using File Scope paths and key symptoms) before creating a new tracking issue. Uncheck to always create a new issue. Default: enabled. ",
|
|
keywords: ["dedupe", "deduplication"],
|
|
},
|
|
{
|
|
sectionId: "source-control",
|
|
key: "githubAuthMode",
|
|
labelKey: "settings.merge.gitHubAuthMode",
|
|
labelFallback: "GitHub auth mode",
|
|
/*
|
|
FNXC:SettingsSearch 2026-07-15-17:35:
|
|
No helpKey/helpFallback: this row carries no help copy in the section either, and inventing index-only text would let search match words that appear nowhere on screen. The keywords carry the vocabulary instead.
|
|
*/
|
|
keywords: ["gh cli", "personal access token", "pat", "credentials", "login"],
|
|
},
|
|
{
|
|
sectionId: "source-control",
|
|
key: "githubAuthToken",
|
|
labelKey: "settings.merge.gitHubPersonalAccessToken",
|
|
labelFallback: "GitHub personal access token",
|
|
helpKey: "settings.merge.githubAuthTokenHint",
|
|
helpFallback: "No default — unset.",
|
|
keywords: ["pat", "credentials", "secret", "ghp"],
|
|
},
|
|
{
|
|
sectionId: "source-control",
|
|
key: "gitlabInstanceUrl",
|
|
labelKey: "settings.general.gitLabInstanceUrl",
|
|
labelFallback: "GitLab instance URL",
|
|
helpKey: "settings.general.gitLabInstanceUrlHint",
|
|
helpFallback:
|
|
"Blank uses GitLab.com or the global default. Set an absolute http:// or https:// URL for self-managed GitLab, such as https://gitlab.example.com/gitlab.",
|
|
keywords: ["self managed", "self-hosted", "on premise"],
|
|
},
|
|
{
|
|
sectionId: "source-control",
|
|
key: "gitlabApiBaseUrl",
|
|
labelKey: "settings.general.gitLabApiBaseUrlOptional",
|
|
labelFallback: "GitLab API base URL (optional / advanced)",
|
|
helpKey: "settings.general.gitLabApiBaseUrlHint",
|
|
helpFallback:
|
|
"Blank derives <instance>/api/v4. Override only when a self-managed GitLab API is served from a different absolute http:// or https:// URL.",
|
|
keywords: ["api v4", "gateway", "self managed"],
|
|
},
|
|
{
|
|
sectionId: "source-control",
|
|
key: "gitlabAuthTokenType",
|
|
labelKey: "settings.merge.gitLabTokenType",
|
|
labelFallback: "GitLab token type",
|
|
/*
|
|
FNXC:SettingsSearch 2026-07-15-20:30:
|
|
No helpKey/helpFallback: the row carries none in the section either. Its enable/disable context comes from the disclosure hint above it, which belongs to no single row and so cannot be indexed as one row's help.
|
|
*/
|
|
keywords: ["personal access token", "project access token", "group access token", "pat"],
|
|
},
|
|
{
|
|
sectionId: "source-control",
|
|
key: "gitlabAuthToken",
|
|
labelKey: "settings.merge.gitLabAccessToken",
|
|
labelFallback: "GitLab access token",
|
|
helpKey: "settings.merge.gitLabAuthTokenHint",
|
|
helpFallback:
|
|
"Read-only GitLab operations need read_api or api. Future write actions such as comments and auto-close need api. Project and group tokens are limited to their associated resource and role membership. No default — unset.",
|
|
keywords: ["glpat", "private-token", "credentials", "secret", "read_api"],
|
|
},
|
|
...[
|
|
["jiraBaseUrl", "JIRA site URL", "JIRA site URL. Default: unset."],
|
|
["jiraApiBaseUrl", "JIRA API base URL (optional)", "Default: <site>/rest/api/3."],
|
|
["jiraAuthEmail", "JIRA account email (optional)", "Email selects Basic authentication. Default: unset."],
|
|
["jiraAuthTokenSecretKey", "JIRA token secret key", "Secret-store key only. Default: JIRA_API_TOKEN."],
|
|
["jiraAuthTokenSecretScope", "JIRA token secret scope", "Default: project."],
|
|
["jiraBranchNameTemplate", "JIRA branch-name template", "Default: feature/{key}-{summary}."],
|
|
].map(([key, labelFallback, helpFallback]) => ({ sectionId: "source-control", key, labelKey: `settings.jira.${key}`, labelFallback, helpKey: `settings.jira.${key}Help`, helpFallback, keywords: ["jira", "branch", "tracker"] })),
|
|
|
|
];
|