Files
PaperClipAI/doc/project-repositories.md
T
DottaandPaperclip b97101893f feat(projects): select multiple GitHub source repositories (#13010)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Projects give tasks a common source repository and execution
context.
> - The current project form asks for a raw URL and unrelated metadata.
> - Teams need to select several repos from GitHub connections they can
use.
> - This pull request implements the reviewed project form and
repository editor.
> - The server checks credential ownership and shared audiences before
discovery.
> - Existing workspace URLs and runtime identity rules remain
compatible.

## Linked Issues or Issue Description

**Problem or motivation**

Project creation accepts one raw repository URL. It does not help users
select repos from their usable GitHub connections or attach several
repos together.

**Proposed solution**

Add a shared GitHub repository picker to project creation and
Configuration. Support multiple selections, transactional persistence,
and the existing GitHub setup flow. Simplify the project form and
Configuration tab as reviewed.

**Alternatives considered**

Keep a raw URL field or add a separate repository table. The existing
workspace collection already supports several repositories and keeps
legacy URLs compatible.

**Roadmap alignment**

This builds on the shipped MCP Tool Gateway and Apps capability. It does
not change runtime credential delegation.

Related work: #11662 addresses the existing dialog's viewport limits.
#4552 addresses generic Git URLs; this change preserves those URLs in
existing workspaces.

## What Changed

- Add company-scoped repository discovery from usable personal and
shared GitHub grants, with provider-ID deduplication, PAT pagination,
and partial failure handling.
- Document the repository endpoints and board access requirements in
OpenAPI.
- Validate new selections and save projects with multiple repository
workspaces in one transaction. Preserve legacy URLs and existing
selections whose access was lost.
- Implement the reviewed Create project dialog, shared repository
editor, scrolling, and mobile layout.
- Move repositories above environment variables, remove Status and Goals
controls and env help paragraphs, move Created to the bottom, and
redirect Overview to Configuration.
- Reuse GitHub setup in dialogs, preserve project drafts, and verify
popup completion through the API.
- Replace the configuration story's DOM adapter with explicit production
composition. Keep the reviewed mobile and short-viewport stories.

## Verification

- Passed: `pnpm build`, `pnpm -r typecheck`, `pnpm build-storybook`, and
`pnpm check:token-gates`.
- Passed: focused repository access, database persistence,
configuration, and connection setup tests.
- Passed: `pnpm exec playwright test --config
tests/e2e/playwright.config.ts tests/e2e/project-repositories.spec.ts`.
- The browser tests use a real temporary server/database. They cover
create, forty persisted repos, mobile scrolling, save/reload, legacy URL
editing, and rejection without a partial project.
- GitHub responses and popup completion use deterministic fixtures. No
real GitHub account was authorized by the test suite.
- All CI general, serialized server, and browser test shards pass on the
final commit.
- The local full-suite run overlapped review edits and was stopped;
fresh repository, OpenAPI, UI/CLI, and connection tests pass. Unrelated
local worker, built-in-agent, and routine timing/socket failures passed
isolated reruns.
- Final commit `1b3308dca`: all CI gates pass, including build, runner
verification, typecheck, canary dry run, and security checks. Greptile
is 5/5 with no unresolved review threads.
- Storybook visual regression is opt-in and was skipped by CI; the
Storybook build passed locally.

## Risks

- Repository discovery depends on provider availability. Failed
connections are reported while successful results stay usable.
- Selections identify source workspaces; they do not grant agents new
credentials. The existing primary-workspace and responsible-user
identity rules still apply.
- No database migration is needed. Existing API status, goals, dates,
and manual workspace URLs remain supported.

## Model Used

OpenAI Codex, based on GPT-6, with repository inspection, code
execution, and browser tools. The runtime does not expose a more
specific model deployment ID or context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-08 08:21:28 -05:00

4.1 KiB

Project source repositories

The Create project dialog accepts a name and optional GitHub repository selections. It uses the same RepositoryEditor as project Configuration. Description remains editable in Configuration. Status, goal links, and target dates remain supported by the API but are omitted from creation; Status and Goals are omitted from Configuration. Old Overview URLs and saved Overview preferences redirect to Configuration.

API and persistence

  • GET /api/companies/:companyId/project-repositories returns repositories, connectionCount, and failedConnectionCount. Repository IDs are GitHub's stable numeric IDs represented as strings. Results are deduplicated across accessible grants and sorted by full name. Connection labels are display provenance only.
  • POST /api/companies/:companyId/projects accepts optional repositoryIds. The server resolves new selections through the caller's authorized GitHub grants before creating the project and all repository workspaces in a transaction. The existing workspace input remains supported; it cannot be combined with repositoryIds.
  • PUT /api/projects/:id/repositories accepts the selected repositoryIds array. Accessible retained IDs refresh their canonical name and URL after renames or transfers; unavailable retained IDs keep their saved metadata. Replacement is transactional. Existing selections may be retained or removed even if their GitHub connection becomes unavailable. New identities require current access. Legacy URL workspaces are preserved, and matching legacy URLs are adopted without creating a duplicate workspace. Local/remote workspace locations survive detaching their repository.

No schema migration is required. Selected repositories are normal project workspaces with metadata.githubRepositoryId. Existing manual repoUrl workspaces remain editable through Configuration and the workspace API. One workspace remains primary; additional repositories do not change the existing runtime workspace-selection or responsible-user credential rules. A repository selection never delegates credentials.

Discovery and setup

The server checks company membership, grant ownership/status, and organization-grant audiences before loading provider metadata. Connection managers receive no bypass to another person's personal repositories. Managed GitHub grants refresh installation access; PAT connections use paginated /user/repos. Provider failures are reported without exposing provider error bodies or credential material. Successful connections remain selectable when another connection fails.

ConnectionSetupFlow owns provider setup in both Apps and project dialogs. Task intents retain their existing callback protocol. Standalone dialogs verify the saved connection through the API after the sign-in popup returns to the instance. Project name and repository drafts stay mounted across setup and cancellation.

UI review and verification

Proposals/Project repos contains the reviewed states, including loading, failure, empty search, disconnected GitHub, multiple repos, legacy URLs, forty selections, mobile, and short viewports. The configuration story composes the production page properties through an explicit repositories slot. Story setup and saves use fixtures.

  • Shared visual control: ui/src/components/RepositoryEditor.tsx.
  • Data and error handling: ProjectRepositoryInput.tsx.
  • Configuration persistence and legacy editing: ProjectRepositories.tsx and LegacyProjectRepository.tsx.
  • Production dialog: NewProjectDialog.tsx.
  • Server tests: project-repositories.test.ts and project-repositories-persistence.test.ts.
  • Browser acceptance: tests/e2e/project-repositories.spec.ts.

The browser suite uses a real temporary server and database. It verifies creation, forty persisted repos, mobile scrolling, removal/save/reload, legacy URL editing, and rejection without a partial project. Provider discovery is simulated in the picker rejection test. GitHub network and popup behavior use deterministic fixtures in integration/component tests; the suite does not authorize a real GitHub account.