paperclip-github-plugin 0.8.1 → 0.8.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 CHANGED
@@ -35,7 +35,7 @@ The plugin adds a full in-host workflow instead of a one-off import script:
35
35
  - saved sync diagnostics that let operators inspect the latest per-issue failures, raw errors, and suggested next steps
36
36
  - a project sidebar item that opens a live project-scoped Pull Requests page for the mapped repository and can show the open PR count through a lightweight badge read
37
37
  - manual sync actions from global, project, and issue surfaces
38
- - a GitHub detail tab on synced Paperclip issues that includes GitHub-marked action buttons plus the GitHub issue creator with avatar, and lets operators manually link an unlinked Paperclip issue to a GitHub issue or pull request
38
+ - a GitHub detail tab on synced Paperclip issues that includes GitHub-marked action buttons plus the GitHub issue creator with avatar, and lets operators manually link or unlink a Paperclip issue from a GitHub issue or pull request
39
39
  - GitHub link annotations on sync-generated status transition comments when the host supports comment annotations
40
40
 
41
41
  ## How it works
@@ -88,6 +88,8 @@ If a Paperclip issue was created locally or by an agent workflow before GitHub S
88
88
 
89
89
  Manual GitHub issue links are added to the same import registry and issue-link entity used by normal sync, so future syncs update the Paperclip issue from the GitHub issue. Manual pull request links are added to the PR-link entity used by the project Pull Requests page, so future syncs monitor PR status even when there is no closing GitHub issue.
90
90
 
91
+ Linked Paperclip issues can also be unlinked from the GitHub detail surface. Unlinking removes the active GitHub Sync link metadata and import-registry tracking for that Paperclip issue without deleting either side, so the issue stays local until it is linked again.
92
+
91
93
  ### Agent workflows built in
92
94
 
93
95
  Paperclip agents can search GitHub for duplicates, read and update issues, assign issues to the saved token owner, 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.
@@ -146,6 +148,8 @@ To keep imported issues recognizable without cluttering the visible description,
146
148
 
147
149
  Repeated syncs keep existing imports current instead of creating duplicates again. If the plugin's import registry is stale, the worker can repair deduplication by reusing existing Paperclip issues when durable GitHub link metadata is already present.
148
150
 
151
+ If a linked GitHub issue is transferred to another repository, GitHub Sync follows the canonical GitHub URL. When the destination repository is mapped to another Paperclip project in the same company, the existing Paperclip issue moves to that project and keeps its GitHub link. When the destination repository is not mapped, GitHub Sync unlinks the Paperclip issue and marks it `cancelled` with a Paperclip comment explaining the transfer.
152
+
149
153
  When the local Paperclip API is available, the plugin also syncs labels by name, prefers exact color matches when multiple Paperclip labels share the same name, and creates missing Paperclip labels when needed.
150
154
 
151
155
  ### Status mapping
@@ -163,6 +167,7 @@ When the local Paperclip API is available, the plugin also syncs labels by name,
163
167
  Additional behavior:
164
168
 
165
169
  - 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`.
170
+ - If the Paperclip host initially creates that imported maintainer issue in `backlog`, GitHub Sync promotes it to `todo` without replacing the configured default assignee with the executor handoff assignee, so triage ownership stays intact.
166
171
  - When Paperclip board access is connected for a company, the advanced assignee dropdowns list both company agents and `Me` for the connected board user.
167
172
  - 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.
168
173
  - For linked pull requests, GitHub Sync treats merge-conflict, behind-branch, blocked, draft, unstable merge states, and requested-changes review decisions as executor work, while merge-ready states such as `CLEAN` and `HAS_HOOKS` can move work into `in_review` when CI is green and there are no requested changes or unresolved review threads.
package/dist/manifest.js CHANGED
@@ -535,7 +535,7 @@ var COMPANY_METRIC_API_ROUTE_URL_PATH = `/api/plugins/${GITHUB_SYNC_PLUGIN_ID}/a
535
535
  var require2 = createRequire(import.meta.url);
536
536
  var packageJson = require2("../package.json");
537
537
  var SCHEDULE_TICK_CRON = "* * * * *";
