paperclip-github-plugin 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/dist/manifest.js +1 -1
- package/dist/ui/index.js +47 -12
- package/dist/ui/index.js.map +2 -2
- package/dist/worker.js +747 -130
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -61,14 +61,16 @@ If a company already has a Paperclip project bound to a GitHub repository worksp
|
|
|
61
61
|
|
|
62
62
|
### Status sync with delivery context
|
|
63
63
|
|
|
64
|
-
The plugin does more than mirror issue text. It looks at linked pull requests, CI, review threads, and trusted new GitHub comments so imported Paperclip issues can reflect where the work actually is.
|
|
64
|
+
The plugin does more than mirror issue text. It looks at linked pull requests, mergeability, CI, review threads, and trusted new GitHub comments so imported Paperclip issues can reflect where the work actually is. When GitHub links an issue to a pull request in another repository, GitHub Sync now follows that pull request's actual repository for status checks, review-thread state, and deep links instead of assuming the issue repository. When sync closes an imported issue as `done` or `cancelled`, it also clears any pending Paperclip review or approval execution state so the host accepts the terminal transition cleanly.
|
|
65
65
|
|
|
66
66
|
### Project pull request command center
|
|
67
67
|
|
|
68
|
-
Each mapped project can expose a **Pull Requests** entry in the sidebar that opens a live GitHub queue page for that repository. The sidebar badge uses a lightweight total-count read, while the queue keeps the default view fast by loading only the current 10-row page, uses a repo-wide metrics read for the summary cards, reuses that cached metrics scan to keep filtered views fast by fetching only the visible filtered rows, keeps repo-scoped count, metrics, and per-PR review/check insight caches warm for repeat visits, lets operators explicitly bust those caches with Refresh when they want a live reread, shows total, mergeable, reviewable, and failing cards that filter the table, includes an **Up to date** column that distinguishes current branches, clean update candidates, conflict cases, and unknown freshness when GitHub cannot confirm the comparison, shows the PR target branch with a highlighted default-branch badge, keeps the list sorted by most recently updated first, paginates larger repositories, keeps a compact bottom detail pane with markdown-and-HTML-rendered conversation plus an inline comment composer, supports deterministic **Update branch** actions for clean behind-base pull requests, adds Copilot quick actions that post `@copilot` requests for **Fix CI**, **Rebase**, and **Address review feedback**, requests Copilot through GitHub’s native reviewer flow for **Review**, keeps comment, review, quick approve/request-changes, re-run CI, merge, and close actions available, lets the review modal submit comment-only, approve, or request-changes reviews, hides any pull request action whose required GitHub permission is not verified for the saved token, and opens linked Paperclip issues in a plugin-provided right drawer so operators can stay on the queue page.
|
|
68
|
+
Each mapped project can expose a **Pull Requests** entry in the sidebar that opens a live GitHub queue page for that repository. The sidebar badge uses a lightweight total-count read, while the queue keeps the default view fast by loading only the current 10-row page, uses a repo-wide metrics read for the summary cards, reuses that cached metrics scan to keep filtered views fast by fetching only the visible filtered rows, keeps repo-scoped count, metrics, and per-PR review/check insight caches warm for repeat visits, lets operators explicitly bust those caches with Refresh when they want a live reread, shows total, mergeable, reviewable, and failing cards that filter the table, only treats a pull request as mergeable when it targets the current default branch with green checks, at least one approval, no outstanding change requests, and no unresolved review threads, includes an **Up to date** column that distinguishes current branches, clean update candidates, conflict cases, and unknown freshness when GitHub cannot confirm the comparison, shows the PR target branch with a highlighted default-branch badge, keeps the list sorted by most recently updated first, paginates larger repositories, keeps a compact bottom detail pane with markdown-and-HTML-rendered conversation plus an inline comment composer, supports deterministic **Update branch** actions for clean behind-base pull requests, adds Copilot quick actions that post `@copilot` requests for **Fix CI**, **Rebase**, and **Address review feedback**, requests Copilot through GitHub’s native reviewer flow for **Review**, keeps comment, review, quick approve/request-changes, re-run CI, merge, and close actions available, lets the review modal submit comment-only, approve, or request-changes reviews, hides any pull request action whose required GitHub permission is not verified for the saved token, and opens linked Paperclip issues in a plugin-provided right drawer so operators can stay on the queue page.
|
|
69
69
|
|
|
70
70
|
Paperclip issue linkage on the queue prefers the GitHub issue that the pull request closes, so imported GitHub issues and delivery work stay connected in the same project view. If a pull request has no closing-issue-backed link yet, the queue falls back to the Paperclip issue created directly from that pull request and updates the table immediately when that create action returns.
|
|
71
71
|
|
|
72
|
+
The issue detail panel and sync-created comment annotations also preserve cross-repository linked pull requests, showing those PRs with their real repository path so operators land in the right place on GitHub.
|
|
73
|
+
|
|
72
74
|
### Agent workflows built in
|
|
73
75
|
|
|
74
76
|
Paperclip agents can search GitHub for duplicates, read and update issues, post comments, create pull requests, inspect changed files and CI, reply to review threads, resolve or unresolve threads, request reviewers, search org-level GitHub Projects, and associate pull requests with those projects without leaving the Paperclip plugin surface.
|
|
@@ -136,8 +138,8 @@ When the local Paperclip API is available, the plugin also syncs labels by name,
|
|
|
136
138
|
| Open issue with no linked pull request, created by a repository maintainer | `todo` on first import |
|
|
137
139
|
| Open issue with no linked pull request | Configured default status, which defaults to `backlog` |
|
|
138
140
|
| Open issue with a linked pull request and unfinished CI | `in_progress` |
|
|
139
|
-
| Open issue with failing CI or unresolved review threads | `todo`, or `in_progress` when GitHub Sync can hand the work back to an executor |
|
|
140
|
-
| Open issue with green CI and all review threads resolved | `in_review` |
|
|
141
|
+
| Open issue with failing CI, a non-mergeable linked pull request, or unresolved review threads | `todo`, or `in_progress` when GitHub Sync can hand the work back to an executor |
|
|
142
|
+
| Open issue with green CI, a merge-ready linked pull request, and all review threads resolved | `in_review` |
|
|
141
143
|
| Closed issue completed as finished work | `done` |
|
|
142
144
|
| Closed issue closed as `not_planned` or `duplicate` | `cancelled` |
|
|
143
145
|
|
|
@@ -146,12 +148,13 @@ Additional behavior:
|
|
|
146
148
|
- Open issues with no linked pull request that are created by a verified repository maintainer/admin bypass the default imported status and start in `todo`.
|
|
147
149
|
- When Paperclip board access is connected for a company, the advanced assignee dropdowns list both company agents and `Me` for the connected board user.
|
|
148
150
|
- Newly imported issues that finish sync in `todo` and are assigned to an agent enqueue an assignee wakeup so the agent can pick them up promptly.
|
|
149
|
-
-
|
|
151
|
+
- For linked pull requests, GitHub Sync treats merge-conflict, behind-branch, blocked, draft, and unstable merge states as executor work, while merge-ready states such as `CLEAN` and `HAS_HOOKS` can move work into `in_review` when CI and review threads are also clear.
|
|
152
|
+
- When sync moves work into `in_review`, GitHub Sync first follows the Paperclip issue execution policy's current reviewer or approver when that stage is visible on the issue. If Paperclip exposes an internal review or approval stage but not yet the participant, the plugin falls back to the configured reviewer or approver handoff assignee. If the transition is only a healthy linked-PR wait with no visible internal review or approval stage, GitHub Sync leaves the issue unassigned so it can wait on normal maintainer review without waking an internal owner.
|
|
150
153
|
- When sync moves work back into active execution, GitHub Sync first follows the Paperclip issue execution policy `returnAssignee` when it is available. Otherwise it falls back to the configured executor handoff assignee and then to the default imported assignee.
|
|
151
154
|
- Sync-driven handoffs to agent assignees best-effort enqueue an explicit wakeup so the next reviewer, approver, or executor can pick the issue up even when their agent is not running heartbeats.
|
|
152
155
|
- Open imported issues that are already in `backlog` stay in `backlog` until someone changes them in Paperclip.
|
|
153
156
|
- If an imported issue is `done` or `cancelled` and GitHub shows it open again with no linked pull request, sync moves it to `todo` so agents can pick it up again.
|
|
154
|
-
- Trusted new GitHub comments from the original issue author or a verified maintainer/admin can move an open imported issue back into active work,
|
|
157
|
+
- Trusted new GitHub comments from the original issue author or a verified maintainer/admin can move an open imported issue back into active work, whether the new comment lands on the source issue, in a linked pull request's top-level comment stream, or in a linked pull request review thread; GitHub Sync uses `in_progress` when it can route the issue to an executor and otherwise `todo`.
|
|
155
158
|
- When the sync changes a Paperclip issue status, it adds a Paperclip comment explaining what changed and why.
|
|
156
159
|
|
|
157
160
|
## Security and authentication
|
package/dist/manifest.js
CHANGED
|
@@ -511,7 +511,7 @@ var require2 = createRequire(import.meta.url);
|
|
|
511
511
|
var packageJson = require2("../package.json");
|
|
512
512
|
var DASHBOARD_WIDGET_CAPABILITY = "ui.dashboardWidget.register";
|
|
513
513
|
var SCHEDULE_TICK_CRON = "* * * * *";
|
|
514
|
-
var MANIFEST_VERSION = "0.5.
|
|
514
|
+
var MANIFEST_VERSION = "0.5.3"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
|
|
515
515
|
var manifest = {
|
|
516
516
|
id: "paperclip-github-plugin",
|
|
517
517
|
apiVersion: 1,
|
package/dist/ui/index.js
CHANGED
|
@@ -27789,8 +27789,13 @@ function resolvePreviewPullRequestReviewable(record) {
|
|
|
27789
27789
|
const unresolvedCopilotThreads = typeof record.copilotUnresolvedReviewThreads === "number" ? record.copilotUnresolvedReviewThreads : record.unresolvedReviewThreads;
|
|
27790
27790
|
return record.githubMergeable === true && record.checksStatus === "passed" && unresolvedCopilotThreads === 0;
|
|
27791
27791
|
}
|
|
27792
|
-
function
|
|
27793
|
-
|
|
27792
|
+
function resolvePreviewPullRequestTargetsDefaultBranch(record, options) {
|
|
27793
|
+
const baseBranch = record.baseBranch.trim();
|
|
27794
|
+
const defaultBranchName = options?.defaultBranchName?.trim();
|
|
27795
|
+
return Boolean(baseBranch && defaultBranchName && baseBranch === defaultBranchName);
|
|
27796
|
+
}
|
|
27797
|
+
function resolvePreviewPullRequestMergeable(record, options) {
|
|
27798
|
+
return record.githubMergeable === true && record.checksStatus === "passed" && record.reviewApprovals > 0 && record.reviewChangesRequested === 0 && record.unresolvedReviewThreads === 0 && resolvePreviewPullRequestTargetsDefaultBranch(record, options);
|
|
27794
27799
|
}
|
|
27795
27800
|
function matchesPreviewPullRequestFilter(record, filter) {
|
|
27796
27801
|
switch (filter) {
|
|
@@ -28845,6 +28850,26 @@ function formatSyncFailureRepository(repositoryUrl) {
|
|
|
28845
28850
|
}
|
|
28846
28851
|
return repositoryUrl.trim();
|
|
28847
28852
|
}
|
|
28853
|
+
function getLinkedPullRequestsForIssueDetails(issueDetails) {
|
|
28854
|
+
if (issueDetails.linkedPullRequests && issueDetails.linkedPullRequests.length > 0) {
|
|
28855
|
+
return issueDetails.linkedPullRequests;
|
|
28856
|
+
}
|
|
28857
|
+
return issueDetails.linkedPullRequestNumbers.map((pullRequestNumber) => ({
|
|
28858
|
+
number: pullRequestNumber,
|
|
28859
|
+
repositoryUrl: issueDetails.repositoryUrl
|
|
28860
|
+
}));
|
|
28861
|
+
}
|
|
28862
|
+
function formatIssueDetailLinkedPullRequestLabel(pullRequest, issueRepositoryUrl) {
|
|
28863
|
+
const pullRequestRepository = parseRepositoryReference(pullRequest.repositoryUrl);
|
|
28864
|
+
if (!pullRequestRepository) {
|
|
28865
|
+
return `PR #${pullRequest.number}`;
|
|
28866
|
+
}
|
|
28867
|
+
const issueRepository = parseRepositoryReference(issueRepositoryUrl);
|
|
28868
|
+
if (issueRepository && issueRepository.owner.toLowerCase() === pullRequestRepository.owner.toLowerCase() && issueRepository.repo.toLowerCase() === pullRequestRepository.repo.toLowerCase()) {
|
|
28869
|
+
return `PR #${pullRequest.number}`;
|
|
28870
|
+
}
|
|
28871
|
+
return `${pullRequestRepository.owner}/${pullRequestRepository.repo}#${pullRequest.number}`;
|
|
28872
|
+
}
|
|
28848
28873
|
function getSyncFailureLogEntries(syncState) {
|
|
28849
28874
|
if (syncState.recentFailures?.length) {
|
|
28850
28875
|
return syncState.recentFailures.filter((entry) => typeof entry.message === "string" && entry.message.trim());
|
|
@@ -29928,7 +29953,9 @@ function GitHubSyncProjectPullRequestsPage() {
|
|
|
29928
29953
|
return {
|
|
29929
29954
|
...nextRecord,
|
|
29930
29955
|
reviewable: resolvePreviewPullRequestReviewable(nextRecord),
|
|
29931
|
-
mergeable: resolvePreviewPullRequestMergeable(nextRecord
|
|
29956
|
+
mergeable: resolvePreviewPullRequestMergeable(nextRecord, {
|
|
29957
|
+
defaultBranchName: pageData.defaultBranchName
|
|
29958
|
+
})
|
|
29932
29959
|
};
|
|
29933
29960
|
});
|
|
29934
29961
|
if (options?.closeModal) {
|
|
@@ -29989,7 +30016,9 @@ function GitHubSyncProjectPullRequestsPage() {
|
|
|
29989
30016
|
return {
|
|
29990
30017
|
...nextRecord,
|
|
29991
30018
|
reviewable: resolvePreviewPullRequestReviewable(nextRecord),
|
|
29992
|
-
mergeable: resolvePreviewPullRequestMergeable(nextRecord
|
|
30019
|
+
mergeable: resolvePreviewPullRequestMergeable(nextRecord, {
|
|
30020
|
+
defaultBranchName: pageData.defaultBranchName
|
|
30021
|
+
})
|
|
29993
30022
|
};
|
|
29994
30023
|
});
|
|
29995
30024
|
closeRerunCiModal();
|
|
@@ -30916,7 +30945,7 @@ function GitHubSyncProjectPullRequestsPage() {
|
|
|
30916
30945
|
] }),
|
|
30917
30946
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-prs-meta__row", children: [
|
|
30918
30947
|
/* @__PURE__ */ jsx2("span", { className: "ghsync-prs-meta__label", children: "Mergeability" }),
|
|
30919
|
-
/* @__PURE__ */ jsx2("div", { className: "ghsync-prs-meta__value", children: selectedPullRequest.mergeable ? "Mergeable now" : "Blocked
|
|
30948
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync-prs-meta__value", children: selectedPullRequest.mergeable ? "Mergeable now" : "Blocked by checks, review feedback, or target branch rules" })
|
|
30920
30949
|
] })
|
|
30921
30950
|
] })
|
|
30922
30951
|
] }),
|
|
@@ -32824,7 +32853,7 @@ function GitHubSyncSettingsPage() {
|
|
|
32824
32853
|
}
|
|
32825
32854
|
}
|
|
32826
32855
|
),
|
|
32827
|
-
/* @__PURE__ */ jsx2("p", { className: "ghsync__hint", children: "The assignee that resumes work when GitHub Sync sends an issue back to active execution, such as failing CI, unresolved review threads, or a trusted new GitHub comment." })
|
|
32856
|
+
/* @__PURE__ */ jsx2("p", { className: "ghsync__hint", children: "The assignee that resumes work when GitHub Sync sends an issue back to active execution, such as failing CI, non-mergeable linked pull requests, unresolved review threads, or a trusted new GitHub comment." })
|
|
32828
32857
|
] }),
|
|
32829
32858
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync__field", children: [
|
|
32830
32859
|
/* @__PURE__ */ jsx2("label", { htmlFor: "advanced-reviewer-assignee", children: "Reviewer handoff" }),
|
|
@@ -33979,6 +34008,7 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
33979
34008
|
if (detailTabState === "hidden") {
|
|
33980
34009
|
return null;
|
|
33981
34010
|
}
|
|
34011
|
+
const linkedPullRequests = issueDetails ? getLinkedPullRequestsForIssueDetails(issueDetails) : [];
|
|
33982
34012
|
return /* @__PURE__ */ jsxs2("section", { className: "ghsync-issue-detail", style: props.themeVars, children: [
|
|
33983
34013
|
/* @__PURE__ */ jsx2("style", { children: EXTENSION_SURFACE_STYLES }),
|
|
33984
34014
|
detailTabState === "loading" ? /* @__PURE__ */ jsx2("p", { className: "ghsync-extension-empty", children: "Loading GitHub sync details\u2026" }) : null,
|
|
@@ -34059,19 +34089,19 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34059
34089
|
] }),
|
|
34060
34090
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-metric", children: [
|
|
34061
34091
|
/* @__PURE__ */ jsx2("span", { children: "Linked PRs" }),
|
|
34062
|
-
/* @__PURE__ */ jsx2("strong", { children:
|
|
34092
|
+
/* @__PURE__ */ jsx2("strong", { children: linkedPullRequests.length })
|
|
34063
34093
|
] }),
|
|
34064
34094
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-metric", children: [
|
|
34065
34095
|
/* @__PURE__ */ jsx2("span", { children: "Last synced" }),
|
|
34066
34096
|
/* @__PURE__ */ jsx2("strong", { children: issueDetails.syncedAt ? formatDate(issueDetails.syncedAt, "Unknown") : "Pending refresh" })
|
|
34067
34097
|
] })
|
|
34068
34098
|
] }),
|
|
34069
|
-
|
|
34099
|
+
linkedPullRequests.length > 0 ? /* @__PURE__ */ jsxs2("div", { className: "ghsync-issue-detail__section", children: [
|
|
34070
34100
|
/* @__PURE__ */ jsx2("div", { className: "ghsync-issue-detail__section-heading", children: "Linked pull requests" }),
|
|
34071
|
-
/* @__PURE__ */ jsx2("div", { className: "ghsync-extension-links", children:
|
|
34101
|
+
/* @__PURE__ */ jsx2("div", { className: "ghsync-extension-links", children: linkedPullRequests.map((pullRequest) => /* @__PURE__ */ jsx2(
|
|
34072
34102
|
"a",
|
|
34073
34103
|
{
|
|
34074
|
-
href: `${
|
|
34104
|
+
href: `${pullRequest.repositoryUrl}/pull/${pullRequest.number}`,
|
|
34075
34105
|
target: "_blank",
|
|
34076
34106
|
rel: "noreferrer",
|
|
34077
34107
|
className: getPluginActionClassName({
|
|
@@ -34079,9 +34109,14 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
34079
34109
|
size: "sm",
|
|
34080
34110
|
extraClassName: "ghsync-extension-link"
|
|
34081
34111
|
}),
|
|
34082
|
-
children: /* @__PURE__ */ jsx2(
|
|
34112
|
+
children: /* @__PURE__ */ jsx2(
|
|
34113
|
+
GitHubButtonLabel,
|
|
34114
|
+
{
|
|
34115
|
+
label: formatIssueDetailLinkedPullRequestLabel(pullRequest, issueDetails.repositoryUrl)
|
|
34116
|
+
}
|
|
34117
|
+
)
|
|
34083
34118
|
},
|
|
34084
|
-
|
|
34119
|
+
`${pullRequest.repositoryUrl}:${pullRequest.number}`
|
|
34085
34120
|
)) })
|
|
34086
34121
|
] }) : null,
|
|
34087
34122
|
issueDetails.labels && issueDetails.labels.length > 0 ? /* @__PURE__ */ jsxs2("div", { className: "ghsync-issue-detail__section", children: [
|