Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ The plugin exposes GitHub workflow tools to Paperclip agents, including:
- review-thread reads, replies, resolve and unresolve actions, and `request_pull_request_reviewers` reviewer requests
- organization-level GitHub Project search/listing and pull-request-to-project association

`create_pull_request` is the single agent-facing delivery call for both branch publication and PR creation. The caller supplies the Paperclip issue id, a plain local branch name, the exact 40-character local branch-tip SHA, the base branch, and the PR metadata. The trusted plugin worker verifies checkout ownership, resolves the issue's execution worktree and GitHub secret, verifies the checked-out branch, worktree HEAD, local branch tip, and base ancestry, publishes only that exact commit with a non-forcing refspec, reads the remote branch SHA back, and only then creates and links the PR. The GitHub credential is never returned to or injected into the calling agent.

Branch publication uses an isolated temporary bare repository backed by the trusted workspace object database. It does not execute repository hooks, accept arbitrary refspecs, or honor agent-supplied remote URLs. Publication rejects owner-qualified heads, base-branch targets, non-fast-forward updates, cross-project issues, mismatched local branch tips, and remote SHA mismatches.

The call is ordered and retry-safe rather than a cross-system transaction: a published branch may remain if GitHub PR creation or Paperclip link persistence fails. On retry, the tool re-verifies and republishes the exact SHA, then recovers an already-open PR only when repository, head, base, and head SHA all match before repairing the link and metric. It never deletes a branch or closes a PR as automatic compensation.

When an agent sends GitHub body content through the plugin, including issue bodies, pull request descriptions, comments, and review-thread replies, the plugin adds a GitHub-flavored Markdown footer with a horizontal rule and compact heading that discloses AI authorship. If the tool caller supplies `llmModel`, the footer also includes the model name, for example `###### ✨ This comment was AI-generated using gpt-5.4`.

### KPI attribution API route
Expand Down
7 changes: 6 additions & 1 deletion SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ The plugin MUST persist repository mappings, company-scoped advanced issue defau
- The plugin MUST expose agent tools for the GitHub issue and pull request workflow around synced work, including repository-item search, issue reads and updates, `assign_to_current_user` for assigning issues to the GitHub user authenticated by the saved token, issue comment reads and writes, pull request creation and updates, pull request asset upload, pull request file and CI inspection, review-thread reads and replies, review-thread resolution changes, `request_pull_request_reviewers` reviewer requests, organization-level GitHub Project search/listing, associating pull requests with organization-level GitHub Projects, and `link_github_item` for linking a Paperclip issue to a GitHub issue or pull request in mapped or third-party repositories.
- Agent tools that send non-empty freeform GitHub body content, such as issue bodies, pull request descriptions, comments, or review-thread replies, MUST append a GitHub-flavored Markdown footer that uses a horizontal rule plus a compact heading to disclose that a Paperclip AI agent created the message. When the caller provides an `llmModel`, that footer MUST also include which LLM was used.
- The plugin MUST expose an agent-authenticated native plugin JSON API route for recording Paperclip-attributed pull request metric events, and `create_pull_request` MUST automatically record a pull-request-created metric event when it succeeds.
- `create_pull_request` SHOULD accept a Paperclip issue id and, when present, MUST persist a pull-request link entity for the created PR so scheduled/manual sync can reconcile that issue from PR status even when the PR does not close a synced GitHub issue.
- `create_pull_request` MUST be the single agent-facing operation for branch publication and pull-request creation. It MUST require a Paperclip issue id, plain local head branch name, exact full local branch-tip commit SHA, base branch, and PR title.
- `create_pull_request` MUST assert issue checkout ownership and resolve the issue's trusted execution workspace plus company-scoped GitHub secret inside the plugin worker. It MUST NOT use the project primary workspace, require or return an agent-visible GitHub token, or expose a separate agent-facing branch-push tool.
- Before creating the PR, `create_pull_request` MUST verify that the issue, execution workspace, and mapped repository belong to the calling run company and project; the issue is checked out by the calling agent/run; the requested branch is checked out in that execution worktree; both worktree `HEAD` and the local branch tip equal the supplied commit SHA; the head differs from the base; and the commit descends from the fetched remote base. It MUST publish only the exact commit to the exact head branch without force, verify the remote SHA, and only then call GitHub's PR API.
- Branch publication MUST use a sanitized Git execution context that does not execute repository hooks or honor agent-controlled credential helpers, remotes, proxies, or arbitrary refspecs. Errors and logs MUST redact the resolved token.
- After successful PR creation, `create_pull_request` MUST persist a pull-request link entity for the supplied Paperclip issue so scheduled/manual sync can reconcile that issue from PR status even when the PR does not close a synced GitHub issue.
- `create_pull_request` MUST be retry-safe across partial outcomes. If GitHub reports that a PR already exists after exact-SHA publication, the worker MAY reuse an open PR only when repository, head branch, base branch, and head SHA all match, then MUST reconcile the durable link and metric. It MUST NOT delete branches or close PRs as automatic compensation.
- That API route MUST accept `pull_request_created`, MUST use the host-provided authenticated agent company as the metric company, MUST reject any payload `companyId` that disagrees with that company, and MUST deduplicate repeated events using a stable pull-request identity or an explicit event key.
- When that API route receives a Paperclip issue id, it MUST verify the live pull request and persist the same pull-request link entity that `create_pull_request` writes, so PRs created through `gh` or another non-plugin client still feed future issue status sync.
- That API route MUST rely on the Paperclip host's `api.routes.register` authentication and company access checks, so missing, invalid, expired, non-agent, or cross-company `PAPERCLIP_API_KEY` requests are rejected before worker dispatch.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"dev": "node ./scripts/build.mjs --watch",
"dev:ui": "paperclip-plugin-dev-server --root . --ui-dir dist/ui --port 4177",
"prepack": "pnpm build",
"test": "node --test tests/build-script.spec.mjs && tsx --test tests/plugin.spec.ts",
"test": "node --test tests/build-script.spec.mjs && tsx --test tests/git-branch-publisher.spec.ts tests/plugin.spec.ts",
"test:e2e": "pnpm build && pnpm exec playwright install chromium && node ./scripts/e2e/run-paperclip-smoke.mjs",
"typecheck": "tsc --noEmit",
"verify:manual": "pnpm build && node ./scripts/e2e/manual-paperclip-verify.mjs"
Expand Down
Loading