Skip to content

fix(git-forges): resolve @me to a real nickname for Bitbucket issue filters#1777

Open
gfargo-horizon-agent[bot] wants to merge 1 commit into
mainfrom
agent/coco-980-coco-1692-medium-bitbucket-issue-list-me
Open

fix(git-forges): resolve @me to a real nickname for Bitbucket issue filters#1777
gfargo-horizon-agent[bot] wants to merge 1 commit into
mainfrom
agent/coco-980-coco-1692-medium-bitbucket-issue-list-me

Conversation

@gfargo-horizon-agent

@gfargo-horizon-agent gfargo-horizon-agent Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

What

Fixes coco issues --mine on Bitbucket remotes returning every issue in the repo instead of only the authenticated user's issues.

Why

Closes #1692

Plane: OSS-980

buildIssueEndpoint skipped the assignee/reporter query clause whenever the filter value was the literal @me, and getBitbucketIssueList never applied any client-side filtering to compensate — despite a test comment claiming it did. The result: coco issues --mine fetched and rendered the full unfiltered issue list under a "mine" header.

How

  • Added getBitbucketCurrentUserNickname(runner) in bitbucketCli.ts, which calls GET /user and returns the authenticated user's nickname (mirrors the existing /user usage in getBitbucketStatus).
  • In getBitbucketIssueList, resolve @me (for assignee and/or author) to the real nickname before building the issue endpoint, so the existing assignee.nickname = "<me>" / reporter.nickname = "<me>" query clauses fire server-side with correct pagination.
  • If /user resolution fails or returns no nickname, fall back to an empty issue list rather than ever rendering an unfiltered list as "mine".
  • Corrected the stale test comment at bitbucketListData.test.ts:121 ("handled client-side") and added coverage for: --assignee @me, --author @me, failed resolution → empty list, and that a named (non-@me) filter doesn't trigger an extra /user call.

Out of scope: getBitbucketPullRequestList has the analogous defect for coco prs --mine — flagged for a follow-up, not fixed here.

Testing

  • build passes
  • tests pass / added (npm run test:jest)
  • lint clean
  • CI: pending

🤖 Generated by the harbor agent loop. Reviewed by a human before merge.

Closes #1692

…ilters

getBitbucketIssueList silently dropped the assignee/author @me filter
and never applied it client-side despite a test comment claiming it
did, so `coco issues --mine` returned every issue in the repo instead
of just the user's own.

Resolve @me via GET /user before building the issue query, so the
existing assignee.nickname / reporter.nickname clauses fire
server-side with the real nickname. If resolution fails, return an
empty list rather than rendering everyone's issues as "mine".

@gfargo-horizon-agent gfargo-horizon-agent Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 Agent review (sonnet) — LGTM

REVIEW: LGTM
RESOLVES: full

The PR correctly resolves '@me' to a real Bitbucket nickname via GET /user before building the issues query, with a safe empty-list fallback when resolution fails, matching the implementation plan exactly and scoped to the three files it named. Tests (including the previously-stale @me test) and lint pass, and the change avoids scope creep into the analogous PR-list defect noted as out-of-scope in the plan.

@gfargo-horizon-agent gfargo-horizon-agent Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 Agent re-review (sonnet, delta) — CONCERNS

REVIEW: CONCERNS
RESOLVES: full

The revise correctly moves @me resolution before the fetch so the Bitbucket query is now scoped server-side, and adds solid test coverage for assignee/author/@me and named-filter paths. However, it silently swallows unresolvable @me into an empty issue list instead of surfacing an error, which is inconsistent with the sibling PR-list path in the same file that still throws a descriptive 'Could not resolve "@me"' message.

  • ⚠️ Unresolvable @me now fails silently as empty listsrc/git/bitbucketListData.ts:342 — Previously (and still for the PR-list loader in this same file) an unresolvable '@me' throws a descriptive error ('Could not resolve "@me" to a Bitbucket user...') that loadForgeList surfaces via the envelope's message field. This change instead returns { issues: [] } with no message, so coco issues --mine silently renders zero issues when the nickname lookup fails (e.g. auth token lacks a nickname), giving the user no indication their identity couldn't be resolved — they'll just believe they have no assigned issues. This creates a UX inconsistency between the PR and issue list code paths for the identical failure mode.

