mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 21:05:21 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Each task has one assignee. Explicit assignment and review requests select who should act. > - An agent mention started another agent on a task it did not own. Native attachment staging then rejected that run. > - Allowing that run through startup could also let two agents work on the same task. > - Mentions should identify relevant context. They should not start work or forward comments to other tasks. > - A personal app installed on a shared agent must also wait until tool use to resolve the current user's grant. > - This pull request removes mention dispatch and keeps missing personal app credentials from blocking startup. ## Linked Issues or Issue Description **What happened?** A native agent mentioned on another agent's task failed with `paperclip_runner_attachment_staging_not_authorized`. The source task could already be complete. A nearby optional-app warning was a separate problem: personal app tools were excluded when their shared health state required attention. **Expected behavior** An agent mention is context only. It does not wake the agent, take ownership, or copy a comment onto another task. Normal feedback still reaches the assignee. Assignment and explicit review requests still dispatch work. An unavailable personal app does not block startup or produce a startup warning. Tool use requests the current user's authorization and never uses another user's grant. **Steps to reproduce** 1. Assign a task to agent A. Post a comment that mentions agent B, including a comment that closes A's task or references B's child task. 2. Confirm the comment retains its agent link and B receives no run or deferred wake. A can still receive normal feedback. 3. Install an active personal MCP connection on B. Give only Alice a grant and leave shared health at `error`. 4. Explicitly assign work to B for another user. Confirm it can finish without using the app. 5. Ask B to use the app. Confirm its tool call shows an inline connection request for the current user. Related work: Refs #11144. This change uses the existing execution-time personal grant resolution. ## What Changed - Remove mention dispatch from standalone comments and issue updates. Remove implicit forwarding of parent comments to a mentioned worker's child task. - Ignore new requests with the legacy mention wake reason before creating a run or deferred request. Preserve already accepted queue entries, which can combine assignments and feedback with a later mention. - Remove the native mention admission, staging, and finalization exceptions from this PR. Native task ownership checks remain intact. - Keep active, installed personal app tools available despite shared health errors. Remove optional-app startup warnings. Tool execution retains the current user's grant and policy checks. - Update agent instructions and product/API docs. Refresh generated capability source anchors. ## Verification - Red: comment-route regressions reproduced extra agent wakes and child comment forwarding. A separate regression proved that cancelling by the last coalesced reason could drop an accepted assignment. - Green: the targeted route, wake queue, heartbeat, workspace, responsible-user, MCP discovery, and HTTP gateway suites passed. The final queue and heartbeat rerun passed 104 tests, the restored queue adapter passed 56, and both comment-route suites passed 135. These include accepted assignment preservation, rejection of new mention requests, and normal assignee feedback. - `pnpm -r typecheck` and `pnpm build` passed locally. The full local `pnpm test:run` attempt was interrupted for review/CI fixes, so it is not claimed as a completed local pass. It exposed a cleanup timing race in the concurrent-mention assertion, now fixed and verified across 10 repetitions. CI also exposed an obsolete test waiting for the removed mention lookup; it was reproduced and fixed, then both comment suites passed. Final full-suite verification is through CI. - Final head `bd9ea4cb05a8f081c54e017760a8999f9ea6ef44`: 54 checks passed, 2 Storybook checks intentionally skipped; no pending or failing checks. Full CI includes general and serialized suites, all 8 browser shards, runner verification, typecheck, build, and canary dry run. Greptile is 5/5 on this exact commit, with no unresolved findings. - One unchanged Cursor adapter test hit its 10-second CI timeout. All 5 tests in that file passed locally; one retry of its CI shard passed all 674 tests (3 skipped). The aggregate verification gate then passed. No code or timeout was changed for that retry. - Live browser check: inserted a structured mention with the picker on a human-owned task. The saved link remained visible. Database checks found zero new runs and zero wake requests. - Live Codex runner check: explicitly assigned that task with the unavailable personal app attached. The run succeeded and committed completion without using the app or creating a connection card. - Live browser follow-up: asked the assignee to call PostHog and mentioned another enabled agent as context. Only the assignee ran. It succeeded and displayed the existing inline connection card. Only Alice's grant existed; the run belonged to a different user. - The HTTP regression covers tool discovery with no provider calls or connection cards, first use returning the current user's authorization request, and successful retry after that user's grant exists. - App checks use an isolated local fixture and a fake MCP provider. They do not use production app credentials. ## Risks - Intentional behavior change: workflows that used mentions to wake agents must use assignment, a bounded child task, or an explicit review request. - Already accepted queue entries retain their prior rules. An old entry can combine assignment or feedback with a later mention; its last reason cannot safely identify mention-only work. New mention requests create no run or deferred wake. - Personal apps with a shared health error remain discoverable. Actual tool use still requires the responsible user's grant and existing policy gates. - No database migration or public API schema change. ## Model Used - OpenAI GPT-6 through Codex, with reasoning, repository tools, code execution, and browser testing. The exact serving model ID and context-window size are not exposed in this session. - Live native-run verification used `gpt-6-astra` through the Codex provider. ## 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>
99 lines
4.5 KiB
Markdown
99 lines
4.5 KiB
Markdown
---
|
|
title: Architecture
|
|
summary: Stack overview, request flow, and adapter model
|
|
---
|
|
|
|
Paperclip is a monorepo with four main layers.
|
|
|
|
## Stack Overview
|
|
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ React UI (Vite) │
|
|
│ Dashboard, org management, tasks │
|
|
├─────────────────────────────────────┤
|
|
│ Express.js REST API (Node.js) │
|
|
│ Routes, services, auth, adapters │
|
|
├─────────────────────────────────────┤
|
|
│ PostgreSQL (Drizzle ORM) │
|
|
│ Schema, migrations, embedded mode │
|
|
├─────────────────────────────────────┤
|
|
│ Adapters │
|
|
│ Claude Code, Codex, │
|
|
│ Process, HTTP │
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
## Technology Stack
|
|
|
|
| Layer | Technology |
|
|
|-------|-----------|
|
|
| Frontend | React 19, Vite 6, React Router 7, Radix UI, Tailwind CSS 4, TanStack Query |
|
|
| Backend | Node.js 24.11+, Express.js 5, TypeScript |
|
|
| Database | PostgreSQL 17 (or embedded PGlite), Drizzle ORM |
|
|
| Auth | Better Auth (sessions + API keys) |
|
|
| Adapters | Claude Code CLI, Codex CLI, shell process, HTTP webhook |
|
|
| Package manager | pnpm 9 with workspaces |
|
|
|
|
## Repository Structure
|
|
|
|
```
|
|
paperclip/
|
|
├── ui/ # React frontend
|
|
│ ├── src/pages/ # Route pages
|
|
│ ├── src/components/ # React components
|
|
│ ├── src/api/ # API client
|
|
│ └── src/context/ # React context providers
|
|
│
|
|
├── server/ # Express.js API
|
|
│ ├── src/routes/ # REST endpoints
|
|
│ ├── src/services/ # Business logic
|
|
│ ├── src/adapters/ # Agent execution adapters
|
|
│ └── src/middleware/ # Auth, logging
|
|
│
|
|
├── packages/
|
|
│ ├── db/ # Drizzle schema + migrations
|
|
│ ├── shared/ # API types, constants, validators
|
|
│ ├── adapter-utils/ # Adapter interfaces and helpers
|
|
│ └── adapters/
|
|
│ ├── claude-local/ # Claude Code adapter
|
|
│ └── codex-local/ # OpenAI Codex adapter
|
|
│
|
|
├── skills/ # Agent skills
|
|
│ └── paperclip/ # Core Paperclip skill (heartbeat protocol)
|
|
│
|
|
├── cli/ # CLI client
|
|
│ └── src/ # Setup and control-plane commands
|
|
│
|
|
└── doc/ # Internal documentation
|
|
```
|
|
|
|
## Request Flow
|
|
|
|
When a heartbeat fires:
|
|
|
|
1. **Trigger** — Scheduler, manual invoke, or event (assignment, assignee feedback) triggers a heartbeat
|
|
2. **Adapter invocation** — Server calls the configured adapter's `execute()` function
|
|
3. **Agent process** — Adapter spawns the agent (e.g. Claude Code CLI) with Paperclip env vars and a prompt
|
|
4. **Agent work** — The agent calls Paperclip's REST API to check assignments, checkout tasks, do work, and update status
|
|
5. **Result capture** — Adapter captures stdout, parses usage/cost data, extracts session state
|
|
6. **Run record** — Server records the run result, costs, and any session state for next heartbeat
|
|
|
|
## Adapter Model
|
|
|
|
Adapters are the bridge between Paperclip and agent runtimes. Each adapter is a package with three modules:
|
|
|
|
- **Server module** — `execute()` function that spawns/calls the agent, plus environment diagnostics
|
|
- **UI module** — stdout parser for the run viewer, config form fields for agent creation
|
|
- **CLI module** — terminal formatter for `paperclipai run --watch`
|
|
|
|
Built-in adapters: `claude_local`, `codex_local`, `process`, `http`. You can create custom adapters for any runtime.
|
|
|
|
## Key Design Decisions
|
|
|
|
- **Control plane, not execution plane** — Paperclip orchestrates agents; it doesn't run them
|
|
- **Company-scoped** — all entities belong to exactly one company; strict data boundaries
|
|
- **Single-assignee tasks** — atomic checkout prevents concurrent work on the same task
|
|
- **Adapter-agnostic** — any runtime that can call an HTTP API works as an agent
|
|
- **Embedded by default** — zero-config local mode with embedded PostgreSQL
|