538
- var MANIFEST_VERSION = "0.8.1"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
538
+ var MANIFEST_VERSION = "0.8.3"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
539
539
  var manifest = {
540
540
  id: GITHUB_SYNC_PLUGIN_ID,
541
541
  apiVersion: 1,
package/dist/ui/index.js CHANGED
@@ -34641,11 +34641,13 @@ function GitHubSyncIssueDetailTabContent(props) {
34641
34641
  forceVisible: true
34642
34642
  });
34643
34643
  const linkGitHubItem = usePluginAction("issue.linkGitHubItem");
34644
+ const unlinkGitHubItem = usePluginAction("issue.unlinkGitHubItem");
34644
34645
  const toast = usePluginToast();
34645
34646
  const [manualLinkOpen, setManualLinkOpen] = useState2(false);
34646
34647
  const [manualLinkKind, setManualLinkKind] = useState2("issue");
34647
34648
  const [manualLinkReference, setManualLinkReference] = useState2("");
34648
34649
  const [manualLinkPending, setManualLinkPending] = useState2(false);
34650
+ const [unlinkPending, setUnlinkPending] = useState2(false);
34649
34651
  useEffect2(() => {
34650
34652
  if (!props.companyId || !props.issueId) {
34651
34653
  return;
@@ -34703,6 +34705,36 @@ function GitHubSyncIssueDetailTabContent(props) {
34703
34705
  setManualLinkPending(false);
34704
34706
  }
34705
34707
  }
34708
+ async function handleUnlinkGitHubItem() {
34709
+ if (!props.companyId || !props.issueId || unlinkPending) {
34710
+ return;
34711
+ }
34712
+ if (typeof window !== "undefined" && !window.confirm("Unlink this Paperclip issue from GitHub? GitHub Sync will stop updating it until it is linked again.")) {
34713
+ return;
34714
+ }
34715
+ setUnlinkPending(true);
34716
+ try {
34717
+ await unlinkGitHubItem({
34718
+ companyId: props.companyId,
34719
+ issueId: props.issueId
34720
+ });
34721
+ await details.refresh();
34722
+ notifyGitHubSyncPullRequestsChanged();
34723
+ toast({
34724
+ title: "GitHub link removed",
34725
+ body: "This Paperclip issue is no longer linked to GitHub.",
34726
+ tone: "success"
34727
+ });
34728
+ } catch (error) {
34729
+ toast({
34730
+ title: "Unable to unlink GitHub item",
34731
+ body: getActionErrorMessage(error, "GitHub Sync could not remove this link."),
34732
+ tone: "error"
34733
+ });
34734
+ } finally {
34735
+ setUnlinkPending(false);
34736
+ }
34737
+ }
34706
34738
  return /* @__PURE__ */ jsxs2("section", { className: "ghsync-issue-detail", style: props.themeVars, children: [
34707
34739
  /* @__PURE__ */ jsx2("style", { children: EXTENSION_SURFACE_STYLES }),
34708
34740
  detailTabState === "loading" ? /* @__PURE__ */ jsx2("p", { className: "ghsync-extension-empty", children: "Loading GitHub sync details\u2026" }) : null,
@@ -34786,7 +34818,24 @@ function GitHubSyncIssueDetailTabContent(props) {
34786
34818
  }),
34787
34819
  children: /* @__PURE__ */ jsx2(GitHubButtonLabel, { label: "Open on GitHub" })
34788
34820
  }
34789
- ) : null
34821
+ ) : null,
34822
+ /* @__PURE__ */ jsx2(
34823
+ "button",
34824
+ {
34825
+ type: "button",
34826
+ className: getPluginActionClassName({
34827
+ variant: "danger",
34828
+ size: "sm",
34829
+ extraClassName: "ghsync-extension-link"
34830
+ }),
34831
+ disabled: unlinkPending,
34832
+ onClick: () => {
34833
+ void handleUnlinkGitHubItem();
34834
+ },
34835
+ title: "Unlink from GitHub",
34836
+ children: /* @__PURE__ */ jsx2(LoadingButtonContent, { busy: unlinkPending, label: "Unlink", busyLabel: "Unlinking" })
34837
+ }
34838
+ )
34790
34839
  ] })
34791
34840
  ] }),
34792
34841
  /* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-grid", children: [