OpenHands / OpenHands/enterprise
Make repository selection optional for Jira and Jira DC resolvers
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 4
- Forks
- 2
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 101
Description
Summary
Both the Jira and Jira DC resolvers currently refuse to start a conversation unless they can infer and verify exactly one repository from the triggering issue/comment. This is stricter than necessary and blocks legitimate use cases:
- Repo-less tasks (e.g., "translate this comment to German and post it back")
- Multi-repo workflows (e.g., "compare the implementations in frontend-app and backend-api")
- Ambiguous mentions that the agent could clarify at runtime using skills
The resolvers should instead allow zero, one, or multiple repos, and defer resolution to the agent when unclear — mirroring how the GitHub resolver already works (repo is provided by the webhook context) and how Slack allows a "No Repository" option.
Current Behavior
Jira (Cloud)
JiraFactory._select_single_repo()(enterprise/integrations/jira/jira_view.py:402-427) raisesRepositoryNotFoundErroriflen(verified_repos) != 1.- Zero repos → "Could not determine which repository to use."
- Multiple repos → "Multiple repositories found: …. Please specify exactly one."
- The agent/conversation is never started.
Jira DC (Data Center)
JiraDcManager.is_job_requested()(enterprise/integrations/jira_dc/jira_dc_manager.py:487-524) returnsFalseunlesslen(verified_repos) == 1.- Zero repos → posts "Could not access any of the mentioned repositories" (or "Could not determine which repository to use") and stops.
- Multiple repos → posts "Multiple repositories found…" and stops.
JiraDcNewConversationView.create_or_update_conversation()(line 86) has a second guard that raisesStartingConvoException('No repository selected…').
Both use infer_repo_from_message() (enterprise/integrations/utils.py:173) to extract candidate repos from free text.
Why This Is Too Restrictive
-
Repo-less tasks are blocked. Example from a real C24 support bundle: user wants to "translate this comment" — no repo needed. Today: refused.
-
The agent could resolve ambiguity at runtime. If two repos are mentioned, the agent could read the issue, ask a clarifying question in a Jira comment, or infer from context (linked PRs, previous comments). Today: hard refusal upfront.
-
Contrast with other integrations:
- GitHub/Bitbucket DC: repo comes from the webhook payload (inherently unambiguous).
- Slack: offers an explicit "No Repository" button and starts the conversation in an empty workspace; the agent can clone repos later via skills.
- Jira should be at least as flexible as Slack.
-
The agent has the tools to handle this. Once started with credentials, the agent can:
- Use the git-provider skill to search/verify/clone repos.
- Post a Jira comment asking the user for clarification.
- Proceed without a repo if the task doesn't require one.
Refusing before the agent even runs discards these capabilities.
Related Issues
- Linear APP-1068: "Jira missing repo information should be optional" — already identified for the regular Jira integration.
- Trailing punctuation regex bug (not yet filed):
infer_repo_from_messagefails to match repos followed by?/!/;due to a too-narrow right-boundary indirect_pattern(line 215). Example:"in repo BANKAPP/bank-android?"extracts nothing. This is a separate one-line fix but contributes to the perception that repo inference is fragile.
Proposed Solution
High-Level Behavior
- ≥1 repo confidently inferred → clone it (or them, if multi-repo is supported) and start.
- 0 repos → start the conversation in an empty workspace (or with an initialized git repo, mirroring Slack's "No Repository" path). Let the agent decide: read the issue, use skills to clone, or ask the user.
- Ambiguous/multiple → start anyway; optionally post a clarifying comment, but don't block.
Code Changes Required
Both Integrations
enterprise/integrations/utils.py— fix the trailing-punctuation regex bug:
Strip any trailing# Line 215: broaden right boundary to allow ?!; as delimiters r'(?=\s|$|}}|[\]\)\'",.:;!?`])' # right boundary.from the captured repo name (mirror the existing.gitcleanup).
Jira (Cloud)
enterprise/integrations/jira/jira_view.py:_select_single_repo()(line 402): instead of raising on zero or multiple, log and returnNone(or the first verified repo, or all of them). Caller must handleNone._infer_repository()(line 431): catchRepositoryNotFoundErrorand returnNoneinstead of propagating.create_view()(line 464): allowview.selected_repo = None.JiraNewConversationView.create_or_update_conversation()(line ~184): drop theif not self.selected_repo: raise StartingConvoException(…)guard._create_v1_conversation(): passselected_repository=Nonewhen appropriate; ensure credentials are still injected even without a repo (this path already exists for Slack "No Repository").
Jira DC
enterprise/integrations/jira_dc/jira_dc_manager.py:is_job_requested()(line 487): change the zero/multiple logic fromreturn Falsetoreturn True(with optional clarifying comment for the user). Setjira_dc_view.selected_repo = Noneorverified_repos[0]as appropriate.- OR keep the current short-circuit but add a fallback: if zero verified, still return
Trueand proceed with no repo.
enterprise/integrations/jira_dc/jira_dc_view.py:JiraDcNewConversationView.create_or_update_conversation()(line 86): drop theif not self.selected_repo: raise StartingConvoException('No repository selected…')guard._create_v1_conversation(): handleselected_repository=Nonegracefully.
Multi-Repo Support (Optional, Larger Lift)
AppConversationStartRequestcurrently takes a singleselected_repository. True multi-repo cloning (passing a list, auto-cloning all) is a broader runtime change.- Pragmatic first step: auto-clone at most one unambiguous repo; let the agent clone additional repos via skills.
Benefits
- Unblocks legitimate use cases (repo-less tasks, multi-repo, agent-driven clarification).
- Parity with Slack's flexibility (no hard refusal for missing/ambiguous repo).
- Leverages the agent's capabilities (skills, clarifying questions, context inference) instead of discarding them.
- Simpler failure mode: if the agent truly needs a repo and none is available, it can post a Jira comment asking — a better UX than a pre-flight refusal.
Testing Strategy
- Repo-less task: Jira issue with
"@openhands translate this comment to German"(no repo mention). Verify: conversation starts, agent responds (even if it says "I need more context"). - Trailing punctuation:
"@openhands clone BANKAPP/bank-android?"(with?). Verify: repo is extracted and cloned (once regex is fixed). - Multiple repos: Issue mentions two repos. Verify: conversation starts (agent may ask which one, or clone both if multi-repo is supported).
- Zero matches, git provider connected: Verify: conversation starts in empty workspace; agent can use skills to search/clone.
Open Questions
- Multi-repo cloning: Do we want to support auto-cloning multiple inferred repos in the initial request, or defer that to agent-driven skill usage?
- UI/messaging: When starting with zero/multiple repos, should we always post an initial Jira comment to set expectations (e.g., "Starting without a pre-selected repo; I'll infer from context"), or only when truly ambiguous?
- Backward compat: Are there workflows that rely on the hard refusal as a safety check (e.g., "don't start unless a repo is explicit")? If so, could we make it a workspace/org setting?
Related Linear Issue: APP-1068
Affected Files:
enterprise/integrations/utils.py:173,215(regex bug + shared inference)enterprise/integrations/jira/jira_view.py:402,431,464,184(regular Jira guards)enterprise/integrations/jira_dc/jira_dc_manager.py:487(Jira DC gate)enterprise/integrations/jira_dc/jira_dc_view.py:86(Jira DC guard)
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with JiraFactory._select_single_repo() and _infer_repository() in enterprise/integrations/jira/jira_view.py, then trace JiraDcManager.is_job_requested() and the conversation guards in jira_dc_view.py. Compare the existing Slack “No Repository” path for credential and empty-workspace handling. Done means repo-less, ambiguous, and multi-repository Jira requests start conversations without the current hard refusal, with the listed testing scenarios covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100