@gfargo-horizon-agent gfargo-horizon-agent Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 Agent re-review (sonnet, delta) — CONCERNS

REVIEW: CONCERNS
RESOLVES: full

The revise correctly fixes the original bug by resolving '@me' to a real nickname and scoping the Bitbucket query server-side, but it stacks this on top of the pre-existing (already-merged) client-side '@me' resolution/filter block instead of replacing it, so every --mine request now hits GET /user twice and runs a now-redundant client-side filter.

  • ⚠️ New @me resolution duplicates pre-existing resolveBitbucketMeNickname callsrc/git/bitbucketListData.ts:378 — getBitbucketIssueList now resolves '@me' twice: once via the new getBitbucketCurrentUserNickname (line ~341, used to build effectiveFilter for the server-side query) and again via the older resolveBitbucketMeNickname (line 378, still present from a prior revision, used for a now-redundant client-side re-filter of the already-scoped results). Both call GET /user with identical logic (bitbucketCli.ts's new getBitbucketCurrentUserNickname duplicates the nicknameOf-based parsing resolveBitbucketMeNickname already did). This doubles the network round-trip for every --mine request and introduces an inconsistent failure mode: if the first resolution succeeds but the second (entirely superfluous) call fails, the request throws 'Could not resolve "@me"...' even though the correctly-filtered data was already fetched.

@gfargo-horizon-agent gfargo-horizon-agent Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 Agent re-review (sonnet, delta) — CONCERNS

REVIEW: CONCERNS
RESOLVES: full

The revise correctly fixes the reported bug: '@me' is now resolved to a real Bitbucket nickname via GET /user and substituted into the query before buildIssueEndpoint runs, with tests covering resolution, fallback, and non-'@me' isolation. Two quality issues remain: a failed '@me' resolution silently renders as zero issues instead of an error, and the fix duplicates an already-merged, more complete fix on main (commit 34020b3 / PR #1778) that also covers the PR list and fails loudly, so this branch will need reconciliation before merge.

3 concerns — 3 inline on the diff

let effectiveFilter = filter
if (filter.assignee === '@me' || filter.author === '@me') {
const me = await getBitbucketCurrentUserNickname(runner)
if (!me) return { issues: [] }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Failed '@me' resolution silently returns empty issue list

getBitbucketCurrentUserNickname swallows all failures (network error, malformed JSON, missing nickname field) into undefined, and the caller responds by returning { issues: [] } with no error or message. A user running --mine during an auth hiccup sees an indistinguishable "you have zero issues" instead of being told resolution failed. Note that main's independently-merged fix (commit 34020b3) throws an explicit error in this exact situation instead.

fetch: async (project) => {
let effectiveFilter = filter
if (filter.assignee === '@me' || filter.author === '@me') {
const me = await getBitbucketCurrentUserNickname(runner)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Redundant GET /user call on every --mine issue query

loadForgeList's auth probe already calls getBitbucketStatus, which itself calls runner('user') and discards the body just to check the request succeeds. getBitbucketCurrentUserNickname then issues a second, identical runner('user') call to extract the nickname. Every issue-list request filtered by '@me' now makes two round trips to the same endpoint where one would do.

Comment thread src/git/bitbucketCli.ts

/**
* Resolve the authenticated user's nickname via GET /user, so callers can
* translate a literal `@me` filter into a real Bitbucket query clause.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Fix duplicates an already-merged, more complete fix on main

origin/main (commit 34020b3, PR #1778, 'fix(git): resolve @me to Bitbucket nickname in PR/issue list filters') already solves this exact bug for both the PR list and issue list, using an explicit-error approach rather than a silent empty-list fallback. This branch was cut before that landed and reimplements the same fix independently and less completely (issue list only, silent failure). Merging/rebasing this PR onto current main will conflict with and likely need to be dropped in favor of the already-shipped fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Medium] Bitbucket issue list: '@me' filter is dropped from the query and never applied client-side, so --mine returns ALL issues

0 participants