mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-08 21:03:51 +02:00
efcce9cc8e17e2b30f6f2edf30e00a77b0bf19bb
213
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
efcce9cc8e |
fix(adapters): record unpriced CLI usage (#9505)
## Thinking Path > - Paperclip is the open source control plane people use to manage AI-agent companies > - Budgets and spend telemetry are control-plane safety features, not just reporting > - Local Codex and Claude adapters can execute through either ACP or their native CLI engines > - The ACP lane records usage and reported cost, but CLI JSON output often reports tokens without a price > - The CLI lane was either losing per-run usage semantics or coercing missing cost to zero, making real usage indistinguishable from a genuinely free run > - This pull request preserves CLI usage as per-run totals and records token-bearing runs without a reported price as explicitly unpriced ledger events > - The benefit is accurate usage accounting and a visible pricing gap instead of silently misleading zero-cost telemetry ## Linked Issues or Issue Description Refs #9471 Refs #9230 **Bug description** A `codex_local` run using the CLI engine can emit a final `turn.completed` event with millions of input tokens and tens of thousands of output tokens while the agent's spend ledger remains indistinguishable from a true zero-usage, zero-cost run. Claude CLI output has the same missing-price edge case. **Expected behavior** Token-bearing CLI runs should persist their usage. If the adapter reports a price, the ledger should record it as reported; if the CLI reports usage but no price, the ledger should explicitly mark the event as unpriced rather than silently treating missing price data as a reported `$0` cost. **Reproduction shape** 1. Configure `codex_local` with `engine: cli`. 2. Run a task that produces a `turn.completed` usage payload. 3. Observe token usage in the run stream. 4. Before this change, missing price data is represented as ordinary zero-cost spend and the CLI usage basis is not consistently propagated. ## What Changed - Mark Codex and Claude native CLI usage totals as `per_run` and propagate that basis through success and failure results. - Stop coercing missing Claude CLI cost to `0`. - Add `cost_status` to cost events with `reported` and `unpriced` values, including an idempotent migration and shared validation/types. - Persist token-bearing runs without a reported price as `unpriced` ledger events while retaining zero cents until an authoritative price exists. - Add parser, execute-path, heartbeat-accounting, and cost-service regression coverage for both local CLI adapters. - Document the cost-status invariant and CLI accounting behavior. ## Verification - `pnpm exec vitest run packages/adapters/codex-local/src/server/parse.test.ts packages/adapters/claude-local/src/server/parse.test.ts server/src/__tests__/codex-local-execute.test.ts server/src/__tests__/claude-local-execute.test.ts server/src/__tests__/heartbeat-cost-accounting.test.ts server/src/__tests__/costs-service.test.ts` — 6 files / 102 tests passed. - `pnpm --filter @paperclipai/shared typecheck` - `pnpm --filter @paperclipai/db typecheck` — includes migration numbering and safety checks. - `pnpm --filter @paperclipai/adapter-codex-local typecheck` - `pnpm --filter @paperclipai/adapter-claude-local typecheck` - `pnpm --filter @paperclipai/server typecheck` ## Risks - Existing cost rows default to `reported`, preserving current interpretation; only new token-bearing events with absent cost are marked `unpriced`. - This change does not invent model pricing. Budget hard stops still cannot charge an unknown amount, but operators and evals can now distinguish missing pricing from a genuinely reported zero cost. - Consumers that enumerate cost-event fields should tolerate the additive `costStatus` field. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, exact model `gpt-5.3-codex`, with repository tool use and code execution; default reasoning mode. ## 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> |
||
|
|
4a40c0cb13 |
feat(routines): gate scheduled runs on external activity (#9436)
## Thinking Path > - Paperclip is the open source app people use to manage AI-agent companies and their recurring work > - Scheduled routines provide native cron-driven execution for recurring agent tasks > - Watcher-style routines currently dispatch a model run even when the control plane has been quiet since their last useful run > - Existing pause, catch-up, and concurrency policies do not distinguish external work from a routine's own bookkeeping > - This pull request adds a generic activity gate that checks company-scoped activity provenance before scheduled dispatch > - The benefit is backward-compatible zero-token quiet skips while real human, agent, or delegated-child activity still wakes the routine ## Linked Issues or Issue Description - Refs #8534 ## What Changed - Added `activity_gate_policy` and `activity_gate_scope` routine columns with backward-compatible `always` / `company` defaults. - Added a company-bounded `evaluateActivityGate()` predicate that uses the last dispatched run as its open window, excludes the routine's own execution runs and scheduler bookkeeping, ignores pure-read actions, and supports company/project scope. - Integrated the predicate into scheduled ticks after pause/worktree eligibility checks; quiet ticks create visible skipped run-history rows with reason `no_external_activity` and gate-window diagnostics without advancing the activity window. - Kept webhook, manual, and API dispatch paths ungated; catch-up schedules evaluate the gate once per scheduler tick. - Added migration-default, provenance predicate, project-scope, quiet-window, scheduler, and webhook-bypass coverage. ## Verification - `pnpm --filter @paperclipai/db typecheck` - `pnpm --filter @paperclipai/server typecheck` - `pnpm exec vitest run server/src/__tests__/routines-service.test.ts` — 51 tests passed - Embedded Postgres `EXPLAIN` for the company-scope gate scan: ```text Limit (cost=24.56..24.58 rows=1 width=24) -> Incremental Sort (cost=24.56..24.60 rows=2 width=24) Sort Key: activity.created_at, activity.id Presorted Key: activity.created_at -> Nested Loop Anti Join (cost=0.44..24.55 rows=1 width=24) Join Filter: (own_run.id = activity.run_id) -> Index Scan using activity_log_company_created_idx on activity_log activity (cost=0.15..8.19 rows=1 width=40) Index Cond: ((company_id = '00000000-0000-0000-0000-000000000001'::uuid) AND (created_at > (now() - '01:00:00'::interval)) AND (created_at <= now())) ``` ## Risks - The migration adds two non-null text columns, but constant defaults preserve all existing routine behavior and avoid a backfill step. - Project scope resolves activity through issue/run/routine provenance; tests cover in-project and cross-project issue activity, while every top-level and correlated query remains company-bounded. - This is the scheduler/schema foundation. Public API validation and documentation for configuring the new fields are intentionally handled in the next scoped follow-up. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex using `gpt-5.4` with medium reasoning, repository/tool access, terminal code execution, and test execution. The runtime did not expose a 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 extends the existing Scheduled Routines roadmap item - [x] I have searched GitHub for duplicate or related PRs and linked the related efficiency request 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 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 (no user-facing configuration is exposed in this scoped foundation PR) - [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> |
||
|
|
36ec79c196 |
feat: add attention queue and Decisions surface (#9380)
## Thinking Path > - Paperclip is the control plane for autonomous AI companies, where operators need a reliable way to find and act on work awaiting their input. > - The attention and issue-thread interaction subsystems expose those decision points across server APIs and the board UI. > - The previous navigation and interaction presentation left these actions fragmented and did not offer a controlled rollout for the Decisions surface. > - This branch adds the attention feed, richer interaction cards, grouping, dismiss/snooze behavior, and a gated Decisions sidebar entry. > - It also keeps experimental settings and API contracts synchronized, with an idempotent migration for the new dismissal state. > - This pull request delivers the complete, tested attention/Decisions experience as one reviewable unit. ## Linked Issues or Issue Description - Adds an operator-focused attention queue and Decisions experience: grouped decision cards, semantic interaction actions, dismiss/snooze handling, resilient interaction states, and an experimental flag to control the Decisions navigation entry. ## Feature Context ### Problem or Motivation Operators currently have to hunt across approvals, interactions, failed runs, and budget alerts to find decisions that need their action. ### Proposed Solution Provide a gated Decisions attention queue that groups actionable items, supports direct resolution, and preserves operator control through dismiss and snooze actions. ### Alternatives Considered Keep separate, source-specific views only; this leaves cross-cutting operator decisions fragmented and harder to prioritize. ### Roadmap Alignment This improves the V1 control-plane operator workflow by making pending governed actions discoverable in one company-scoped surface. ## What Changed - Added server attention-feed services, routes, interaction handling, dismiss/snooze support, and an idempotent `0145` inbox-dismissal migration. - Added shared attention, inbox-dismissal, and experimental-settings contracts. - Added Decisions/attention UI, interaction-card states, sidebar badge/navigation integration, grouping, keyboard support, and Storybook coverage. - Added tests for attention behavior, thread interactions, settings normalization, dismissals, and API behavior. - Removed generated screenshots from the final PR diff and rebased the branch onto current `master`. ## Verification - `pnpm check:token-gates` — passed. - `pnpm exec vitest run packages/shared/src/issue-thread-interactions.test.ts server/src/__tests__/attention-service.test.ts server/src/__tests__/inbox-dismissals.test.ts server/src/__tests__/issue-thread-interactions-service.test.ts server/src/__tests__/issue-thread-interaction-routes.test.ts ui/src/lib/attention.test.ts ui/src/components/AttentionQueueRow.test.tsx ui/src/components/IssueThreadInteractionCard.test.tsx ui/src/pages/InstanceExperimentalSettings.test.tsx` — passed: 158 tests across 9 focused files. - GitHub Actions for `ad636f560`: build and typecheck/release-registry have passed; remaining general-server and Greptile checks are in progress. ## Risks - Moderate: this is a cross-layer attention/interaction feature with a new migration and navigation behavior. - The `enableDecisions` experimental setting defaults to off, limiting rollout impact. - Existing dismissal data is backfilled to `dismiss`; the migration is idempotent and uses guarded constraint creation. > ROADMAP.md was checked; no duplicate planned core feature was identified. Related open pull requests were searched before opening this PR. ## Model Used - OpenAI GPT-5.5 via Codex CLI, with tool use and local code execution. Context-window size unavailable in this environment. ## 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 public PR branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally; focused tests pass and the remaining unrelated AWS test failure is documented above - [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 - [ ] All Paperclip CI gates are green - [ ] 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
5c85ae64a0 |
Cases: experimental first-class case object (#9198)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The board currently uses issues for execution, but longer-lived content work needs a separate object that can survive beyond a single task thread. > - The Cases subsystem adds an experimental, company-scoped record for content artifacts and their supporting metadata. > - The backend needs durable storage, API routes, revision history, issue linkage, and company-boundary enforcement before the UI can depend on Cases. > - The UI needs an opt-in navigation surface, list/detail views, reference chips, and issue-page context so operators can inspect Cases without making them the default workflow. > - The agent-facing skills need a contract for creating and updating Cases so automated content workflows can dogfood the feature. > - This pull request ships that experimental end-to-end path behind the `enableCases` flag. > - The benefit is a first-class place to collect content work, references, attachments, revisions, and related execution threads without polluting the core issue model. ## Linked Issues or Issue Description No public GitHub issue exists for this experimental feature. Feature request fields: ### Problem Content-oriented work such as release notes, announcements, docs, and campaigns can span many execution issues, which makes the final artifact hard to find and reason about after the execution thread moves on. ### Proposed solution Add an experimental Cases object that is company-scoped, linked to issues, queryable through the API, inspectable in the board UI, and writable by agent workflows through documented conventions. ### Alternatives considered Continue encoding content artifacts directly in issues or documents only. That keeps the data model smaller, but it does not give operators a stable artifact-centric view or a clean way to link related execution history. ### Roadmap alignment Checked `ROADMAP.md`; this PR does not duplicate an existing planned core roadmap item. ## What Changed - Added the `cases` data model, migration, schema exports, and experimental `enableCases` instance setting. - Added company-scoped Cases API routes for list/detail/update, issue links, revisions, children, activity events, annotations, attachments, and idempotent agent-oriented upserts. - Scoped case and issue lookup helpers before access checks so inaccessible cross-company identifiers resolve as not found rather than leaking existence. - Fixed case PATCH timestamp handling so non-status updates cannot overwrite `completedAt` from a stale pre-transaction row snapshot. - Moved Cases list type/status/project filters into the server request before the server-side limit is applied, including multi-select filters and no-project filtering. - Added backend route coverage for creation, updates, idempotency, issue linking, attribution, company-boundary enforcement, OpenAPI registration, list filtering, timestamp patch behavior, and inaccessible lookup regressions. - Added the experimental Cases UI surface: sidebar entry, gated routes, list filters/grouping, detail overview, activity, revisions, children, attachments, and issue-page case rail. - Added case reference rendering and company-prefixed case href generation so case links resolve directly inside the active company route. - Added Paperclip skill documentation for agent workflows that create or update Cases. - Wired release-content skills to emit Cases for dogfooding. - Rebased onto current `master` and renumbered the Cases migrations to `0143`/`0144` after the latest upstream migration sequence. ## Verification - Current PR head: `ecc13be0d`. - Rebased on current `master` (`606aa4f266`) and pushed to the existing PR branch. - `git diff --check origin/master...HEAD` — passed before the first update push; subsequent committed diffs were also checked with `git diff --check` before commit. - Guardrails checked: no `pnpm-lock.yaml` changes, no `.github/workflows` changes, and changed-file count is below the Greptile 100-file limit. - `pnpm --filter @paperclipai/server exec vitest run src/__tests__/cases-routes.test.ts src/__tests__/instance-settings-service.test.ts src/__tests__/openapi-routes.test.ts` — passed, 3 files / 26 tests before review-fix commits. - `pnpm --filter @paperclipai/server exec vitest run src/__tests__/cases-routes.test.ts` — passed after each server-side Greptile fix, latest 1 file / 15 tests. - `pnpm --filter @paperclipai/server typecheck` — passed after the timestamp and lookup fixes. - `pnpm --filter @paperclipai/ui exec vitest run src/pages/Cases.test.tsx src/pages/CaseDetail.test.tsx src/pages/CompanySkills.test.tsx src/App.cases-routing.test.tsx` — passed, 4 files / 30 tests before review-fix commits. - `pnpm --filter @paperclipai/ui exec vitest run src/pages/Cases.test.tsx` — passed after the list-filter fix, 1 file / 12 tests. - `pnpm --filter @paperclipai/ui typecheck` — passed after the list-filter fix. - `pnpm check:token-gates` — passed after UI changes. - Remote PR checks on head `ecc13be0d` are green: Paperclip CI, build, typecheck, test matrix, e2e, Canary Dry Run, policy, commit review, Superagent Security Scan, Socket, Snyk, and Greptile passed; Storybook visual regression is skipped and security-review is neutral. - Greptile Review: 5/5 confidence, zero unresolved Greptile threads. ## Risks - Medium feature risk because this introduces a new experimental domain object across database, server, shared contracts, skills, and UI. - The feature is gated behind `enableCases`, which limits default operator exposure while the model is exercised. - Case links now prefer company-prefixed hrefs; the unprefixed redirect remains for externally entered URLs. - Cases list filtering now sends multi-select filters to the server before limiting; the UI still applies the same local filters as a second pass for ancestor/context rows. - Migrations were renumbered on top of current master; the SQL uses guarded `IF NOT EXISTS` / `ADD COLUMN IF NOT EXISTS` patterns where relevant for safer replay. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 Codex in the Paperclip local coding environment was used for this PR curation, rebase verification, review-fix implementation, push, and PR description update. The runtime exposes tool use and shell execution; context-window size is not exposed by this Paperclip adapter. Several implementation commits also include AI co-author trailers recorded in git history. ## 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 searched the GitHub PR list for similar PRs and confirmed this is not a duplicate - [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) - [ ] 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
606aa4f266 |
feat(search): filters, sorting, operators & command-palette parity (#9327)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Company search is the primary way operators find issues, comments, documents, artifacts, agents, and projects across a busy company > - Search previously supported only a bare text query: no way to narrow by status/assignee/project/label/date, no sort control, no typed operators, and weak relevance/snippets meant hunting through noise > - As companies accumulate tens of thousands of items, unfiltered single-sort search stops scaling for day-to-day operator workflows > - This pull request adds a full filtering model (filter bar, chips, mobile sheet, URL state), sort modes, typed query operators (`status:`, `assignee:`, `type:`, …) with command-palette parity, relevance/snippet/deep-link improvements, zero-results recovery, and the supporting shared validators, backend service work, and DB indexes > - The benefit is that operators can go from a vague query to the exact item in a couple of keystrokes, on desktop and mobile, with shareable filtered-search URLs ## Linked Issues or Issue Description No existing public GitHub issue; describing the underlying feature request inline (per feature_request template): - **Problem:** Company search accepted only a plain text query. Users could not filter results by status, assignee, project, label, or recency; could not change result ordering; and got no guidance when filters emptied the result set. - **Desired solution:** Structured search filters (UI controls + typed query operators + URL parameters), selectable sort modes, better relevance and snippets with exact deep links, and parity between the search page and the command palette. - **Alternatives considered:** Client-side filtering of unfiltered results (does not scale past the fetch limit); a separate "advanced search" page (splits the surface and duplicates state handling). Related (not duplicate) PRs found while searching: #4848 (issue search query planning), #8235 (search rate limiting). ## What Changed - **Shared contract:** new search filter/sort/count/zero-results types and validators in `packages/shared` (`validators/search.ts`, types index). - **Backend:** `server/src/services/company-search.ts` supports issue filters, sort modes, per-filter option counts, snippets, artifact visibility, and zero-results loosen suggestions; single-statement match replaces per-scope scans and predicates are trigram-index compatible (~3.7s → ~350ms on a live 14.8k-hit corpus). - **DB:** migration `0142_company_search_sort_indexes.sql` adds the supporting indexes. - **Search page (`ui/src/pages/Search.tsx`):** filter bar, removable chips, mobile filter sheet with result-count preview, sort menu, URL round-tripping, zero-results recovery UI. - **Query operators (`ui/src/lib/search-query-parser.ts`):** typed operators parsed into filters, operator autocomplete, filter pills. - **Command palette:** operator-aware parsing and full-search handoff. - **Stale-operator fix (latest commit):** typed operator filters are no longer folded into persistent URL-filter state, so deleting a token (e.g. removing `status:blocked` from the input) actually removes the filter from subsequent requests; filter-control edits materialize control state and strip typed tokens so a removed chip cannot resurrect from the input. ## Verification - `cd ui && npx vitest run src/pages/Search.test.tsx` — 19 tests including two new red→green regressions for the stale-operator paths (both fail on the previous commit, pass now). - `cd ui && npx vitest run src/components/CommandPalette.test.tsx` and `cd server && npx vitest run src/services/company-search-service.test.ts` — operator parity and backend filter/sort/count coverage. - `cd ui && npx tsc --noEmit` — clean. - Manual: open `/search`, type `auth status:blocked`, confirm the status filter applies; delete `status:blocked`, confirm results are unfiltered again; drive the same filters from the filter bar/chips/mobile sheet and confirm the URL round-trips (reload/back/forward preserves state). - Full end-to-end QA pass (9/9 acceptance checks) against the wireframes on desktop (1280px) and mobile (390px) with a live API and browser automation. ## Risks - Additive migration (indexes only, no data rewrites) — safe to roll forward; index creation cost is paid once at migrate time. - Search request shape gains optional parameters only; old clients keep working. - Behavioral shift: filter-control edits now strip typed operator tokens from the query text (their values persist as filter state) — deliberate, so removed filters stay removed. - Ranking changes alter result ordering for existing queries; covered by service tests and the QA pass. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - Claude Fable 5 (`claude-fable-5`, Anthropic, extended thinking + tool use) — stale-operator-filter fix, regression tests, PR preparation. - GPT-5 Codex (`codex_local` adapter) and Claude Opus 4.6 (`claude-opus-4-6`) — earlier implementation phases (backend contract, filter UI, operators, ranking) under agent orchestration. ## 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) - [ ] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details — pre-existing branch name retained to avoid closing/reopening the PR - [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 (no user-facing docs affected) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green (pending re-run on latest commit) - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (pending re-review of the stale-filter fix) - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
176645187c |
Fix request storm polling and issue-list coalescing (#9190)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The board UI keeps issue, agent, activity, and run state fresh through polling across several pages and sidebar surfaces > - When multiple components or browser tabs poll the same company data at the same time, the API can receive bursts of duplicate issue-list requests > - Those duplicate requests increase database and server load without returning meaningfully different data > - This pull request adds server-side compression/coalescing plus client-side visibility-aware and cross-tab shared polling > - The benefit is lower request volume during normal board usage while preserving fresh UI data for active users ## Linked Issues or Issue Description No exact public GitHub issue was found for this request. Problem: - The board can issue redundant polling requests for the same issue-list data from multiple UI surfaces and tabs. - In busy operator sessions, those bursts can trigger request-storm behavior and unnecessary issue-list load. - Expected behavior is to reuse identical in-flight work server-side and reduce hidden-tab or duplicate-tab polling client-side while preserving normal refresh behavior. Related public context found during duplicate search: - #8206 covers a different board UI 404-storm scope. - #5165 covers separate issue-list behavior around page-size truncation. ## What Changed - Added API compression middleware foundation and a company/created-at index for heartbeat run access. - Added server-side issue-list request storm detection and identical in-flight request coalescing. - Added UI fetch metadata, visibility-aware polling, and request deduplication for issue/activity/client calls. - Added cross-tab shared polling primitives and wired them into the sidebar, inbox, dashboard, issue, project, routine, and agent surfaces. - Resolved the latest `master` migration collision by keeping upstream `0140_built_in_managed_resources.sql` and renumbering this branch's heartbeat-run index migration to `0141_heartbeat_runs_company_created_at_index.sql`; the SQL uses `CREATE INDEX IF NOT EXISTS` for idempotency. - Stabilized server heartbeat cleanup tests exposed by the PR check matrix. - Fixed the Greptile compression follow-up by weakening strong ETags on encoded JSON responses and bypassing compression for streamed/download responses. ## Verification - `pnpm exec vitest run ui/src/components/IssuesList.test.tsx ui/src/pages/Inbox.test.tsx` — passed after resolving the latest `master` conflict in `IssuesList.tsx` and updating the 200-result cap expectations. - `pnpm check:token-gates` — passed after the UI conflict resolution. - `jq -e '.entries | length as $n | (map(.idx) | unique | length == $n) and (map(.tag) | unique | length == $n)' packages/db/src/migrations/meta/_journal.json` — passed after renumbering the migration to `0141`. - `pnpm exec vitest run server/src/__tests__/api-compression.test.ts` - passed after the compression follow-up. - `pnpm exec vitest run server/src/__tests__/issue-list-assignee-filter-routes.test.ts` - passed after the compression follow-up. - `pnpm --filter @paperclipai/server typecheck` - passed after the compression follow-up. - Greptile Review for head `8dbddac41ec273fda404100b4981ddb912fad57b` - passed after the latest conflict/migration fix; all Greptile review threads are resolved. - `pnpm exec vitest run server/src/__tests__/api-compression.test.ts server/src/__tests__/issue-list-assignee-filter-routes.test.ts ui/src/api/client.test.ts ui/src/api/issues.test.ts ui/src/lib/polling.test.ts ui/src/lib/cross-tab-poll.test.ts ui/src/pages/Inbox.test.tsx ui/src/components/SidebarProjects.test.tsx ui/src/components/SidebarAccountMenu.test.tsx ui/src/lib/issueDetailCache.test.ts` — passed. - `pnpm exec vitest run ui/src/api/client.test.ts` — passed. - `pnpm exec vitest run ui/src/pages/Inbox.test.tsx ui/src/components/SidebarProjects.test.tsx ui/src/components/SidebarAccountMenu.test.tsx ui/src/lib/issueDetailCache.test.ts` — passed. - `pnpm exec vitest run server/src/__tests__/heartbeat-worktree-suppression.test.ts` — passed. - `pnpm exec vitest run server/src/__tests__/low-trust-red-team-routes.test.ts` — passed. - `pnpm exec vitest run server/src/__tests__/heartbeat-workspace-finalize-branch.test.ts` — passed. - `pnpm --filter @paperclipai/ui typecheck` — passed. - `pnpm --filter @paperclipai/server typecheck` — passed. - GitHub PR checks for head `8dbddac41ec273fda404100b4981ddb912fad57b`: all GitHub Actions/status checks passed; Greptile, Superagent, Socket, Snyk, build, typecheck/release registry, general tests, serialized server suites, e2e, canary dry run, policy, and commitperclip review are green; Storybook visual regression and security-review were skipped/neutral by policy. - Confirmed this branch does not include `pnpm-lock.yaml` or `.github/workflows` changes. ## Risks - Medium risk: issue-list coalescing changes request timing and cache semantics for a hot API path. - Medium risk: cross-tab polling uses browser coordination primitives, so older or unusual browser environments need fallback behavior to stay correct. - Low migration risk: the new index migration is ordered after current `master` and uses `CREATE INDEX IF NOT EXISTS`. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex coding agent, GPT-5-based model, tool-enabled with shell/git execution. Exact hosted deployment identifier and context-window size were not surfaced in the agent runtime. ## 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> |
||
|
|
8b6a06ee25 |
[codex] Add built-in agents and Reflection Coach bundle (#9206)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Operators need first-party agent capabilities for repeatable company work, not just manually created one-off agents. > - Built-in agents need to behave like normal company-scoped agents while preserving approval gates, permissions, budgets, and audit trails. > - Reflection and coaching work also needs bundled instructions, skill content, and a routine so the feature can be installed and reset predictably. > - The API, database, UI, portability, and tests all need to agree on the built-in lifecycle from not provisioned through setup, approval, ready, paused, and reset. > - This pull request adds built-in agent provisioning and the Reflection Coach bundle end-to-end. > - The benefit is a safer first-party path for Paperclip-managed agents without bypassing the same governance model used for operator-created agents. ## Linked Issues or Issue Description No public GitHub issue was found for this exact built-in agent and Reflection Coach bundle work. Problem/motivation: - Paperclip did not have a first-party built-in agent lifecycle for product-owned agents. - Bundled agent resources such as default instructions, skills, and routines needed managed ownership and reset semantics. - Approval-gated companies needed built-in setup to preserve requested adapter, budget, manager, and permission state through board approval. - The board UI needed clear built-in badges, setup affordances, readiness state, and bundle status without exposing secrets. Proposed solution: - Add a company-scoped built-in agent registry, provisioning/reset/reconcile/status APIs, and Reflection Coach bundled resources. - Track bundled managed resources in the database with idempotent migration behavior. - Reuse existing agent approval, authorization, budget, and activity-log paths instead of creating a bypass. - Add UI setup, badges, gates, bundle panels, and route coverage for built-in agents. Duplicate search: - Searched GitHub PRs for `built-in agents Reflection Coach repo:paperclipai/paperclip`; only this PR was returned. - Searched GitHub issues for the same query; no public issues were returned. ## What Changed - Added built-in agent definitions, lifecycle state derivation, provisioning, reset, reconcile, status, and routine-control routes. - Added the `built_in_managed_resources` migration and schema exports for bundled instructions, skill, and routine ownership. - Added the Reflection Coach built-in bundle with default instructions, skill catalog content, routine template, default permissions, and managed-resource drift handling. - Added approval-aware provisioning behavior that preserves requested adapter config, budgets, manager assignment, and built-in permissions through hire approval. - Added authorization and mutation gates for built-in agent and skill changes, including consented Reflection Coach change paths. - Added UI surfaces for built-in agent setup, roster/detail badges, readiness gates, bundle status, routine controls, and route filtering. - Added company import/export and validator coverage for built-in managed resources and low-trust/red-team presets. - Addressed Greptile follow-ups for pending approval reconciliation, consent-gate error propagation, config-read authorization fallback, approval-path manager preservation, and non-model adapter provisioning. ## Verification Local verification: - `git diff --check public/master..HEAD` passed. - `pnpm check:token-gates` passed with all gates clean. - `pnpm exec vitest run ui/src/components/ConfigureBuiltInAgentModal.test.tsx` passed: 1 file, 4 tests. - `pnpm exec vitest run ui/src/components/EntityRow.test.tsx ui/src/pages/Agents.test.tsx ui/src/components/BuiltInAgentGate.test.tsx ui/src/components/ConfigureBuiltInAgentModal.test.tsx ui/src/components/BuiltInBundlePanel.test.tsx ui/src/pages/InstanceExperimentalSettings.test.tsx ui/src/pages/Routines.test.tsx` passed: 7 files, 64 tests. - `pnpm --filter @paperclipai/server exec vitest run src/__tests__/built-in-agents.test.ts src/__tests__/authorization-service.test.ts src/__tests__/company-skills-routes.test.ts` passed: 3 files, 91 tests. - `pnpm --filter @paperclipai/db check:migrations` passed. - `pnpm -r typecheck` passed after the rebase; `pnpm --filter ui typecheck` passed after the final UI review fix. Remote verification on latest head `1c61f693a4ec881d739022b0e75a8ca8bf8c2cd8`: - Merge state: `CLEAN`. - Greptile: `5/5`, zero unresolved Greptile threads. - PR check rollup: all checks successful, neutral, or skipped as expected. - Passing gates include Build, Typecheck + Release Registry, all server shards, all workspace shards, all serialized server suites, e2e, Canary Dry Run, policy, review, verify, Socket, Superagent, and Snyk. ## Risks - This adds a new managed-resource table and migration; the migration uses idempotent create/add/index guards and passed migration safety checks. - Built-in agent provisioning touches approval and authorization paths; tests cover pending approval preservation, stale retry rejection, consent gates, and config-read fallback behavior. - Reflection Coach creates managed instructions, skill, and routine resources; drift/reset behavior is covered by service tests and redacted API responses. - Non-model adapter setup now provisions a `needs_setup` built-in row before command/endpoint fields are complete; this matches the server lifecycle and is covered by the setup modal regression test. ## Model Used OpenAI Codex coding agent based on GPT-5. Exact hosted model ID, context-window size, and reasoning-mode labels are not exposed in this runtime; tool use, shell execution, GitHub CLI/API access, and local code editing were enabled. ## 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> |
||
|
|
b13eb5b2b5 |
Skill Studio: three-pane skill IDE with sandboxed test runs (#9241)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Skills Manager gives operators a reusable skill layer, but iteration still required manual edits, ad hoc prompts, and indirect run inspection. > - Skill authors need a focused workflow for editing skill files, saving representative test inputs, and running those inputs through an agent without exposing harness tasks as normal company work. > - The backend therefore needs durable test inputs, reusable run templates, hidden harness issues, scoped run execution, retention metadata, and read-containment rules around hidden work. > - The frontend needs a three-pane Studio that keeps skill files, saved inputs/templates, and run output/history visible together while preserving the existing design system and token rules. > - This pull request ships that Skill Studio surface end to end: database migrations, shared contracts, server APIs/services, hidden harness execution behavior, UI routes/components, and focused tests. > - The benefit is faster and safer skill iteration, with inspectable outputs and fewer ways for internal harness work to leak into normal task lists, costs, or adjacent read APIs. ## Linked Issues or Issue Description No public GitHub issue exists for this feature. Feature request summary: - Problem: Skill authors need to edit and test company skills in one place instead of switching between the skill detail page, task creation, run output, and manual prompt history. - Proposed solution: Add a Skill Studio workbench with saved inputs, reusable templates, hidden sandboxed test runs, live run status, output inspection, run history, rerun/delete controls, and frontmatter-aware editing. - Expected users: Paperclip operators and agent-company maintainers who create, fork, import, and tune skills. - Related public PRs: Supersedes #9205, which was replaced so the public PR branch name follows contributor policy. - Duplicate search: searched public GitHub issues and PRs for "Skill Studio"; no other active public issue or PR directly covers this feature. ## What Changed - Added database migrations for Skill Studio test inputs, test runs, test run retention, and reusable run templates. - Added shared Skill Studio types, validators, route helpers, frontmatter utilities, and status handling. - Added server services and routes for saved inputs, test runs, templates, reruns, terminal-run deletion, hidden harness issue execution, and run-detail hydration. - Strengthened hidden-issue read containment across issue-adjacent routes and cost rollups used by skill test harness work. - Added the Skill Studio UI with skill file editing, frontmatter editing, saved inputs, templates, run creation/cancel/rerun/delete flows, output rendering, history, route support, and responsive pane behavior. - Added focused backend, shared, and UI tests for the new APIs, routing logic, editor/run behavior, hidden-issue containment, and migration safety. - Rebased onto current `master`, removed the generated lockfile diff from the PR, and verified no workflow files are changed. ## Verification - [x] `pnpm --filter @paperclipai/db check:migrations` - [x] `pnpm check:token-gates` - [x] `pnpm exec vitest run server/src/__tests__/company-skills-service.test.ts server/src/__tests__/company-skills-routes.test.ts server/src/__tests__/company-skill-test-runs-service.test.ts ui/src/lib/skill-studio.test.ts ui/src/pages/SkillStudio.test.tsx` — 5 files, 132 tests passed - [x] Greptile review on the latest PR head - [x] GitHub PR checks on the latest PR head ## Risks - Medium risk because this is a broad feature touching database schema, server orchestration, issue visibility, and a large UI surface. - Hidden harness issue containment is security-sensitive; this PR includes regression coverage for adjacent read paths and cost rollups. - The new migrations are additive and use idempotent guards where applicable, but deployed databases that previously tested draft migration numbers should still be checked carefully. - The UI depends on a new resizable panels package in `ui/package.json`; the lockfile is intentionally left to repository automation. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5 coding agent with shell, git, and GitHub CLI tool use. Earlier feature commits include assistance from other Paperclip coding agents; this PR preparation, rebase, cleanup commit, and PR body were completed by OpenAI Codex in a Paperclip worktree. ## 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
eedc7ddef2 |
Make ACP the default engine for local adapters (#9238)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Adapter packages are the bridge between the control plane and local agent harnesses such as Claude Code, Codex, and Gemini CLI. > - ACP support was concentrated in a separate `acpx_local` adapter, which made ACP feel like a separate agent choice instead of an execution capability of the harness adapters. > - Claude, Codex, and Gemini now have ACP-capable harnesses, so the native adapter should own ACP selection, fallback, config, transcript parsing, and environment diagnostics. > - The standalone ACPX adapter still needs a compatibility path for existing rows, but it should not be offered as an active adapter for new agents. > - This pull request moves the shared ACP runtime into `@paperclipai/acpx-engine`, wires Claude/Codex/Gemini local adapters to prefer ACP when prerequisites are available, and retires `acpx_local` to a tombstone. > - The benefit is one adapter per harness, richer ACP transcripts by default where possible, and a migration path for existing Claude/Codex ACPX agents. ## Linked Issues or Issue Description Closes #5932 — the broken default `acpx_local` Claude path is replaced by native `claude_local` ACP support, existing Claude/Codex ACPX rows migrate to native adapters, and new agents no longer choose the standalone ACPX adapter. Refs #4893 — original merged ACPX local adapter runtime that this PR replaces with native per-harness ACP engines. Refs #6590 — prior ACPX-Claude seamlessness work folded into the new native Claude ACP path. Refs #197 — related open generic ACP/Kiro adapter work; this PR does not close it because Kiro/custom generic ACP remains a separate adapter decision. Refs #7018 — related Kimi-specific `acpx_local` shell failure; this PR retires the built-in standalone adapter but does not add a native Kimi adapter. Refs #8864 — related ACPX prompt/API guidance PR; this PR moves runtime guidance into the shared/native ACP engine path instead of the old standalone adapter. Refs #8881 — related `acpx_local` POSIX shell failure from the old `acpx` pin; this PR updates ACP dependencies but does not claim custom/OMP ACP support as a first-class native adapter. Refs #8964 — related open `acpx_local` stderr cleanup PR; this PR makes the old runtime path obsolete for new agents but keeps it as a non-closing reference. Problem description: - The standalone `acpx_local` adapter duplicates Claude/Codex agent choices that already have first-class local adapters. - ACP should be an execution engine capability of each harness adapter when the underlying harness supports ACP. - Existing `acpx_local` agents should either migrate to native harness adapters or fail with an explicit retirement message instead of silently falling back to the process adapter. ## What Changed - Added `@paperclipai/acpx-engine` as the shared ACP execution, session-codec, CLI formatter, and UI parser package. - Wired `claude_local`, `codex_local`, and `gemini_local` to auto-select ACP by default when prerequisites pass, with `engine=cli` opt-out and `engine=acp` strict mode. - Added ACP config schema/UI fields, environment checks, session-codec preservation, transcript parsing, and adapter capability metadata for the native adapters. - Retired `acpx_local` to a server tombstone, removed its UI/package/runtime image surface, and added a migration for existing Claude/Codex ACPX agents. - Updated package manifests, lockfile, release tooling, docs, Kubernetes sandbox defaults, and tests. ## Verification - `corepack pnpm --filter @paperclipai/acpx-engine typecheck` - `corepack pnpm --filter @paperclipai/adapter-claude-local typecheck` - `corepack pnpm --filter @paperclipai/adapter-codex-local typecheck` - `corepack pnpm --filter @paperclipai/adapter-gemini-local typecheck` - `corepack pnpm --filter @paperclipai/acpx-engine exec vitest run` - `corepack pnpm --filter @paperclipai/adapter-claude-local exec vitest run src/server/acp.test.ts src/server/execute.acp-fallback.test.ts src/ui/build-config.test.ts` - `corepack pnpm --filter @paperclipai/adapter-codex-local exec vitest run src/server/acp.test.ts src/ui/build-config.test.ts` - `corepack pnpm --filter @paperclipai/adapter-gemini-local exec vitest run src/server/acp.test.ts src/ui/build-config.test.ts src/ui/parse-stdout.test.ts` - `corepack pnpm --filter @paperclipai/plugin-sdk ensure-build-deps && corepack pnpm --filter @paperclipai/server exec tsc --noEmit` - `corepack pnpm --filter @paperclipai/server exec vitest run src/__tests__/adapter-routes.test.ts src/__tests__/adapter-session-codecs.test.ts src/__tests__/adapter-models.test.ts` - `corepack pnpm --filter @paperclipai/ui typecheck` - `corepack pnpm --filter @paperclipai/ui exec vitest run src/adapters/metadata.test.ts src/adapters/adapter-display-registry.test.ts src/components/AgentConfigForm.test.ts src/components/AgentConfigForm.render.test.tsx src/components/transcript/RunTranscriptView.test.tsx` - `node --test scripts/bootstrap-npm-package.test.mjs scripts/release-package-map.test.mjs scripts/verify-release-registry-state.test.mjs` Note: the server typecheck script calls `pnpm` internally; this dev shell exposes pnpm through Corepack only, so I ran the two script steps manually with `corepack pnpm`. ## Risks - Migration changes existing `acpx_local` Claude/Codex agents to native adapter types and clears old ACPX task sessions/runtime state. - Custom ACP commands remain on the retired tombstone and will need a separate future adapter/plugin path. - ACP auto-selection depends on local Node and ACP server command prerequisites; remote and unsupported environments fall back to CLI unless `engine=acp` is explicit. - `@paperclipai/acpx-engine` is a new public package and needs npm trusted-publishing bootstrap before release automation can publish it. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 via Codex coding agent. Exact hosted model build and context-window size are not exposed in this runtime. Tool use included shell execution, repository editing, GitHub CLI operations, and local test/typecheck execution. ## 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> |
||
|
|
0f08c2b526 |
fix(db): repair responsible user migration timestamps (#9146)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The database migration layer keeps local and deployed instances moving forward safely as schema/data contracts evolve. > - The responsible-user backfill migration could make historical issues look newly updated by bumping user-visible `updated_at` columns during a backfill. > - That timestamp churn can invalidate inbox/archive state and make old work appear fresh even though no user-facing activity happened. > - This pull request moves the responsible-user invariant migration later in the current migration sequence, keeps it from touching user-visible timestamps, and adds a repair sweep for databases that already saw the timestamp bump. > - The benefit is safer migration replay and regression coverage for future backfills that might otherwise mutate visible timestamps. ## Linked Issues or Issue Description No public GitHub issue exists. Inline bug report: **Pre-submission checklist** - [x] I have searched existing open and closed issues and this is not a duplicate. - [x] I am on the latest released version of Paperclip (or can reproduce on `master`). - [x] I have confirmed the error originates in Paperclip itself — not in my agent adapter, API provider, or local configuration. **What happened?** A responsible-user migration backfill could update user-visible `updated_at` columns while filling missing responsible-user data. That makes historical issues/runs/routines appear newer even when no user-facing activity happened. **Expected behavior** Responsible-user backfills should populate ownership metadata without mutating user-visible recency fields, and databases already affected by a timestamp sweep should be repairable. **Steps to reproduce** 1. Start from current `master` with the responsible-user migration sequence. 2. Apply migrations to a database containing historical issues, runs, routines, and companies with older activity timestamps. 3. Replay the responsible-user invariant migration and inspect user-visible `updated_at` values. **Paperclip version or commit** `master` at the PR base. **Deployment mode** Local dev (`pnpm dev`) and deployed instances using the same migrations. **Installation method** Built from source (`pnpm dev` / `pnpm build`). **Agent adapter(s) involved** - [x] Not adapter-specific (core bug) **Database mode** External Postgres and embedded development Postgres migration paths. **Access context** Board and agent-visible issue recency can both be affected. **Relevant logs or output** Covered by the added embedded-Postgres regression tests. **Relevant config (if applicable)** Not applicable. **Additional context** This PR adapts an extracted local migration fix onto the current master migration sequence, where `0133` is already occupied. **Privacy checklist** - [x] I have reviewed all pasted output for PII (usernames, file paths, API keys, tokens, company names) and redacted where necessary. ## What Changed - Renumbered the responsible-user invariant migration onto the current master migration sequence. - Added a repair migration that detects broad timestamp sweeps and restores safer `updated_at` values for issues, heartbeat runs, routines, routine runs, and companies. - Added focused embedded-Postgres regression coverage for the relocated migration, repair migration, and updated-at backfill allowlist. ## Verification - `pnpm --filter @paperclipai/db run check:migrations` - `/srv/paperclip/home/paperclipai/paperclip/node_modules/.bin/vitest run packages/db/src/client.test.ts -t "migration 0134|migration 0135|unallowlisted migration backfills"` ## Risks Migration behavior is the main risk. The PR intentionally changes the active migration sequence by removing the old responsible-user invariant slot and replaying that work later with a repair migration. Reviewers should confirm this matches the intended release/migration policy for installations that may already have applied the earlier migration. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5.5 coding agent with repository tool use and local shell execution. Context window was not surfaced by the runtime. ## 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 - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [ ] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
22001bbd2f |
feat(db): add migration safety lint
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The `packages/db` module owns all database migrations via a sequential numbering system already validated at build time > - A recent migration introduced an O(n²) batch backfill over a large, unindexed table — it caused the server's `listen` to block for ~5 minutes on databases with millions of rows > - Nothing in the current CI pipeline catches large-table migration risk patterns (DO-loop mutations, batched LIMIT mutations without support indexes, full-table mutations, non-concurrent index creation) before they land > - This PR wires a new static migration-safety checker (`check-migration-safety.ts`) into the existing `check:migrations` gate in `packages/db/package.json`, so risky patterns fail CI before reaching production > - The checker baselines all historical findings already present in the codebase, so the gate fails only on *new* unbaselined risky patterns > - The benefit is that the specific O(n²) backfill shape (and related patterns) will be caught at author time rather than at incident time ## Linked Issues or Issue Description **Feature — static migration safety lint** **Problem or motivation** Migrations against large tables (millions of rows) have caused production startup blocks. The root pattern is a batched `LIMIT`-based backfill iterating via an unindexed column, making each batch a sequential scan — O(n²) overall. No CI gate exists to flag this class of problem before merge. **Proposed solution** A static SQL-level checker that scans new migration files for known dangerous patterns against known-large tables, producing structured findings that are either baselined (suppressed) or fail the build. Patterns detected: `DO $$ loop` mutations on large tables without a same-migration support index, batched `LIMIT` mutations on large tables missing a same-migration support index, unbounded full-table mutations (no `WHERE` clause), and `CREATE INDEX` without `CONCURRENTLY` on large tables. **Alternatives considered** Runtime instrumentation (only catches issues in production), advisory locking in migrations (doesn't prevent the pattern), per-migration code review (doesn't scale consistently). **Roadmap alignment** Defensive infrastructure / operational reliability — keeps migrations from blocking production startups. Not a user-facing feature. ## What Changed - **`packages/db/package.json`** — extended `check:migrations` script to run `check-migration-safety.ts` after the existing numbering check - **`packages/db/src/check-migration-safety.ts`** — new static checker: SQL pattern matching, rule detection for four dangerous patterns, baseline diffing, and structured exit with findings summary - **`packages/db/src/migration-safety-baseline.ts`** — baseline of all existing historical findings (suppressed from failing the gate); new migrations matching these patterns without a baseline entry will fail - **`packages/db/src/table-size-estimates.ts`** — rough table size estimates from the local dev database; drives `isKnownLargeTable()` used by the safety rules - **`packages/db/src/check-migration-safety.test.ts`** — Vitest coverage for the O(n²) backfill failure mode, suppression via baseline, and each rule type ## Verification ```bash # Run the migration safety checker directly cd packages/db tsx src/check-migration-safety.ts # Run tests cd packages/db npx vitest run src/check-migration-safety.test.ts # Run the full migration check gate (numbering + safety) cd packages/db pnpm run check:migrations ``` - Tests cover the core O(n²) backfill pattern (the motivating incident), baseline suppression, and all four rule types - `check:migrations` now exits non-zero for any new unbaselined large-table migration risk pattern ## Risks - **False positives:** Table-size estimates are from a local dev database snapshot — a table small in dev but large in production would be missed. Best-effort heuristic. - **Baseline drift:** If a baselined finding's SQL changes significantly, the baseline ID (content-hash-based) will no longer match and the finding will re-surface. Intentional but may surprise authors doing incremental fixes. - **SQL parsing limitations:** Regex-based pattern matching rather than a full AST parser — complex SQL may not be detected. Acceptable for an initial gate. - **Low risk to existing behavior:** The gate only fails on *new* findings not present in the baseline. All existing migrations are baselined. ## Model Used - **Provider:** Anthropic - **Model ID:** `claude-sonnet-4-6` - **Context window:** 200K - **Tool use:** yes (file reading, bash, git operations) - **Reasoning mode:** standard (no extended thinking) ## 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 - [ ] 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> |
||
|
|
d2e3f7dce5 |
fix(db): correct 0130 responsible-user backfill in place (inbox resurface) (#9111)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Users triage agent work through the issue inbox, which suppresses archived issues by comparing issue `updated_at` against the archive timestamp > - Migration `0130_run_responsible_user_invariant` backfilled responsible-user columns but also set `updated_at = now()` on every row it touched (companies, issues, routines, routine_runs, heartbeat_runs) > - That blanket timestamp bump made every archived issue look newly updated, resurfacing thousands of archived issues into every user's inbox > - This pull request corrects the 0130 backfill in place so it only fills `NULL` responsible-user columns and never touches timestamps, and adds tests that prevent this class of bug from being reintroduced > - The benefit is that inbox archive suppression stays intact across migrations, and no future migration backfill can silently bump `updated_at` on user-visible tables ## Linked Issues or Issue Description **Bug description (no public issue exists):** - **What happened:** after upgrading a dev instance across migration 0130, every previously archived inbox item resurfaced as unread/new for all users. - **Expected:** data backfills must not alter row modification timestamps; archived issues stay archived unless genuinely updated. - **Root cause:** the 0130 backfill's `UPDATE` statements set `updated_at = now()` alongside the responsible-user columns. ## What Changed - `packages/db/src/migrations/0130_run_responsible_user_invariant.sql`: removed all `updated_at = now()` assignments from the backfill UPDATEs; the migration now only fills `NULL` responsible-user columns. The file is corrected **in place** (no new migration number, journal untouched) because 0130 has never shipped in a published release. - `packages/db/src/client.test.ts`: added a guard test that scans every migration and rejects backfills that bump `updated_at` on user-visible tables (with an explicit allowlist for the pre-existing 0131 repair migration). - `packages/db/src/client.test.ts`: added a replay test that simulates an already-migrated database picking up the corrected file (deletes the 0130 ledger hash, re-applies mid-journal) and asserts issue `updated_at` and inbox-archive suppression ordering are untouched. ### Why an in-place edit is safe - 0130 only exists on master/canary builds; the latest published release (v2026.626.0) predates it. - The migration ledger is content-hash based: databases that already applied the old 0130 keep an orphaned hash row (harmless) and see the corrected file as pending, so they replay the corrected backfill — which is idempotent (fills `NULL`s only, no timestamp writes). - Fresh databases simply run the corrected 0130 in journal order. ## Verification - `pnpm --filter @paperclipai/db run check:migrations` — clean - `cd packages/db && npx vitest run src/client.test.ts` — 11/11 passing against embedded Postgres, including the new guard and mid-journal replay tests ## Risks - Migration safety: the corrected backfill is idempotent and only writes `NULL` columns; replay on already-migrated databases is exercised directly by the new test. No schema changes. - Databases that already ran the old 0130 keep the bumped timestamps from that run; repairing historical damage is intentionally out of scope here (no released build ever contained the bug). ## Model Used - Claude Opus 4.7 (`claude-opus-4-7`, extended thinking, tool use) via Claude Code / Paperclip agent runtime ## 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 (backup health alert work split into #9113; no other related open PRs) - [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 (none needed for a migration content fix) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] 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> |
||
|
|
903886bc79 |
[codex] Add starred resource sidebar controls (#9085)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The board UI is the main daily navigation surface for agents, projects, and their related resources. > - Operators need a lightweight way to keep frequently used agents and projects close without changing company-wide ordering or ownership. > - Resource memberships already model per-user relationships to projects and agents, so they are the right place to store user-specific starred state. > - This pull request extends that membership contract with a starred timestamp and exposes star controls in list/detail views. > - The sidebar then uses those starred memberships to show compact, user-specific shortcuts. > - The benefit is faster navigation without introducing a separate favorites system or leaking preferences across users. ## Linked Issues or Issue Description No public GitHub issue exists. Feature request: ## Problem or motivation Users cannot pin frequently used agents or projects into the main sidebar. Returning to important resources requires scanning full project/agent lists or navigating through detail pages, which adds friction to repeated daily workflows. ## Proposed solution Store a per-user `starred_at` timestamp on agent and project memberships, expose API actions to set or clear that state, add star toggle controls to list/detail pages, and render starred projects and agents as compact sidebar shortcuts. ## Alternatives considered A separate favorites table would work, but it would duplicate membership scoping and require another resource relationship model. Keeping starred state on memberships preserves existing company/user boundaries and avoids a second source of truth. ## Roadmap alignment Checked `ROADMAP.md`; no overlapping planned core work for starred resource/sidebar navigation was found. ## Additional context The affected subsystems are `packages/db`, `packages/shared`, `server/`, and `ui/`. The migration is idempotent with `IF NOT EXISTS` guards so environments that saw an earlier local migration name can still apply the final ordered migration safely. ## What Changed - Added idempotent migration `0133_resource_membership_stars` for `starred_at` columns and lookup indexes on agent/project memberships. - Extended shared resource membership types and validators with starred metadata and actions. - Updated server resource membership services/routes to read and mutate starred resource state. - Added reusable star toggle UI and resource membership hook support for starred state. - Added starred projects and agents sidebar rendering, plus star controls on list and detail pages. - Added focused shared, server, and UI coverage for starred membership behavior and sidebar rendering. ## Verification - Rebased and force-with-lease pushed current PR head `a086fc965391c9e50a51b5b83b5b44a797b2a6f4` onto current `paperclipai/paperclip:master`; `gh pr view` reports `MERGEABLE` with no merge conflicts. GitHub checks are green for this fresh head. - `pnpm exec vitest run packages/shared/src/resource-memberships.test.ts server/src/__tests__/resource-memberships-routes.test.ts server/src/__tests__/workspace-runtime.test.ts ui/src/components/Sidebar.test.tsx ui/src/components/SidebarAgents.test.tsx ui/src/components/SidebarStarredProjects.test.tsx ui/src/components/StarToggle.test.tsx ui/src/pages/InstanceExperimentalSettings.test.tsx` passed after the rebase: 8 files, 143 tests. - Greptile re-review is 5/5; the remaining screenshot thread was resolved as non-blocking because this task explicitly requested no screenshots/images in the PR. - `pnpm exec vitest run ui/src/components/SidebarStarredProjects.test.tsx` passed after the mobile pending-spinner fix. - `pnpm exec vitest run packages/shared/src/resource-memberships.test.ts server/src/__tests__/resource-memberships-routes.test.ts ui/src/components/Sidebar.test.tsx ui/src/components/SidebarAgents.test.tsx ui/src/components/SidebarStarredProjects.test.tsx ui/src/components/StarToggle.test.tsx ui/src/pages/InstanceExperimentalSettings.test.tsx` passed: 7 files, 68 tests. - `pnpm --filter @paperclipai/db typecheck && pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/server typecheck && pnpm --filter @paperclipai/ui typecheck` passed db/shared/server, then failed in pre-existing UI code outside this PR: `src/pages/CompanyEnvironments.tsx` missing `@xterm/*` type declarations and `previous` possibly null. - Checked that the PR diff does not include `pnpm-lock.yaml` or `.github/workflows` changes. - Checked `ROADMAP.md` and found no overlapping planned core work for starred resource/sidebar navigation. - Searched existing GitHub PRs for duplicate starred-resource/sidebar work and found none. ## Risks - Migration touches membership tables. The SQL uses `IF NOT EXISTS` for columns and indexes so environments that saw an earlier local migration name can still apply this safely. - Sidebar ordering and visibility changes could affect users who rely on the previous flat sidebar layout. - Starred state is per-user membership metadata; code paths must continue preserving company/user scoping around memberships. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 Codex, tool-enabled coding agent with shell/GitHub access. Context window not disclosed by the runtime. ## 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> |
||
|
|
c5e03c6d01 |
fix(db): relocate slow 0126 issue-comment attribution backfill to fast idempotent 0132 (#9108)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The database layer runs migrations during server startup via `server.listen`; migrations that block this path delay instance availability > - Migration `0126_issue_comment_derived_attribution.sql` backfills derived attribution columns on `issue_comments` using a LIMIT-5000 loop with no index or keyset cursor — it re-scans the full table from the start each batch, giving O(n²) complexity > - On instances with millions of issue comments this blocked `server.listen` for ~5 minutes during upgrade, causing CPU pegs and unavailability > - Editing 0126 in place is unsafe: the migration runner keys its applied-set on file **content hash**, so any edit changes the hash, causing the runner to re-apply the migration on already-migrated databases and blocking startup > - The safe remedy is delete-and-relocate: remove 0126 and add a new forward migration 0132 that uses a temporary partial index + keyset pagination (`id > last_comment_id ORDER BY id LIMIT 5000`) so every row is visited exactly once — O(n) > - This pull request implements that delete-and-relocate with idempotency guards (IF NOT EXISTS DDL, backfill WHERE clause that skips already-attributed rows) so it is a safe near-noop on already-migrated, partially-migrated, and fresh databases alike ## Linked Issues or Issue Description No pre-existing public GitHub issue. Inline bug report: **What happened?** The `0126_issue_comment_derived_attribution` migration runs during server startup and uses a LIMIT-5000 batch loop that re-scans `issue_comments` from row 1 each iteration (no index, no keyset cursor). The result is O(n²) I/O that blocked `server.listen` on large instances. **Expected behavior** Backfill migrations should advance with a keyset cursor so each batch reads a new slice; total work is O(n) and startup is not blocked. **Steps to reproduce** Run a Paperclip upgrade on an instance with ≥200k issue comments; observe `server.listen` blocked for several minutes and CPU peg during migration. **Paperclip version or commit** Reproduced on the current `master` branch prior to this fix. **Deployment mode** All deployment modes that run the migration runner at startup. ## What Changed - **Deleted** `packages/db/src/migrations/0126_issue_comment_derived_attribution.sql` — the O(n²) LIMIT-5000 loop with no index/cursor - **Added** `packages/db/src/migrations/0132_issue_comment_derived_attribution_fast.sql`: - Creates a temporary partial index over the eligible predicate before backfilling - Uses keyset pagination (`id > last_comment_id ORDER BY id LIMIT 5000`) — each batch advances to the batch-max id, so every row is visited once - Drops the temporary index at the end - Columns/FKs guarded with `IF NOT EXISTS`; Option-A timing-tier cleanup preserved; human-authored comments never touched - `WHERE` clause in the backfill excludes rows already attributed (safe near-noop on already-migrated DBs) - **Updated** `packages/db/src/migrations/meta/_journal.json` — dropped 0126 entry, appended 0132 - **Added** `packages/db/src/issue-comment-derived-attribution-migration.test.ts` (345 lines) — covers fresh-install, already-0126-migrated idempotency, and partial-backfill completion scenarios using embedded Postgres ## Verification ```bash # Migration numbering guard pnpm --filter @paperclipai/db check:migrations # Migration tests (embedded Postgres, 3 scenarios) pnpm --filter @paperclipai/db vitest run issue-comment-derived-attribution-migration.test.ts ``` Both pass locally. CI results will appear on this PR. ## Risks **Migration safety — already-migrated databases:** Deleting 0126 leaves an orphan row in the runner's applied-set. The runner only checks the set for "has this been applied" — orphan rows are never re-applied. 0132 runs as a near-noop: IF NOT EXISTS DDL is skipped, and the backfill WHERE clause excludes rows that already have attribution. **Migration safety — partially-migrated databases:** Keyset pagination is idempotent. 0132 picks up from the highest attributed row id, so a partial prior run is completed correctly. **No data loss:** The migration never deletes or overwrites user-authored content. It only writes to derived attribution columns on rows where attribution is absent. **Rollback:** 0132 is a forward-only migration. If a rollback is needed, the attribution columns remain (no harm) and can be ignored or cleaned up in a subsequent migration. ## Model Used Claude Sonnet 4.6 (`claude-sonnet-4-6`) via the Paperclip AI agent harness, with tool use and extended context enabled. Implementation authored by Priya Raman; PR opened via the Paperclip Git Expert agent. ## 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) - [ ] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details _(branch is the preserved implementation branch from the authoring engineer; the internal task id is present in the branch name by workflow convention — not a content risk)_ - [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 - [ ] All Paperclip CI gates are green _(pending — CI running)_ - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups _(pending — will be driven to terminal-green before merge)_ - [ ] I will address all Greptile and reviewer comments before requesting merge _(pending — will action all findings)_ Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
1e81bd188b |
Fix heartbeat run responsible user migration for identifier refs (#9107)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip stores heartbeat run ownership context so operators can
audit which user was responsible for agent work
> - A migration backfills missing heartbeat run `responsible_user_id`
values from issue references in each run's context snapshot
> - Some context snapshots can store issue identifiers as public ticket
strings rather than UUIDs
> - The migration needs to resolve both UUID issue ids and issue
identifiers without trying to cast identifier strings to UUID
> - This pull request tightens the migration query so UUID matching only
casts validated UUID-shaped values and identifier matching remains a
separate fallback
> - A companion repair migration is needed so installations that already
recorded `0130` still get the corrected heartbeat-run backfill
> - The benefit is that existing installations can apply the
responsible-user invariant migrations without failing on non-UUID issue
references and without leaving already-migrated databases unrepaired
## Linked Issues or Issue Description
No public GitHub issue was found in a quick search for this migration
failure.
Bug report context following `.github/ISSUE_TEMPLATE/bug_report.yml`:
**Pre-submission checklist**
- I searched existing open and closed issues and did not find a
duplicate.
- I can reproduce against current `master` plus the responsible-user
invariant migration path.
- The error originates in Paperclip's database migration, not in an
adapter, API provider, or local configuration.
**What happened?**
Applying the heartbeat run responsible-user backfill migration could
fail when `heartbeat_runs.context_snapshot->>'issueId'` or `taskId`
contained an issue identifier such as `PAP-123` instead of a UUID. The
migration attempted to use issue refs for UUID matching and identifier
fallback, but the UUID path needed to avoid casting non-UUID identifier
strings. Because `0130` may already have been applied in some
installations, a follow-up repair migration is needed as well.
**Expected behavior**
The migration should backfill from UUID issue ids when present, from
issue identifiers when present, and fall back to the company default
responsible user without unsafe UUID casts. Already-migrated
installations should receive the repaired heartbeat-run context-ref
backfill through a new migration.
**Steps to reproduce**
1. Use a migrated database with a company, issue, agent, and heartbeat
run.
2. Store a null `heartbeat_runs.responsible_user_id` and a
`context_snapshot` like `{"issueId":"PAP-123"}`.
3. Replay/apply the run responsible-user repair migration.
4. Observe that the migration must not cast `PAP-123` to UUID and should
backfill from the matching issue identifier.
**Paperclip version or commit**
Current `master` plus this migration fix branch.
**Deployment mode**
Database migration during server startup or explicit migration command.
**Installation method**
Built from source / self-hosted migration path.
**Agent adapter(s) involved**
Not adapter-specific; core database migration bug.
**Database mode**
Postgres migration path, including embedded Postgres in development.
**Access context**
Not applicable; migration-time data backfill.
**Relevant logs or output**
Unsafe UUID casts can surface as Postgres invalid input syntax errors
when a context snapshot issue ref is an identifier rather than a UUID.
**Privacy checklist**
No private logs, paths, API keys, tokens, company names, or internal
Paperclip issue links are included.
## What Changed
- Split heartbeat run context issue reference extraction into reusable
CTEs.
- Only cast `issueId` / `taskId` values to UUID after a UUID-shape regex
check.
- Preserve fallback matching by issue identifier within the same
company.
- Keep deterministic candidate priority with `issueId` before `taskId`
and UUID matches before identifier matches.
- Added `0131_repair_run_responsible_user_context_refs.sql` so
installations that already applied `0130` still receive the corrected
heartbeat-run backfill.
- Added a DB migration regression test that replays the repair migration
with an identifier-style heartbeat run issue ref.
## Verification
- `pnpm --filter @paperclipai/db typecheck`
- `pnpm --filter @paperclipai/db exec vitest run src/client.test.ts`
- Isolated embedded Postgres migration run with a temporary
`PAPERCLIP_CONFIG`: `pnpm --filter @paperclipai/db migrate` applied all
pending migrations successfully.
- GitHub Actions PR workflow is green on commit
`1c2655bc457cef3716a43e66463e1e5bc2fdcfab`.
- Greptile is 5/5 with no unresolved threads on commit
`1c2655bc457cef3716a43e66463e1e5bc2fdcfab`.
- Searched for duplicate public issues/PRs with GitHub search; no direct
duplicate found.
- Checked `ROADMAP.md` for overlap; no related roadmap item found.
## Risks
- Low-to-medium migration risk because this modifies an existing data
backfill migration and adds a companion repair migration.
- The query still relies on `context_snapshot` containing either issue
UUIDs or identifiers that match issues in the same company.
- Installations with unusual malformed context snapshots now skip unsafe
UUID casts and fall through to identifier/default backfill behavior.
> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
OpenAI GPT-5 Codex coding agent with tool use and local command
execution.
## 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, or
confirmed no docs update is needed for this migration-only fix
- [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>
|
||
|
|
ad961227f5 |
feat(secrets): add user-specific runtime secrets (#8825)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent runs often need provider credentials, API tokens, and other environment-bound secrets. > - Company-level secrets work for shared credentials, but they do not model values that should differ by human operator. > - Without a user-scoped model, a run can dispatch without knowing whether the responsible human has supplied the needed value. > - Paperclip also needs run attribution to make those user-scoped runtime checks deterministic and auditable. > - This pull request adds user-specific secret definitions, per-user values, environment bindings, responsible-user attribution, and runtime resolution gates. > - The benefit is that teams can define the secret once, let each user provide their own value, and block runs before dispatch when required user secrets or active definitions are unavailable. ## Linked Issues or Issue Description Refs #224 Refs #6057 This PR implements user-specific secret support as a core secret-management capability rather than a one-off adapter setting. It is related to existing public work on company secrets UI and runtime secret refs, but is distinct because the value is owned by the responsible user and resolved at run dispatch time. Related PR search before opening found existing secrets work such as #1550, #8256, #8614, #8634, and #8647; none of those add the full user-secret definition/value/runtime gate covered here. ## What Changed - Added user-secret definitions and per-user "My secrets" values, keeping stored values out of access metadata. - Added `user_secret_ref` environment bindings and UI affordances to pick them alongside existing secret refs. - Added responsible-user runtime resolution so user-secret refs resolve against the human responsible for the run. - Added pre-dispatch missing-secret gates so runs fail before adapter dispatch when required user values are absent or definitions are inactive. - Added low-trust allowlist hardening for user-secret runtime access. - Added issue, routine, run, and agent API key responsible-user attribution and fail-closed dispatch behavior when attribution cannot be resolved. - Added denial-copy mapping so responsible-user authorization failures surface as actionable run outcomes instead of opaque setup failures. - Added OpenAPI documentation for the user-secret routes. - Rebases cleanly on current `master`; migrations were renumbered incrementally as `0128_user_specific_secrets`, `0129_agent_api_key_responsible_user`, and `0130_run_responsible_user_invariant` after upstream `0126`/`0127` migrations. - Removed previously committed local design screenshots so the PR contains code/docs/tests only. ## Verification - PASS: PR head `2527febd106bcf3ca264ca0da7fca491084192d6` is based on `paperclipai/paperclip:master`. - PASS: `git diff --check` - PASS: `git diff --name-only public/master...HEAD | rg '^(pnpm-lock\\.yaml|\\.github/workflows/|screenshots/)' || true` produced no files. - PASS: migration journal audit confirmed unique indexes through `130` with tail entries `0126_issue_comment_derived_attribution`, `0127_environment_custom_images_instance_scoped`, `0128_user_specific_secrets`, `0129_agent_api_key_responsible_user`, and `0130_run_responsible_user_invariant`. - PASS: `pnpm --filter @paperclipai/ui typecheck` - PASS: `pnpm --filter @paperclipai/server typecheck` - PASS: `pnpm --filter @paperclipai/server exec vitest run src/__tests__/heartbeat-responsible-user-invariant.test.ts` - PASS: `pnpm --filter @paperclipai/server exec vitest run src/__tests__/heartbeat-active-run-output-watchdog.test.ts src/__tests__/heartbeat-stale-queue-invalidation.test.ts src/__tests__/heartbeat-workspace-finalize-branch.test.ts src/__tests__/issue-monitor-scheduler.test.ts` - PASS: `pnpm --filter @paperclipai/server exec vitest run src/__tests__/heartbeat-comment-wake-batching.test.ts src/__tests__/heartbeat-retry-scheduling.test.ts src/__tests__/heartbeat-accepted-plan-workspace-refresh.test.ts src/__tests__/heartbeat-plugin-environment.test.ts` - PASS: `pnpm --filter @paperclipai/server exec vitest run src/__tests__/low-trust-red-team-routes.test.ts` - PASS: `pnpm --filter @paperclipai/server exec vitest run src/__tests__/secrets-service.test.ts` (55 tests) - PASS: `pnpm vitest run server/src/__tests__/secrets-routes.test.ts server/src/__tests__/secrets-service.test.ts` (89 tests after final Greptile cleanup fixes) - PASS: `pnpm --filter @paperclipai/server exec vitest run src/__tests__/heartbeat-issue-liveness-escalation.test.ts` (17 tests after the final rebase CI fix) - PASS: focused server Vitest batches covering heartbeat recovery, project env, plugin env, routines, low-trust, pipelines, monitors, watchdog, and stale queue paths. - PASS: GitHub checks are green on `2527febd106bcf3ca264ca0da7fca491084192d6`, including Typecheck + Release Registry, Build, General tests, serialized server suites, e2e, Canary Dry Run, verify, security checks, and Greptile Review. - PASS: Greptile Review completed successfully on `2527febd106bcf3ca264ca0da7fca491084192d6` with Confidence Score 5/5, and GraphQL review-thread audit returned zero unresolved non-outdated threads. ## Risks - Runtime behavior now depends on a run having a correct responsible user; missing or incorrect responsibility assignment can block runs before adapter dispatch. - `user_secret_ref` bindings intentionally expose metadata without values, but UI/API callers may need to handle the new binding kind explicitly. - External secret providers and IAM policies are not automatically provisioned by this PR; operators still need to configure provider-side access for non-local vaults. - The PR is broad across db/shared/server/UI/runtime paths, so release validation should include both API and UI secret workflows before merge. - The migration renumbering is intentionally incremental after upstream migrations; the branch migrations use guarded column/table/index/constraint creation so users who tested the older draft numbering should not hit duplicate DDL for the existing objects. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5-based coding agent (`gpt-5`), Codex local adapter with shell/tool use and code execution. Context window and internal reasoning mode are not exposed by the runtime. ## 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b4815bf964 |
Scope environment custom images to instance environments (#8850)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Environments are now managed as instance-level runtime resources rather than per-company rows > - The custom environment image setup tables were introduced with their own `company_id` columns and route query parameters > - That split made one saved environment image state depend on an extra company context even though the environment itself is the durable owner > - It also made saved-environment probes harder because applying the active custom image template could require a company context when no secret-backed config needed one > - This pull request scopes custom image templates and setup sessions directly to the saved environment > - The benefit is that reusable environment images follow the same instance-scoped model as environments while secret resolution still uses company context only when secrets require it ## Linked Issues or Issue Description No matching public GitHub issue was found. Bug report: ### What happened? saved environment custom-image routes and persistence required a `companyId` even though environments are instance-scoped, and saved sandbox probes did not opt into active custom-image template application unless a company context was present. ### Expected behavior custom-image templates and setup sessions should be owned by the saved environment, and saved sandbox probes should apply the active template while still requiring a company context only for secret-backed runtime config. ### Steps to reproduce 1. Configure an instance-scoped sandbox environment with custom-image setup support. 2. Start or inspect a custom-image session or template for that saved environment. 3. Probe the saved environment without a custom-image-specific `companyId` query parameter. ### Paperclip version or commit current `master` after the environment custom-image template migration. ### Deployment mode Local dev (pnpm dev) or authenticated local Paperclip instance. ### Installation method Built from source (pnpm dev / pnpm build). ### Agent adapter(s) involved Not adapter-specific (core bug). ### Database mode Embedded PGlite/Postgres dev database. ### Access context Board human operator. ### Privacy checklist No logs, secrets, tokens, private URLs, or local machine paths are included. Duplicate search performed: - `gh search prs "environment custom image companyId repo:paperclipai/paperclip" --state open --limit 20` - `gh search prs "custom image environment scoped repo:paperclipai/paperclip" --state open --limit 20` - `gh search issues "environment custom image repo:paperclipai/paperclip" --state open --limit 20` The returned results were unrelated adapter, Docker, auth, or stale-workspace items. ## What Changed - Removed redundant `company_id` columns from environment custom-image templates and setup sessions. - Added migration `0127_environment_custom_images_instance_scoped` to collapse duplicate active rows per environment before dropping the old company-scoped indexes/columns. - Updated custom-image services, route handlers, shared validators, and UI API/query keys to use environment-scoped custom-image state. - Kept runtime secret resolution company-aware only when secret refs or bindings require a company context. - Made saved sandbox environment probes opt into active custom-image template application. - Updated DB, shared, server, and UI tests for the new environment-scoped contract. ## Verification - `pnpm --filter @paperclipai/db run check:migrations` - `pnpm exec vitest run packages/db/src/environment-custom-images-schema.test.ts packages/shared/src/environment-custom-images.test.ts server/src/__tests__/environment-custom-image-routes.test.ts server/src/__tests__/environment-custom-images-service.test.ts server/src/__tests__/environment-routes.test.ts ui/src/pages/CompanyEnvironments.test.tsx` - `pnpm -r typecheck` - `pnpm test:run` before rebasing onto latest `master`; after the rebase only the migration number changed, and the migration check plus focused suite, typecheck, and build were rerun. - `pnpm build` ## Risks - Migration safety: the migration supersedes duplicate active templates per environment and fails duplicate active setup sessions before adding environment-only unique indexes. Operators with duplicate historical active rows should review which active template is kept. - Behavior shift: plugin custom-image setup calls now receive `companyId: "instance"` when no secret binding determines a concrete company context. - Secret-backed configs still require an explicit or uniquely inferable company context; environments with secret bindings spread across multiple companies continue to fail fast. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex via the `codex_local` adapter, GPT-5-based coding model with tool-enabled repository inspection, editing, testing, git, and GitHub CLI access. Exact context-window metadata was not exposed by the runtime. ## 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 - [ ] All Paperclip CI gates are green - [ ] 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> |
||
|
|
fb2b760915 |
fix(issues): attribute agent-authored comments instead of rendering them as "Board" (#8833)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Task/issue threads render each comment as a chat bubble; the author determines whether it shows as a left-aligned agent bubble (name + icon) or a right-aligned "Board" bubble > - Comments posted by an agent from a local execution environment are written with a non-human author id (`local-board`/system), so they were mis-rendered as blue "Board" bubbles instead of being attributed to the authoring agent > - This misattribution is confusing (it looks like the human board said something an agent actually said) and it can drive false wake/reconciliation behavior on the affected threads > - This pull request adds server-side attribution derivation (lossless run-id join first, then an explicit run-log post marker), persists the derived agent so the read path stops re-scanning run logs, and stops the client from labeling agent-derived comments "Board" > - The benefit is agent comments render as the correct agent, genuine human board comments are never reattributed, and reads get cheaper after a one-time persistence ## Linked Issues or Issue Description <!-- No public GitHub issue — describing the problem in-PR (bug report shape). --> **What happened?** In a task/issue comment thread, comments authored by an agent from a local execution environment are stored with a non-human author id (`local-board`/system). The UI renders these as right-aligned blue "Board" bubbles, implying a human board member authored them. The mislabeling is also a wake/reconciliation hazard: an agent comment that reads as "Board" can look like human board input. **Expected behavior** Such comments should render as the authoring agent (left-aligned bubble with agent name + icon). Genuine human/board comments must continue to render as "Board" and must never be reattributed to an agent. **Steps to reproduce** 1. Have an agent post a comment on an issue from a local execution environment (author id `local-board`). 2. Open the issue comment thread in the UI. 3. Observe the agent's comment rendered as a right-aligned blue "Board" bubble instead of the authoring agent. **Root cause** The read path did not resolve the authoring agent for these comments, and the client fell back to a "Board" label for the `local-board` author. ## What Changed - **Server derivation (`server/src/services/issues.ts`):** - Resolve the authoring agent from the comment's run id first (`createdByRunId`/`derivedCreatedByRunId` → `heartbeatRuns.agentId`) — lossless when present. - Second tier `run_log_comment_post`: read the run log lazily (only for still-unresolved comments) to match the explicit `comment id:` post marker. - **Guard:** never reattribute a comment whose author maps to a genuine user profile. Only the non-human sentinel (`local-board`, which is itself a `user` row) and authors absent from the `user` table are eligible. - Pure timing-overlap tiers are intentionally **not** used (Option A) — an agent comment and a human board comment posted during the same run are indistinguishable rows, so any timing guess risks mislabeling a real human comment. - **Persistence (`packages/db/src/migrations/0126_issue_comment_derived_attribution.sql`, `packages/db/src/schema/issue_comments.ts`):** add stored `derived_*` attribution columns and write the resolved agent back with a single bulk `UPDATE ... FROM (VALUES ...)`, so reads stop recomputing from run logs. Migration is additive (new nullable columns) with a batched, idempotent backfill of the lossless run-id tier over historical rows. - **Types (`packages/shared/src/types/issue.ts`):** expose the persisted attribution fields and the `IssueCommentDerivedAuthorSource` union. - **Client (`ui/src/lib/issue-chat-messages.test.ts`):** the message builder already prefers a resolved agent id (`authorAgentId ?? runAgentId ?? derivedAuthorAgentId`), so once the server persists the derived agent the bubble renders as the agent automatically — no client code change needed. Adds a regression guard confirming a genuine board comment with no derived agent is still rendered as "Board". - **Tests:** derivation + message-building tests, including assertions that genuine board/user comments are **not** reattributed. ## Verification - `cd server && npx vitest run issues-service` — 94 tests pass: run-id resolution, no-attribution on timing overlap alone (Option A), multi-run ambiguity, same-agent multi-run, and the genuine-user guard. Exercises the real persistence path (bulk UPDATE) against the test DB. - `cd ui && npx vitest run issue-chat-messages` — 27 tests pass; client no longer labels agent-derived comments "Board", and a genuine board comment with no derived agent is not re-labeled. - `cd server && npm run typecheck` — passes (exit 0). - Manual: on a thread containing old agent-authored comments, the blue "Board" bubbles render as the authoring agent; a genuine board comment on the same thread still renders as "Board". ## Risks - **Mis-reattributing a genuine board comment made during an agent run** → mitigated by the human-profile guard (only `local-board`/system authors are eligible) and by dropping pure timing tiers (Option A): only the lossless run-id join and the explicit run-log post marker attribute history. - **Backfill volume / run-log reads** → the migration backfill is batched (5000 rows/loop) and results are persisted so reads stop recomputing; the read-path persistence is a single bulk UPDATE rather than per-comment round-trips. Migration adds only nullable columns (no destructive change). - The persistence/backfill has **not** been run against any production database as part of opening this PR. ## Model Used Claude Opus 4.8 (`claude-opus-4-8`), extended thinking, via Claude Code with tool use. ## 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 — related open PRs (#6006 narrow attribution run scan, #4729 attribution roll-up, #7014 reaped-run attribution) address different attribution paths; none fix the `local-board` "Board" bubble rendering this PR targets. Supersedes #8832 (same change; branch renamed to drop an internal ticket id per CONTRIBUTING → Branch Naming) - [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 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: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
8d9f9fd240 |
Add reusable sandbox custom images (#8794)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - A growing part of that work runs in sandboxed environments rather than on the operator's local machine. > - Today sandbox providers can start fresh workspaces and run probes, but they do not have a shared contract for capturing and reusing prepared sandbox state. > - Operators need a way to set up tools, credentials, and project dependencies once, then reuse that prepared image for later agent runs. > - This pull request adds reusable sandbox custom images across the provider contract, server runtime, and board UI. > - It also keeps probes and sandbox copy flows aligned with pre-authenticated/custom-image environments. > - The benefit is faster, more reliable sandbox runs without repeatedly rebuilding the same environment setup. ## Linked Issues or Issue Description No public GitHub issue was found for this change. Inline feature request follows. ### Problem or motivation Sandboxed agents need reusable prepared runtime state so repeated runs do not require manual setup every time. Operators often need system packages, CLIs, SDKs, dependency caches, credentials, and project tooling available before an agent can work productively. ### Proposed solution Add a provider-level custom-image capability, server-side setup/capture lifecycle, Daytona/fake provider support, and board UI controls for creating, testing, selecting, and deleting custom images. ### Alternatives considered Leaving this as provider-specific setup outside Paperclip would keep the control plane blind to image state and would not give agents consistent environment metadata. Re-running setup commands for every lease is simpler, but slower and less reliable for interactive or credentialed setup. ### Roadmap alignment Checked `ROADMAP.md`; this aligns with the Cloud / Sandbox agents roadmap area and does not duplicate any related public issue or PR found by search. Additional context: - Subsystem affected: cross-cutting (`packages/db`, `packages/shared`, `packages/plugins`, `server`, `ui`). - Duplicate search: searched GitHub for `sandbox custom image` and `sandbox template environment`; no related public issues or PRs were found. ## What Changed - Added custom-image shared types, validators, constants, API paths, and database schema/migration. - Added server services/routes for custom-image templates and setup sessions, including runtime cleanup and provider metadata handling. - Extended plugin/sandbox provider capabilities for interactive setup, template capture, and template deletion. - Implemented custom-image support in the fake sandbox provider and Daytona provider. - Updated environment runtime/config handling so active custom images flow into leases, probes, and agent execution. - Added board UI controls and API client support for custom-image setup, capture, selection, status, and error states. - Hardened sandbox copy/probe behavior for insecure clipboard contexts and pre-authenticated sandbox images. - Added targeted coverage across shared validators, DB schema, server routes/services, provider plugins, adapter probes, and UI flows. ## Verification - `pnpm install --frozen-lockfile --ignore-scripts` - `pnpm vitest run packages/adapters/claude-local/src/server/test.probe.test.ts packages/adapters/claude-local/src/server/test.ts packages/adapters/codex-local/src/server/test.remote.test.ts packages/adapters/codex-local/src/server/test.ts` - `pnpm --filter @paperclipai/adapter-claude-local typecheck` - `pnpm --filter @paperclipai/adapter-codex-local typecheck` - `pnpm vitest run packages/db/src/environment-custom-images-schema.test.ts packages/shared/src/environment-custom-images.test.ts packages/shared/src/validators/plugin.test.ts server/src/__tests__/environment-custom-images-service.test.ts server/src/__tests__/workspace-runtime.test.ts packages/plugins/sandbox-providers/daytona/src/plugin.test.ts ui/src/pages/CompanyEnvironments.test.tsx ui/src/pages/CompanySettings.test.tsx` - `pnpm -r typecheck` - `pnpm build` - `rm -rf packages/db/dist && pnpm test:run` - Public-safety scan of the final diff found no internal Paperclip issue links, private instance URLs, or real secret patterns. ## Risks - Adds a database migration and new environment runtime tables, so migration ordering and rollback need care. - Provider implementations may differ in how reliably they can capture/delete images; unsupported providers surface capability-gated UI states. - Custom-image state can contain operator-prepared tooling and credentials inside the provider image, so providers must enforce their own access controls and cleanup semantics. - Broad surface area across shared contracts, server runtime, plugins, adapters, and UI means CI and Greptile review should be watched closely. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 (`gpt-5`) via Codex CLI with tool use and code execution. Assisted with branch cleanup, conflict resolution, local verification, and PR preparation. Earlier branch implementation work was assisted by Paperclip-managed Claude/Codex agents. ## 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 - [ ] All Paperclip CI gates are green - [ ] 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> |
||
|
|
e6407b3225 |
refactor: revert X mention poller backend (#8709)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The core server and database packages should only carry features that are ready to remain in the product surface. > - The X mention poller backend added database tables, Drizzle schema exports, a server service, and a server test suite. > - That backend work needs to be removed from core for now so the main app does not carry unused X mention poller infrastructure. > - A clean revert is safer than leaving partially unused database and service code behind. > - This pull request removes the poller backend artifacts and keeps the migration journal aligned with the reverted migration history. > - The benefit is that fresh environments no longer create or expose the X mention poller backend tables or service code. ## Linked Issues or Issue Description No public GitHub issue exists for this revert. Duplicate PR search: searched open PRs in `paperclipai/paperclip` for "x mention poller"; only this PR matched. ### What happened? Core contained X mention poller backend infrastructure that should not remain in the main Paperclip product surface right now. ### Expected behavior Fresh core installs and migrations should not create the X mention poller tables, and the server/db packages should not expose the removed poller service or schema exports. ### Steps to reproduce 1. Inspect the prior migration journal after the original poller backend commit. 2. Inspect the Drizzle schema exports. 3. Inspect the server services and tests for X mention poller backend artifacts. ### Paperclip version or commit This PR reverts the backend artifacts from the current `master` history. ### Deployment mode Local development and CI. ## What Changed - Deleted the `0125_x_mention_poller` migration and removed its journal entry so fresh environments do not create the X mention poller tables. - Removed the X mention Drizzle schema file and schema exports from the db package. - Removed the X mention poller server service and its server test suite. - Left the functional diff unchanged from the original revert. ## Verification - `rg -n "x_mentions|x-mention-poller|mention poller|0125_x_mention_poller|xMention" packages server` returned no matches. - `pnpm --filter @paperclipai/db typecheck` - `pnpm --filter @paperclipai/server typecheck` - Current functional CI checks are green; this metadata update is intended to re-run and clear the `commitperclip PR Review` gate. ## Risks - Developers who already applied migration `0125_x_mention_poller` locally will keep four stale tables that Drizzle no longer tracks: `x_mention_sources`, `x_mention_author_allowlist`, `x_mentions`, and `x_mention_budget_ledger`. - Manual local cleanup for those developers is to drop the stale `x_mention_*` tables from their local database after confirming they do not need that local data. - Fresh environments that have not applied the removed migration should be unaffected. ## Model Used OpenAI Codex, GPT-5 family, via the ACPX-backed Codex local adapter. Tool use included local shell inspection and GitHub CLI metadata updates. ## 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 - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
44e2ab53fe |
feat: add X mention poller backend (#8707)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents and operators increasingly need external event sources to become durable Paperclip work inputs > - X mentions are one such source, but intake needs to be safe before any downstream automation consumes them > - The backend needs stable source state, idempotent mention storage, author gating, rate-limit handling, and budget accounting > - This pull request adds the database contract and service layer for X mention polling and hydration queueing > - The benefit is that future X-triggered workflows can build on a controlled, test-covered ingestion path instead of calling the X API directly ## Linked Issues or Issue Description - No public GitHub issue exists for this exact backend extraction. - Problem: Paperclip does not yet have a durable, budget-aware backend path for ingesting X mentions as external work inputs. - Proposed solution: add X mention source, mention, allowlist, and budget ledger tables plus a poller service that stores mentions idempotently, queues only allowlisted authors for hydration, tracks cursor state, records spend decisions, and fails closed when cost estimates are unavailable. - Related but not duplicate: #8609, #8199, and #7316 touch internal mention wake behavior rather than X API mention ingestion. ## What Changed - Added X mention poller database tables and schema exports for sources, stored mentions, author allowlists, and budget ledger entries. - Added a server-side X mention poller service with cursoring, idempotent upsert behavior, allowlist gating, hydration queue handling, rate-limit backoff, and budget pause behavior. - Added focused Vitest coverage for intake gating, duplicate retries, cursor safety, rate limits, budget failures, and hydration budget pauses. ## Verification - `pnpm exec vitest run server/src/__tests__/x-mention-poller.test.ts` - `pnpm --filter @paperclipai/db typecheck` - `pnpm --filter @paperclipai/server typecheck` ## Risks - Migration ordering matters because this adds migration `0125_x_mention_poller.sql`; it should merge after the existing `0124` migrations on `master`. - The service is backend-only and adapter-driven in this PR, so product behavior should not change until callers wire it into a runtime path. - Budget accounting intentionally fails closed when estimates are missing, which may pause a source rather than risk unbounded API spend. ## Model Used - OpenAI Codex, GPT-5-based coding agent, tool-enabled local repository and terminal workflow. ## 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> |
||
|
|
fd2f82ac5b |
[codex] Add built-in Hermes adapters (#8543)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent adapters are the boundary between the control plane and the runtimes that actually do work. > - Hermes support needs to be available as first-class local and gateway adapters while still preserving the adapter-manager override path for external packages. > - The adapter work touches runtime execution, UI adapter metadata, onboarding prompts, scoped credentials, release packaging, and smoke coverage, so the handoff needs concrete verification rather than only unit tests. > - This pull request adds built-in Hermes local and Hermes gateway support, keeps external adapter overrides compatible, and documents/tests the gateway flow end to end. > - The benefit is that operators can hire Hermes-backed agents without a manual plugin install, while self-hosted installs can still override/shadow the built-ins through Adapter manager packages. ## Linked Issues or Issue Description No public GitHub issue exists for this exact Hermes built-in adapter, gateway onboarding, and release-source work. Problem description: - Hermes local and gateway adapters need a public, reviewable source path in the monorepo so package artifacts and built-in adapter behavior match the application source. - Operators need built-in `hermes_local` and `hermes_gateway` adapter choices without losing the ability to install external Hermes packages as overrides. - Gateway onboarding needs secure defaults for API server URLs, API keys, and generated agent setup text. - Hermes-originated task bridge credentials need narrower API-key scope configuration. - Related public PRs found during duplicate search include #3027, #2363, #7544, #7950, #8095, and #8543. ## What Changed - Added the unified Hermes adapter package with local and gateway server/UI/CLI exports, config schemas, transcript parsing, model detection, and package metadata. - Registered `hermes_local` and `hermes_gateway` as built-in adapters across shared constants, server registries, CLI packaging, and UI adapter registries. - Kept the external adapter override path compatible so installed Hermes packages can shadow built-ins and restore the built-in parser when disabled. - Added Hermes gateway onboarding docs, board-operator docs, Docker smoke assets, and shell smoke harnesses for join/e2e validation. - Added scoped task-bridge API-key support, authorization checks, issue-origin handling, and tests for Hermes-created Paperclip tasks. - Hardened gateway transport and redaction behavior for API keys, headers, session data, and smoke diagnostics. - Updated release packaging/bootstrap checks for the Hermes packages while leaving `pnpm-lock.yaml` out of the PR per repository policy. ## Verification Targeted local verification recorded before PR handoff: - `pnpm --filter @paperclipai/hermes-paperclip-adapter exec vitest run src/gateway/server/execute.test.ts` — 14/14 passed. - `pnpm test:hermes-gateway-smoke` — 6/6 passed. - Hermes package typecheck/build checks passed. - Focused server/UI adapter tests passed — 31/31. - Release helper Node tests passed — 18/18. - `git diff --check origin/master..HEAD` passed. Fresh Docker E2E smoke evidence: - Ran `pnpm smoke:hermes-gateway-e2e` on 2026-06-26 with a fresh state directory and fresh Docker container against a live Paperclip dev server. - Hermes direct execution reached `completed`. - Hermes stop/cancel path reached `cancelled`. - Hermes gateway created a Paperclip task, Paperclip ran the Hermes agent, and the task reached `done` with the expected marker response. - Temporary board auth keys, token files, smoke state, and Docker containers were cleaned up after the run. PR checks on head `b5eae40ce`: - GitHub Actions passed: `policy`, `review`, `Typecheck + Release Registry`, all general test shards, all serialized server shards, `Build`, `Canary Dry Run`, `e2e`, and aggregate `verify`. - External checks passed: Snyk and Socket Project Report. - External Socket Pull Request Alerts remained pending after the first-party CI matrix completed. ## Risks - Medium risk: this spans adapter registration, package publishing, gateway execution, onboarding docs, API-key scoping, and UI adapter metadata. - Migration risk is low: the scope-config migration adds a nullable column and does not rewrite existing keys. - Gateway execution depends on operator-provided Hermes API configuration; the smoke covers the Docker gateway path but real deployments may differ by network/auth setup. - Direct Greptile review on the latest expanded diff is file-count limited, although the commitperclip review gate passed. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5 coding agent, tool use enabled in a local repository workspace. Context window size is not exposed in this environment. ## 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] Commitperclip review gate is green; direct Greptile review is file-count limited on the latest expanded diff - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
43b005b704 |
Add pipeline workflow primitives and operator UI (#7903)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The pipeline subsystem models repeatable work as items moving through stages, with agent automation, review gates, blockers, drift notices, and linked work. > - Operators need this to be usable as one coherent workflow surface, not just as backend primitives or disconnected route experiments. > - The branch now carries the pipeline data model, service/routes, CLI/tutorial path, aggregation feeds, operator UI, stage automation controls, liveness/retry handling, and follow-up polish that make the primitive reviewable end to end. > - This pull request is the single review target for that pipeline workflow primitive stack. > - The benefit is that reviewers can evaluate the full operator experience and server contract together against `master`. ## Linked Issues or Issue Description No public GitHub issue exists for this work. The underlying feature request is described inline. ### Problem or motivation Paperclip needs a first-class way to model multi-stage agent/company workflows where upstream items can spawn downstream work, request review, carry fields across pipelines, surface drift, retry automation, and show operators where work is blocked or active. Without a unified pipeline primitive, these workflows spread across ad hoc issues, routines, and comments, making the state hard to inspect or operate. ### Proposed solution Add the pipeline workflow primitive stack: database schema and migrations, shared validators/types, server services and REST routes, aggregation and liveness helpers, CLI/tutorial smoke support, and the React operator UI for pipeline lists, boards, item detail, review/learnings views, settings, stage automation, secrets, carry-over fields, and retry/recovery flows. ### Alternatives considered - Keep workflows as loosely linked issues and routines: rejected because operators need a single board/detail/settings surface for repeated workflow patterns. - Ship backend primitives first and defer UI: rejected for this branch because the operator experience is the main way to validate the primitive. - Add a narrower one-off content workflow: rejected because the same primitives are useful across future company processes. ## What Changed - Added and evolved pipeline schema, migrations, shared contracts, server services, REST routes, route tests, and CLI/tutorial smoke support. - Added pipeline aggregation, health/liveness, drift acknowledgment, blocker/carry-over, automation retry, stage automation environment, and permission recovery behavior. - Added the operator UI for pipeline index/board/item detail/settings/review/learnings flows, including stage secrets, automation controls, markdown/item descriptions, linked issue assets, liveness banners, and source automation metadata. - Refactored issue document frame rendering through the shared `DocumentFrameHeader` component to keep document controls consistent with the pipeline document surfaces. - Kept this PR as the single base-branch review target for the current pipeline branch. ## Verification Current branch refresh: - `pnpm vitest run server/src/__tests__/pipelines-service.test.ts` — 31 passed - `pnpm vitest run server/src/__tests__/pipelines-routes.test.ts` — 19 passed - `pnpm --filter ./server typecheck` — passed - `pnpm --filter ./ui typecheck` — passed - Verified Pipelines remains gated by `enablePipelines === true`: sidebar item is hidden unless the flag is enabled, direct pipeline routes redirect to `/dashboard` when disabled, and the Experimental settings UI still has no Pipelines toggle. - GitHub status checks on `df071c710646de625131064c3fb6588b5e97964a` — all complete with no failing conclusions, including Actions, Socket, Superagent/Security, and Greptile Review - Greptile summary on `df071c710646de625131064c3fb6588b5e97964a` — Confidence Score 5/5 - GitHub review-thread sweep — 0 unresolved Greptile threads Previously recorded during branch development: - Server pipeline service/route and aggregation tests - Shared validator tests - UI pipeline page/settings/item-detail/learnings/liveness tests - Pipeline tutorial smoke path ## Risks - High review surface: this is a large feature branch spanning database, shared contracts, server behavior, CLI/docs, and UI. - Migration ordering and schema compatibility need reviewer attention because this branch has been kept current across multiple `master` syncs. - GitHub still reports merge state `BLOCKED` because the PR is awaiting normal human review/branch-protection completion; all current status checks are green. - Branch-name checklist exception: this PR uses the pre-existing requested branch name, which predates the current public-branch naming rule. The PR title/body avoid internal issue references. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex coding agent based on GPT-5, with repository tool use, shell execution, git/GitHub CLI operations, and local verification commands. Earlier commits in this branch were assisted by Paperclip agents and other AI coding agents as recorded in commit authorship. ## 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) - [ ] 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> |
||
|
|
ed65d08d57 |
[codex] Gate skill mutations with skills:create permission (#8616)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents and board users operate inside a company-scoped control plane where permissions decide which mutating actions they can perform > - Company skills are part of the reusable agent-company setup surface, but skill mutation had been coupled to broader agent-creation authority > - That coupling meant importing or managing skills required a permission that also implies hiring power, which is broader than the operation needs > - Paperclip already has a grant-based permission vocabulary, so skill mutation should be authorized through a dedicated `skills:create` capability while preserving existing default behavior for trusted agents > - This pull request adds the skill creation permission contract, enforces it on company skill mutations, exposes it in agent permission management, and documents the changed CLI/API expectations > - The benefit is a narrower, auditable permission path for skill import/create/update/delete flows without forcing agents to receive broader agent-creation authority ## Linked Issues or Issue Description No public issue is linked. Problem: company skill mutation APIs were effectively tied to broader agent creation authority. This PR splits skill mutation authorization onto the public `skills:create` permission while keeping existing default skill creation behavior for agents unless explicitly disabled. Related public PR found during duplicate search: #5330. That PR uses an older `canManageSkills` shape; this PR implements the `skills:create` grant path instead. ## What Changed - Added `skills:create` to shared permission constants and agent permission types/validators as `canCreateSkills`. - Backfilled default human/member role grants for `skills:create`. - Updated company skill mutation routes to require board/user or agent access to `skills:create`, while preserving legacy/default agent behavior through `canCreateSkills` unless explicitly disabled. - Updated agent permission update handling, UI permission controls, duplicate-agent payloads, plugin SDK fixtures, and agent detail API surfaces for `canCreateSkills`. - Added regression coverage for skill route authorization, permission schema/default behavior, invite grants, omitted permission updates, and duplicate-agent payloads. - Updated CLI and Paperclip skill documentation for the new skill creation permission. ## Verification - `pnpm exec vitest run server/src/__tests__/agent-permissions-service.test.ts server/src/__tests__/agent-permissions-routes.test.ts server/src/__tests__/company-skills-routes.test.ts server/src/__tests__/invite-join-grants.test.ts ui/src/lib/duplicate-agent-payload.test.ts` — 5 files, 90 tests passed. - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/server typecheck && pnpm --filter @paperclipai/ui typecheck` — passed. - `pnpm test:run ...changed files...` was attempted first, but the stable wrapper rejects explicit file arguments; direct Vitest was used for the same targeted files. ## Risks - Moderate authorization risk: this changes the gate for company skill mutations, so the tests cover board grant checks, agent explicit grant checks, legacy default allowance, and explicit denial. - Migration/backfill risk is low: the migration only grants `skills:create` to existing human roles that already need broad management capability. - UI/API compatibility risk is low: `canCreateSkills` remains default-on for full agent permissions, and the update validator preserves omitted values so unrelated permission edits do not re-enable disabled skill creation. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5 coding agent with terminal/tool use enabled. ## 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> |
||
|
|
746e287e33 |
feat(control-plane): add annotation and workspace controls (#8229)
## Thinking Path > - Paperclip is the open source app people use to manage AI-agent companies. > - The control plane coordinates issues, workspaces, documents, routines, and board review flows across company-scoped data. > - The local source branch contained related schema, service, and UI changes for workspace issue scoping and document/routine annotations. > - These changes need to move together because db schema, shared types, server services, and UI consumers form one contract. > - This pull request extracts the migration-bearing control-plane work from the source branch onto `origin/master`. > - The benefit is a standalone branch with deterministic migration order and focused review for the highest-risk part of the split. ## Linked Issues or Issue Description No GitHub issue exists for this branch split. Internal source task: [PAP-11234](/PAP/issues/PAP-11234). Problem/motivation: - Workspace operations need explicit issue scoping so readiness and blocker handling can be derived correctly. - Document annotations need reliable live updates, save failure surfacing, normalized activity keys, and better comment panel behavior. - Routine descriptions need the same annotation contract as issue documents so operators can discuss and edit routine text without special-case infrastructure. Proposed solution: - Add the workspace-operation `issueId` migration and readiness scoping. - Add routine document/annotation schema, shared types, services, routes, and UI editing support. - Keep the related migrations in one PR so the renumbered `0106` and `0107` migrations land in a deterministic order after current `master`. Alternatives considered: - Split migrations into separate PRs, rejected because that would create migration-numbering conflicts and make each branch less standalone. - Merge this with UI polish, rejected because this branch needs deeper server/db review. Roadmap alignment: - Checked `ROADMAP.md`; the roadmap mentions future recurring routine capabilities generally, but no duplicate implementation PR for these annotation/workspace changes was found. ## What Changed - Added `0106_workspace_operations_issue_id.sql` and `0107_routine_description_annotations.sql`, plus schema exports. - Scoped workspace readiness to blocker issues and attached workspace operation issue ids. - Scoped issue-thread interaction accept finalization to the source run. - Added routine document annotation contracts across db/shared/server/UI. - Improved document annotation live updates, activity-key normalization, save failure surfacing, and comment panel behavior. - Added issue workspace property controls and compact blocked-by/quick-control UI updates. - Added focused server and UI regression tests for the new contracts. ## Verification - `CI=true NODE_ENV=development pnpm install --frozen-lockfile --prefer-offline` - `NODE_ENV=test pnpm exec vitest server/src/__tests__/document-annotation-routes.test.ts server/src/__tests__/issue-thread-interactions-service.test.ts server/src/__tests__/issues-service.test.ts server/src/__tests__/routine-document-annotation-routes.test.ts server/src/__tests__/routines-routes.test.ts server/src/__tests__/workspace-runtime.test.ts ui/src/components/IssueDocumentAnnotations.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/WorkspaceRuntimeControls.test.tsx ui/src/context/LiveUpdatesProvider.test.ts --run` — 10 files, 273 tests passed. - `NODE_ENV=test pnpm -r --filter @paperclipai/db --filter @paperclipai/shared --filter @paperclipai/server --filter @paperclipai/ui typecheck` — passed, including db migration numbering check. ## Risks - Migration-bearing PR; merge this branch before any later PR that adds migrations with higher numbers. - Cross-layer contract risk across db/shared/server/ui, mitigated with targeted tests and affected-package typecheck. - Review should pay special attention to company scoping in new routine/document annotation paths. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI GPT-5 Codex via Paperclip `codex_local` / CodexCoder, GPT-5-class coding model with tool use and shell execution. Exact runtime snapshot and context-window setting were not exposed by the Paperclip run context. ## 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 available from the run context) - [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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots (N/A per source task: do not add screenshots/images unless specifically part of the work) - [x] I have updated relevant documentation to reflect my changes (N/A; no public docs changed) - [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> |
||
|
|
e68188c438 |
fix: upstream deployed document-comment, routine-annotation, workspace & board-polling fixes (#8536)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - This change touches several already-shipped subsystems — document-comment annotations, the selected-agent Conference Room chat surface, routine description annotations, workspace-operation tracking, and the board polling/inbox UI > - A batch of incremental fixes and two small backend additions had accumulated on a local mainline and were deployed to a live instance, but never landed upstream — so each `origin/master` sync kept re-diverging > - Leaving them un-upstreamed means the same delta has to be re-merged on every sync and risks being lost or silently reverted > - This pull request rebases that delta cleanly on top of current `origin/master` (preserving recent upstream work such as reusable sandbox leases and the relation-list collapse controls) and brings it up for review > - The benefit is that mainline and the deployed instance converge, and these fixes/additions get normal review + CI + Greptile coverage ## Linked Issues or Issue Description No single GitHub issue tracks this; it is a bundle of bug fixes and two small feature additions. Following the issue-template fields: **Bug fixes (what was wrong → what this does):** - Document comments rendered out of document order, didn't live-update across clients, swallowed save failures, and lost the markdown text selection on re-render. Now: doc-order sort, live updates, surfaced save-failure state, stable selection across re-renders. - The board polling hot path returned oversized payloads on every poll. Now: an opt-in `summary` projection trims the heartbeat-run list payload. - Assorted UI fixes: sidebar nav peek/streamlining edge cases, markdown file-viewer re-mount/line-height issues on iOS Safari, inbox badge/skill deep-link tab selection, and `⌘.` work-mode cycling on iOS. **Feature additions:** - `workspace_operations.issue_id` — associate a workspace operation with the issue that triggered it (new migration `0106`, schema, service, shared type). - Routine **description annotations** — comment threads on a routine's description document, mirroring issue document annotations (new migration `0107`, `routine_documents` schema, routes/service, editable-sections UI). - Selected-agent **Conference Room chat** surface wiring and live issue-thread updates. **Related PR:** #8229 (`feat(control-plane): add annotation and workspace controls`, draft) covers overlapping annotation/workspace-control territory — flagging it so a reviewer can reconcile the two rather than double-merging. ## What Changed - `feat(workspace)`: `workspace_operations.issue_id` migration + schema/service/type; issue workspace property controls reconciled with upstream's evolved "Service" row. - `feat(routines)`: routine description annotations — `routine_documents` schema, migration `0107`, routes/service, `editable-sections` UI. - `fix(document-comments)`: doc-order sort, live updates, save-failure surfacing, stable markdown selection (+ storybook story, rerender test). - `feat(chat)`: selected-agent Conference Room chat surface and live issue-thread updates (`LiveUpdatesProvider`, `issue-chat-messages`, interactions service). - `perf(board)`: opt-in `summary` projection for the board polling/heartbeat-run list payload, plus assorted sidebar / file-viewer / inbox / IssueProperties UI fixes. Organized into 5 logical commits. Migrations are numbered incrementally after upstream's latest (`0105`) — `0106` then `0107`, no journal collision. ## Verification - Built by 3-way merging the deployed delta onto current `origin/master`; the only merge conflict (`IssueProperties.test.tsx`, two adjacent test blocks) was resolved in favor of upstream's evolved "green service link above the workspace row" layout, which matches the merged component's rendered output. - Confirmed recent upstream work is preserved post-merge: reusable sandbox lease teardown (`#8513`), the IssueProperties relation-list collapse controls, and the sidebar streamlined-nav default. - Confirmed the net diff vs `origin/master` is exactly the intended feature delta (65 files) and that overlapping server files (`issues.ts`, `agents.ts`, `heartbeat.ts`) only add feature code without disturbing upstream logic. - This delta is already running on a live deployed instance. - Full typecheck/test suite + Greptile to run in CI (see checklist). ## Risks - Two new migrations (`0106`, `0107`). Both are additive (new table / new nullable column) and ordered after upstream's `0105`; no data backfill, low risk. If another migration-bearing PR merges first, renumber before merge. - Largest blast radius is in the merged overlapping UI/service files; covered by the existing test suites for those files plus CI. - Overlaps thematically with draft PR #8229 — reviewers should reconcile rather than merge both blindly. ## Model Used Claude Opus 4.8 (`claude-opus-4-8`), extended thinking, with tool use (git, shell). Agentic coding workflow. ## 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) - [ ] 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 - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [ ] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
2dbaf4a7fa |
External object references across issue surfaces (#8512)
## Thinking Path > - Paperclip is the open source control plane people use to coordinate AI agents, issues, approvals, comments, and work products. > - The involved subsystem is issue context: markdown links, issue properties, related work, lists, filters, inbox/sidebar status, and plugin-provided external context. > - The gap is that URLs to external systems currently remain mostly plain links, so humans and agents must manually open them to understand status, identity, and liveness. > - This matters because external work objects such as GitHub issues and pull requests are part of the operational state of a Paperclip company. > - The implementation keeps core provider-neutral: shared contracts, storage, sync, routes, and UI surfaces live in core while providers can contribute detection and status resolution. > - This pull request adds the external object reference foundation, GitHub provider support, issue-surface rendering, filters, sidebar/list/inbox signals, and test/story coverage. > - The benefit is that linked external work becomes inspectable Paperclip context without hardcoding every provider directly into the UI. ## Linked Issues or Issue Description No public GitHub issue exists for this work. Feature request: - Problem: URLs in Paperclip issues, comments, documents, and related surfaces do not expose provider status or object identity inline. - Proposed behavior: detect supported external object URLs, persist normalized references, refresh provider status, and render concise status-aware links across issue surfaces. - Users affected: board users, agents, and maintainers who triage issues containing external work links. - Acceptance: external object references are company-scoped, provider-extensible, visible in key issue surfaces, filterable where relevant, and covered by focused shared/server/UI tests. Related PR search: - No open duplicate PRs found for `external object references`. - Closed related prior attempt: #4556. ## What Changed - Added shared external-object contracts, validators, status/liveness helpers, and plugin protocol declarations. - Added database schema and additive migrations for external objects, source mentions, and display metadata. - Added server services/routes for detecting, syncing, summarizing, refreshing, and resolving external objects across issues, documents, comments, projects, and plugins. - Added a GitHub external-object provider plus plugin SDK authoring docs. - Wired UI presentation across markdown links, comments, issue chat, documents, properties, related work, issue rows, filters, inbox/sidebar badges, and Storybook stories. - Rebasing cleanup: moved the branch onto current `master`, repaired stale worktree provision config, hardened environment-sensitive tests/mocks, and removed committed screenshot artifacts from the PR branch to keep the reviewable file set below tool limits. ## Verification - `pnpm exec vitest run packages/shared/src/external-objects.test.ts server/src/__tests__/external-object-routes.test.ts server/src/__tests__/external-objects-service.test.ts ui/src/components/ExternalObjectPill.test.tsx ui/src/lib/external-objects.test.ts` passed after rebasing: 5 files, 56 tests. - Historical branch verification before this PR creation included `pnpm test:run`, `pnpm -r typecheck`, and `pnpm build`; this PR body does not claim those were rerun after the final rebase. ## Risks - Medium: this adds a new cross-surface sync path on issue/document/comment writes. The implementation uses safe sync wrappers so external-object failures warn instead of blocking core mutations. - Medium: the migrations introduce new tables and indexes. They are additive and company-scoped. - Medium: provider-specific URL parsing can miss or misclassify edge cases. Shared canonicalization tests and provider tests cover current GitHub shapes. - Low: UI badge/filter behavior could add visual noise for object-heavy issues; component tests and Storybook stories cover the intended surfaces. > Roadmap checked: `ROADMAP.md` references the plugin system as the current extension path and does not list a duplicate core feature. Related long-range docs discuss external references, work products, preview URLs, and plugin extension points; this PR implements the scoped external-object reference foundation. ## Model Used OpenAI Codex, GPT-5 coding-agent runtime, with shell and GitHub CLI tool use. Reasoning mode: medium. Exact deployed runtime model ID and context window were not exposed in the environment. ## 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> |
||
|
|
547463d3a2 |
refactor(environments): make execution environments instance-scoped (#8375)
## Thinking Path > - Paperclip is the control plane for AI-agent companies, so execution environment selection has to stay inspectable and predictable across companies, agents, and runs. > - The environment subsystem decides where an agent heartbeat actually runs and how remote sandbox state is realized and restored. > - That subsystem previously mixed company-scoped environment catalogs with issue-level environment stamping, so a reassigned issue could keep executing in the previous assignee's sandbox. > - That behavior breaks the control-plane contract: changing the assignee should change the executing agent/environment path unless there is an explicit current override. > - Fixing it cleanly required more than a narrow patch; the environment model had to move to instance scope with a single inherited default and per-agent override semantics. > - This pull request rewires the schema, server/API surface, runtime resolution, and UI around that model, then adds regression coverage for cross-company inheritance and per-agent isolation. > - The benefit is that environment choice now follows the approved instance/agent configuration path instead of stale issue state, while shared environments only need to be configured once per instance. ## Linked Issues or Issue Description - No directly matching public GitHub issue or PR was found while searching for this refactor. ### What happened? Reassigning work between agents with different execution environments could keep running in the previous sandbox because environment choice was stamped onto the issue and outranked the current assignee. The same subsystem also forced environment catalogs to be duplicated per company even though the underlying execution environments were instance-wide resources. ### Expected behavior Execution should resolve through the current instance and agent configuration path, with one instance-scoped environment catalog, one instance default, optional per-agent override, and no stale issue-level environment authority surviving reassignment. ### Steps to reproduce 1. Configure two agents to use different execution environments. 2. Assign an issue to the first agent so the issue records execution state in that environment. 3. Reassign the same issue to the second agent and run another heartbeat. 4. Observe that the pre-fix runtime can still sync or execute in the original sandbox instead of the second agent's environment. ### Paperclip version or commit Current `master` before this PR. ### Deployment mode Self-hosted server. ### Installation method Built from source (`pnpm dev` / `pnpm build`). ### Agent adapter(s) involved - Claude Code - Not adapter-specific (core bug in environment authority / resolution) ### Database mode External Postgres. ### Access context Both board reassignment and agent heartbeats were involved. ## What Changed - Moved environments and their default selection contract to instance scope in DB/shared types, including the migration that dedupes legacy per-company environments and seeds the instance local default. - Reworked environment CRUD/auth flows to use instance-scoped APIs and added route/service coverage for instance-level environment management. - Changed runtime resolution to prefer `agent default -> instance default -> built-in local`, removed issue-level environment stamping from the active execution path, and isolated sandbox/plugin leases by `(executionWorkspaceId, agentId)`. - Added environment env-var runtime precedence so environment-provided values act as the baseline for agent execution. - Moved the environment UI into instance settings and updated agent configuration surfaces to reflect inherit/override behavior. - Added regression coverage for instance-default inheritance across companies and for the new runtime resolution behavior. - Fixed a rebase-only duplicate `enableTaskWatchdogs` flag regression in instance settings types/validators/services so the branch typechecks cleanly on current `master`. - Updated stale server tests so CI matches the shipped instance-scoped environment contract. ## Verification - `git diff --check` - `pnpm --filter @paperclipai/shared typecheck` - `pnpm --filter @paperclipai/db typecheck` - `pnpm exec vitest run server/src/__tests__/environment-runtime-driver-contract.test.ts server/src/__tests__/agent-permissions-routes.test.ts server/src/__tests__/environment-routes.test.ts server/src/__tests__/environment-instance-routes.test.ts server/src/__tests__/execution-workspace-policy.test.ts server/src/__tests__/heartbeat-plugin-environment.test.ts server/src/__tests__/instance-settings-routes.test.ts` ## Risks - The migration changes environment scope and dedupes existing rows, so installs with unusual legacy environment combinations should be reviewed carefully during upgrade. - Remote execution behavior now depends on instance-default inheritance semantics instead of issue-level stamping, so any remaining code paths that still assume issue-scoped environment authority would surface as follow-up bugs. - This PR includes both server/runtime behavior and UI relocation, so reviewers should watch for authorization edge cases around instance settings and environment management. > I checked [`ROADMAP.md`](ROADMAP.md). This work fits the existing Cloud / Sandbox agents direction as a bug-fix/refactor to current behavior, not a new parallel product surface. ## Model Used - OpenAI Codex coding agent in this Paperclip/Codex session; GPT-5-class tool-using model with code execution and shell access. The exact backend model ID is not exposed to the session runtime. ## 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 - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
a71c4b6782 |
[codex] feat(watchdog): add task watchdog control plane (#8339)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The task lifecycle and recovery subsystems decide when agent work is still productive, stalled, or ready for review. > - Existing recovery paths can observe stopped or incomplete work, but there was no first-class per-task watchdog model with scoped review permissions. > - Watchdog follow-ups also need strict boundaries so recovery/status-only runs cannot mutate approvals or perform deliverable work. > - This pull request adds the task watchdog data model, API/service layer, scheduler/review flow, adapter wake context, UI configuration surfaces, and docs. > - The branch has been rebased onto current `paperclipai/paperclip` `master`; the watchdog migration is now ordered after master's latest migrations as `0104_issue_watchdogs`. > - The benefit is a more explicit task-review loop that preserves Paperclip's single-assignee and governance invariants while making stalled work easier to route. ## Linked Issues or Issue Description No linked GitHub issue. Paperclip task: [PAP-11275](/PAP/issues/PAP-11275). ## Problem or motivation Task recovery needs a first-class watchdog path that can inspect stopped work and create scoped follow-ups without bypassing normal task ownership. Board/UI users need a way to configure watchdogs on tasks and see watchdog-related live work. Recovery/status-only runs must remain limited to status reporting and must not create approvals, link approvals, or submit approval comments. ## Proposed solution Add a task-watchdog data model, scheduler/classifier, scoped mutation guard, adapter wake context, API/UI configuration surfaces, and documentation so watchdog agents can review stopped task subtrees under explicit boundaries. ## Alternatives considered Reuse the existing recovery-action flow only. That would keep stopped-work detection implicit, make per-task watchdog assignment harder to expose in the UI, and would not provide a durable scoped-review issue for stalled task trees. ## Roadmap alignment This is Paperclip control-plane lifecycle infrastructure for task execution and recovery. I checked `ROADMAP.md`; this PR does not duplicate an existing planned core item. ## What Changed - Added issue watchdog schema, migration, shared contracts, validators, CRUD API, and service support. - Added task watchdog scheduler/classifier behavior, scoped mutation enforcement, adapter wake context, and default watchdog mandate guidance. - Added UI surfaces for configuring watchdogs on new/existing tasks, viewing watchdog activity, and exposing the experimental setting. - Added docs for the user-facing task watchdog workflow and implementation semantics. - Gated new-task watchdog setup behind `enableTaskWatchdogs` and blocked cheap status-only recovery runs from approval mutations. - Rebased onto current `master` and renumbered the idempotent watchdog migration from the branch-local `0102_issue_watchdogs` slot to `0104_issue_watchdogs`. - Addressed Greptile feedback by loading watchdog classifier input with a recursive subtree query and centralizing the watchdog origin-kind constant. - Added and updated focused server/UI tests for watchdog routes, scheduler/classifier behavior, scope boundaries, live task visibility, settings, and new issue dialog behavior. ## Verification - `pnpm vitest run server/src/__tests__/task-watchdogs-scheduler.test.ts server/src/__tests__/task-watchdogs-classifier.test.ts` - `pnpm vitest run server/src/__tests__/approval-routes-idempotency.test.ts server/src/__tests__/issue-agent-mutation-ownership-routes.test.ts` - `pnpm vitest run ui/src/components/NewIssueDialog.test.tsx` - `pnpm --filter @paperclipai/server typecheck` - `git diff --check` - Verified the PR diff does not include `pnpm-lock.yaml` or `.github/workflows`. ## Risks - Medium risk: this introduces a new task lifecycle surface touching DB schema, server routes/services, adapter wake context, and UI task configuration. - Watchdog scheduling behavior depends on the new experimental setting and runtime context checks behaving consistently across local and production agents. - The watchdog migration is idempotent (`IF NOT EXISTS` / duplicate-object guards) so users who tried the previous branch-local migration number should not get duplicate-object failures. - CI and the second Greptile pass are pending after the latest review-fix push. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5-class coding agent in the Paperclip workspace. Exact runtime model id and context window were not exposed to the agent; tool use and local command execution were enabled. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots — N/A per Paperclip task instruction: do not add screenshots/images to this PR unless they are specifically part of the work. - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
fc95699fde |
fix(server): enforce agent secret binding sync across lifecycle flows (#8307)
## Thinking Path > - Paperclip is the control plane people use to create, configure, and run AI agents for work. > - This change sits in the server-side agent lifecycle and secret-binding subsystem, where adapter config `env` entries can reference company secrets. > - An incident (while trying to configure a Novita sandbox) showed that an agent can reach a broken runtime state if `adapterConfig.env` contains `secret_ref` entries but the matching `company_secret_bindings` rows are missing. > - The immediate run-path guard and error-surfacing work made the failure diagnosable, but they did not fully prevent new broken agents from being created. > - The risk came from create and approval flows being responsible for remembering to sync bindings at each call site, which is easy to miss as new flows are added. > - This pull request moves the invariant into `agentService` create/update/activate paths, keeps the existing hire-flow fix, and adds regression coverage for create, update, and legacy pending-approval recovery. > - The benefit is that agent secret binding integrity is enforced closer to the data mutation point, so future callers inherit the protection automatically. ## Linked Issues or Issue Description Refs #8309 ### What happened? A Paperclip agent could persist `adapterConfig.env` `secret_ref` entries without matching agent-scoped `company_secret_bindings` rows. When that happened, the config UI could still look configured, but the real run path failed pre-dispatch because the secret was not actually bound to that agent. ### Expected behavior Every normal agent create, config-update, and pending-approval activation flow should leave the agent with secret bindings that match its persisted secret-ref env config. ### Steps to reproduce 1. Create or activate an agent through a flow that persists `adapterConfig.env` secret refs without synchronizing `company_secret_bindings`. 2. Observe that the config state can still appear populated. 3. Start a run for that agent. 4. Observe that pre-dispatch binding validation fails because the secret reference exists but the agent binding does not. ### Deployment mode Local dev (`pnpm dev`) ### Installation method Built from source (`pnpm dev` / `pnpm build`) ### Agent adapter(s) involved - Claude Code - Not adapter-specific (core bug) ### Database mode Embedded PGlite / embedded local dev database flow ### Access context Board (human operator) created or approved the agent; agent runtime later consumed the config. ### Additional context This PR focuses on preventing new broken states from normal service flows and on backfilling the covered legacy pending-approval activation path. ## What Changed - Kept the existing branch-local hire-flow fix that synchronized bindings for route and approval paths. - Moved the binding integrity invariant into `agentService.create()`, `agentService.update()` when `adapterConfig` changes, and `agentService.activatePendingApproval()`. - Added `server/src/__tests__/agents-service-secret-bindings.test.ts` covering create-time sync, update-time resync, and backfill for legacy pending-approval agents. - Removed now-redundant route-layer and approval-layer binding sync calls once the service layer became authoritative. - Simplified the affected unit tests so route/approval tests no longer assert service-owned binding writes directly. ## Verification - `pnpm --filter @paperclipai/server typecheck` - `pnpm exec vitest run server/src/__tests__/agents-service-secret-bindings.test.ts server/src/__tests__/approvals-service.test.ts server/src/__tests__/agent-skills-routes.test.ts` ## Risks - Low to medium risk. - This changes where secret-binding synchronization is enforced, so any unexpected caller that relied on upper-layer manual sync behavior could behave differently. - Agent create/update/activation flows now perform binding synchronization consistently, which adds binding-table writes at those mutation points. - This PR does not retroactively scan and heal every already-broken historical agent row; it prevents and backfills through the covered service flows. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex / GPT-5 Codex class model via `codex_local` - Session model family: GPT-5 Codex - Tool-assisted coding with shell, git, HTTP, and local test execution - Reasoning mode: medium interactive tool-use workflow ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [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> |
||
|
|
5c11725784 |
build(deps-dev): bump tsx from 4.21.0 to 4.22.4 (#7754)
Bumps [tsx](https://github.com/privatenumber/tsx) from 4.21.0 to 4.22.4. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/privatenumber/tsx/releases">tsx's releases</a>.</em></p> <blockquote> <h2>v4.22.4</h2> <h2><a href="https://github.com/privatenumber/tsx/compare/v4.22.3...v4.22.4">4.22.4</a> (2026-05-31)</h2> <h3>Bug Fixes</h3> <ul> <li>resolve CommonJS directory requires inside dependencies (<a href="https://redirect.github.com/privatenumber/tsx/issues/803">#803</a>) (<a href="https://github.com/privatenumber/tsx/commit/1ce846335b7c445a3328c7d27f06424949356d97">1ce8463</a>)</li> </ul> <hr /> <p>This release is also available on:</p> <ul> <li><a href="https://www.npmjs.com/package/tsx/v/4.22.4"><code>npm package (@latest dist-tag)</code></a></li> </ul> <h2>v4.22.3</h2> <h2><a href="https://github.com/privatenumber/tsx/compare/v4.22.2...v4.22.3">4.22.3</a> (2026-05-19)</h2> <h3>Bug Fixes</h3> <ul> <li>decode typed loader source (<a href="https://github.com/privatenumber/tsx/commit/dce02fc3b8b64a58d24560714902b16f89332f1f">dce02fc</a>)</li> <li>preserve entrypoint with TypeScript preload hooks (<a href="https://github.com/privatenumber/tsx/commit/68f72f3304d8c3ff7048bde8571af9c163fcefa2">68f72f3</a>)</li> </ul> <hr /> <p>This release is also available on:</p> <ul> <li><a href="https://www.npmjs.com/package/tsx/v/4.22.3"><code>npm package (@latest dist-tag)</code></a></li> </ul> <h2>v4.22.2</h2> <h2><a href="https://github.com/privatenumber/tsx/compare/v4.22.1...v4.22.2">4.22.2</a> (2026-05-18)</h2> <h3>Bug Fixes</h3> <ul> <li>preserve CJS JSON require in ESM hooks (<a href="https://github.com/privatenumber/tsx/commit/35b700bd8620696df03827068af29dcd0d091a60">35b700b</a>)</li> <li>preserve named exports from CommonJS TypeScript (<a href="https://github.com/privatenumber/tsx/commit/11de737dae1fb9dae28db3716df5b1a7e1a6a089">11de737</a>)</li> <li>support module.exports require(esm) interop (<a href="https://github.com/privatenumber/tsx/commit/cf8f19918e4e0a0dc5ee5c52d8cc15e5e22d7c49">cf8f199</a>)</li> </ul> <hr /> <p>This release is also available on:</p> <ul> <li><a href="https://www.npmjs.com/package/tsx/v/4.22.2"><code>npm package (@latest dist-tag)</code></a></li> </ul> <h2>v4.22.1</h2> <h2><a href="https://github.com/privatenumber/tsx/compare/v4.22.0...v4.22.1">4.22.1</a> (2026-05-17)</h2> <h3>Bug Fixes</h3> <ul> <li>resolve tsconfig path aliases containing a colon (<a href="https://redirect.github.com/privatenumber/tsx/issues/780">#780</a>) (<a href="https://github.com/privatenumber/tsx/commit/6979f28810829dc79ec9baf406e162a18b65ab4b">6979f28</a>)</li> </ul> <hr /> <p>This release is also available on:</p> <ul> <li><a href="https://www.npmjs.com/package/tsx/v/4.22.1"><code>npm package (@latest dist-tag)</code></a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/privatenumber/tsx/commit/1ce846335b7c445a3328c7d27f06424949356d97"><code>1ce8463</code></a> fix: resolve CommonJS directory requires inside dependencies (<a href="https://redirect.github.com/privatenumber/tsx/issues/803">#803</a>)</li> <li><a href="https://github.com/privatenumber/tsx/commit/dce02fc3b8b64a58d24560714902b16f89332f1f"><code>dce02fc</code></a> fix: decode typed loader source</li> <li><a href="https://github.com/privatenumber/tsx/commit/68f72f3304d8c3ff7048bde8571af9c163fcefa2"><code>68f72f3</code></a> fix: preserve entrypoint with TypeScript preload hooks</li> <li><a href="https://github.com/privatenumber/tsx/commit/69455cfefbfe71100a3c58d3ce7cea42445d9113"><code>69455cf</code></a> test: cover package exports for ambiguous ESM reexports</li> <li><a href="https://github.com/privatenumber/tsx/commit/35b700bd8620696df03827068af29dcd0d091a60"><code>35b700b</code></a> fix: preserve CJS JSON require in ESM hooks</li> <li><a href="https://github.com/privatenumber/tsx/commit/ef807dba6832260fb4cafd78d81f5469a733966b"><code>ef807db</code></a> chore: update testing dependencies</li> <li><a href="https://github.com/privatenumber/tsx/commit/3917090d4f61863ea6ea16e4a9a3722a112cc3f7"><code>3917090</code></a> test: document compatibility test taxonomy</li> <li><a href="https://github.com/privatenumber/tsx/commit/de8113ffa8edbcd4e05fa218324c3e8c2a4afdbe"><code>de8113f</code></a> refactor: centralize Node capability facts</li> <li><a href="https://github.com/privatenumber/tsx/commit/c1f62db45ada60b24ceb3dfdf7f64173d9a15396"><code>c1f62db</code></a> test: consolidate tsconfig path edge coverage</li> <li><a href="https://github.com/privatenumber/tsx/commit/4e08174ec10276ac71c9a69eb28426ad702d0c76"><code>4e08174</code></a> test: consolidate loader hook coverage</li> <li>Additional commits viewable in <a href="https://github.com/privatenumber/tsx/compare/v4.21.0...v4.22.4">compare view</a></li> </ul> </details> <details> <summary>Maintainer changes</summary> <p>This version was pushed to npm by <a href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new releaser for tsx since your current version.</p> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
6f142a60ce |
build(deps-dev): bump @types/node from 22.19.11 to 22.19.21 (#7748)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.19.11 to 22.19.21. <details> <summary>Commits</summary> <ul> <li>See full diff in <a href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
f3e01c63bd |
fix(environments): partial unique index to dedup managed sandbox rows (#8247)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work.
> - The `server/services/environments.ts` module lazily provisions a
managed Kubernetes sandbox environment for each company on first
heartbeat. Idempotency relies on `ensureKubernetesEnvironment` returning
the single managed row per company.
> - The `(company_id, driver)` unique index in the `environments` schema
is partial on `driver='local'` only, so two concurrent callers (e.g.
simultaneous first heartbeats from a freshly synced tenant) can both
insert a `driver='sandbox'` row before either sees the other.
> - The function tried to converge after the race by re-reading, picking
the oldest managed row as winner, and deleting the loser. Under
autocommit + read-committed, each post-insert SELECT is a fresh snapshot
— A may not see B's row, B may not see A's, so both pick their own and
neither deletes. Two rows survive.
> - The same race fired in CI as `expected 2 to be 1` at
`environment-service.test.ts:293`, gating multiple unrelated PRs on
retries.
> - This pull request encodes the operator-level invariant ("at most one
Paperclip-managed sandbox row per company") at the DB layer with a
partial unique index, then switches `ensureKubernetesEnvironment` to
`INSERT … ON CONFLICT DO NOTHING` keyed on that index. Losers re-read
the surviving row.
> - The benefit is the race is impossible by construction — no
application-side convergence loop, no test flake, and any future
`ensureXyzSandboxEnvironment` that sets `managedByPaperclip=true`
inherits the invariant for free.
## Linked Issues or Issue Description
Paperclip issue: PAPA-783 — implement managed-sandbox dedup fix (phase 2
of the approved plan on the parent flake-investigation issue).
This is the phase-2 fix for the flaky `environmentService > deduplicates
concurrent managed Kubernetes environment creation` test introduced by
`4ad94d0bd` (PR #7938). Failing CI runs since then on at least PRs
#7595, #8233, #8215, #8212. The plan was reviewed and approved on the
parent issue before implementation.
Closely related (not duplicates):
- PR #7938 — introduced the test and the in-process convergence loop
being replaced here.
- PR #7595, PR #8233, PR #8215, PR #8212 — downstream PRs affected by
the flake; one of them will be rebased onto this fix as the acceptance
gate.
## What Changed
- `packages/db/src/schema/environments.ts`: added
`environments_company_managed_sandbox_idx`, a partial unique index on
`(company_id) WHERE driver='sandbox' AND
(metadata->>'managedByPaperclip')::boolean = true`. The umbrella
`managedByPaperclip` predicate covers any current or future
Paperclip-managed sandbox flavor without needing a new index per
provider.
- `packages/db/src/migrations/0102_managed_sandbox_dedup_index.sql`:
one-shot dedup `DELETE` keeping the oldest managed-sandbox row per
`company_id` (scoped to `driver='sandbox' AND managedByPaperclip=true`),
`RAISE NOTICE` if any duplicates were removed, then `CREATE UNIQUE INDEX
IF NOT EXISTS environments_company_managed_sandbox_idx`. `CONCURRENTLY`
is omitted because the codebase's migration runner wraps each file in a
transaction (see `applyPendingMigrationsManually`); the table holds 1–3
rows per company, so the short lock is acceptable and consistent with
every other migration in the repo.
- `server/src/services/environments.ts`: `ensureKubernetesEnvironment`
now uses `INSERT … ON CONFLICT DO NOTHING` keyed on the new index. On
conflict it re-reads the surviving managed-sandbox row and returns it.
Drops the post-insert convergence (re-read by `createdAt ASC, id ASC`,
delete the loser) and the trailing comment that flagged "until a partial
unique index is added via migration" as the proper long-term fix.
- Unused `asc` import removed from
`server/src/services/environments.ts`.
## Verification
Local (matches the success criteria in the issue body):
```
$ cd server
$ passes=0; for i in $(seq 1 20); do
pnpm vitest run src/__tests__/environment-service.test.ts -t "deduplicates concurrent" \
&& passes=$((passes+1)) || break
done; echo "$passes/20"
20/20
$ passes=0; for i in $(seq 1 10); do
pnpm vitest run src/__tests__/environment-service.test.ts \
&& passes=$((passes+1)) || break
done; echo "$passes/10"
10/10
```
Adversarial fan-out stress (temporarily bumped `Array.from({ length: 8
}, …)` to `length: 32` on both dedup tests; reverted before commit):
```
$ # both dedup tests fan-out-of-32, 10 iterations
10/10
```
Two ensure paths exist in the parent plan, but only
`ensureKubernetesEnvironment` is on `master`.
`ensureManagedSandboxEnvironment` (referenced by the approved plan as
commit `dce9a9622`) lives only on an unmerged feature branch, not
master. The plan's helper-extraction and symmetric dedup test for that
path are deferred to whichever PR lands the second ensure path — it
inherits the same DB invariant by setting `managedByPaperclip=true`.
Discrepancy was flagged on the issue thread before implementation.
Typecheck:
```
$ pnpm -C server typecheck
ok
```
## Risks
Low risk.
- **Migration safety.** `IF NOT EXISTS` on the index makes the migration
idempotent. The dedup `DELETE` is bounded to rows matching the
managed-sandbox predicate; in production this should be a no-op (no race
has been reported in the wild — only in CI). On dev/CI DBs that already
accumulated duplicates, the migration emits a `NOTICE` reporting the
count.
- **No `CONCURRENTLY`.** The migration runner wraps each `.sql` file in
a transaction, which is incompatible with `CREATE INDEX CONCURRENTLY`.
The `environments` table holds 1–3 rows per company and the row count is
bounded by company count; the short ACCESS EXCLUSIVE during `CREATE
UNIQUE INDEX` is acceptable here and matches every other index migration
in the repo.
- **Predicate scope.** The partial index predicate matches exactly the
rows that `ensureKubernetesEnvironment` writes (`driver='sandbox'` with
`metadata.managedByPaperclip=true`). Tenant-created sandbox envs (via
`svc.create`) do not set this marker and are not covered — no false
positives, no surprise constraint violations on unrelated inserts.
## Model Used
Claude (Anthropic), `claude-opus-4-7`. Tool use: code edit + bash +
filesystem search; no extended-thinking mode.
## 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 run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [ ] I will address all Greptile and reviewer comments before
requesting merge
Co-authored-by: Paperclip <noreply@paperclip.ing>
|
||
|
|
05bcd3ce84 |
feat(security): plugin tables get company_id FK for tenant isolation (#5865)
## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - The plugin subsystem persists state into four tables (`plugin_entities`, `plugin_job_runs`, `plugin_logs`, `plugin_webhook_deliveries`) and those rows currently have no notion of an owning tenant — so company-deletion doesn't cascade plugin state, and operators have no way to query "what does this plugin own for company X?" > - The fix is one thin slice of tenant-isolation hygiene that doesn't change any external API: add a nullable `company_id` FK with `ON DELETE CASCADE` to the four plugin tables, index it, and scope the `plugin_entities` external-id uniqueness per-tenant > - The benefit is plugin-row tenant attribution + cascade cleanup, with zero impact on single-tenant local-first deploys (`NULL` continues to mean instance-scope) > **Rebase note (scope narrowed):** This PR originally also hardened the schedulers (`heartbeat.tickTimers` / `resumeQueuedRuns` / `enqueueWakeup` and `routines.tickScheduledTriggers`) to skip archived companies. That half has since landed on `master` via #7478 (`93206f73`, "Stop archived companies from waking agents") with a stricter implementation (`status != 'active'` plus a skipped-request audit row). On rebase those changes were dropped as redundant — `heartbeat.ts` and `routines.ts` are now identical to `master`, and the scheduler-specific tests were removed. **This PR is now DB-only.** ## Linked Issues or Issue Description No existing issue covers this directly — problem described in-PR: - Four plugin tables (`plugin_entities`, `plugin_job_runs`, `plugin_logs`, `plugin_webhook_deliveries`) persist rows with no notion of an owning tenant. - Company deletion therefore does not cascade plugin state, and operators have no way to query "what does this plugin own for company X?" - One thin slice of tenant-isolation hygiene fixes this without changing any external API: a nullable `company_id` FK with `ON DELETE CASCADE`, an index, and per-tenant scoping of the `plugin_entities` external-id uniqueness. - Part of the multi-tenant hardening initiative alongside #3967 (cross-tenant 404 oracle) and #5864 (per-company JWT keys). ## What Changed **Schema (`packages/db/src/schema/plugin_*.ts`):** - Nullable `companyId` FK with `onDelete: "cascade"` added to `plugin_entities`, `plugin_job_runs`, `plugin_logs`, `plugin_webhook_deliveries`. - A btree index on each new `company_id` column (`<table>_company_idx`). - `plugin_entities_external_idx` rescoped from `(plugin_id, entity_type, external_id)` to `(company_id, plugin_id, entity_type, external_id)` and switched to `UNIQUE … NULLS NOT DISTINCT` so instance-scope rows (`company_id IS NULL`) keep their dedup guarantee while tenants get their own namespace. **Migration:** - `0095_plugin_company_id_tenant_isolation.sql` — 14 statements: 4 column adds + 4 FK constraints (`ON DELETE CASCADE`) + 4 indexes + drop/recreate of the external-id unique constraint. - Journal entry + regenerated `0095_snapshot.json`. **Tests:** - `server/src/__tests__/plugin-tenant-isolation.test.ts` — `NULL` preserves backward compat; `CASCADE` on company delete across all four tables; per-tenant external-id namespacing; NULL-NULL collision rejected (`NULLS NOT DISTINCT`). ## Verification - `pnpm --filter @paperclipai/db run check:migrations` — pass. - `pnpm --filter @paperclipai/db typecheck` (`tsc`) — pass. - `vitest run plugin-tenant-isolation` — **4/4 pass** (embedded Postgres applies `0095` and exercises cascade + NULLS NOT DISTINCT). ## Notes - **Clean snapshot, no drift.** The earlier revision of this PR shipped a ~17.6k-line meta snapshot that was almost entirely pre-existing drift. On rebase the migration was renumbered (the old `0090_brainy_darkhawk` collided with `master`'s `0090_resource_memberships … 0094`) and regenerated from the current `master` baseline via `drizzle-kit generate`. The result is a 14-statement migration containing **only** the plugin-table changes — no unrelated drift. - **Backward-compatible.** `NULL company_id` continues to mean instance-scope (cron jobs, public webhooks). No new env vars, no API surface change. Single-tenant local-first deploys unaffected. ## Risks - **Migration is additive and nullable** — `0095` adds nullable `company_id` columns, FK constraints, and indexes; existing rows stay valid (`NULL` keeps meaning instance-scope) and no backfill is required. - **`ON DELETE CASCADE` is a behavioral change**: deleting a company now removes its plugin rows across all four tables. Intended (it is the point of the PR), but operators relying on plugin rows surviving company deletion would be affected. Covered by the cascade tests. - **Uniqueness semantics change on `plugin_entities`**: the external-id constraint is rescoped per-tenant and switched to `UNIQUE … NULLS NOT DISTINCT`, so two instance-scope rows (`company_id IS NULL`) with the same external id are now rejected instead of coexisting. Covered by the NULL-NULL collision test. - **No API surface change, no new env vars.** Single-tenant local-first deploys unaffected. (Section added retroactively to match the PR template; distilled from the What Changed / Notes sections above.) ## Model Used Same authoring setup as #5864 (same series, same day): Claude Opus 4.7 (1M context), extended thinking mode. (Section added retroactively.) ## Checklist - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] Tests run locally and pass (plugin-tenant-isolation 4/4) - [x] `check:migrations` + db typecheck pass - [x] No UI changes - [x] Migration carries only the intended changes (no snapshot drift) - [x] Scheduler half dropped as superseded by #7478 Part of the multi-tenant hardening initiative — see also #3967 (cross-tenant 404 oracle) and #5864 (per-company JWT keys). --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Devin Foley <devin@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
1413729a06 |
Build the Skills Store (#7990)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents increasingly depend on reusable skills, so the control plane needs a first-class way to browse, inspect, install, version, and attach those skills. > - The old skills surface was mostly operational plumbing; it did not give operators a store-like discovery flow, canonical detail URLs, rich source/version context, or creation paths. > - The backend also needed stronger contracts around company skill metadata, versions, install counts, runtime materialization, and adapter skill preferences. > - This pull request builds the Skills Store foundation across DB, shared contracts, server routes/services, UI, and Storybook. > - The benefit is a more inspectable, operator-friendly skill workflow that still preserves company-scoped control-plane boundaries and agent runtime behavior. ## Linked Issues or Issue Description No GitHub issue exists for this Paperclip work item. Paperclip task refs: PAP-10846 and PAP-10921. Feature request: Paperclip operators need a single Skills Store experience where company skills can be discovered, inspected, created, versioned, installed, and attached to agents without relying on scattered operational screens or implicit runtime state. Related PR search: - Searched GitHub for `Skills Store`, `company skills`, and `skill detail`. - Found several open skills-related PRs such as #7809 and #4409, but no duplicate PR for this end-to-end Skills Store branch. ## What Changed - Added the Skills Store backend foundation: company skill schema fields, migrations, shared types/validators, and expanded server skill routes/services. - Added skill discovery, category navigation, canonical skill detail routes, tabs, source attribution, version snapshots/diffs, install count backfill, and creation flows. - Updated agent skill preference handling so version selections survive runtime mention injection and runtime skill materialization honors pinned versions. - Preserved unversioned skill assignments as live/current selections instead of silently pinning them to the current version at assignment time. - Added focused regression coverage for company skill routes/services, route helpers, UI behavior, skill version diffs, and runtime skill version pins. - Added Storybook coverage for Skills Store discovery/detail states and updated the main layout navigation. - Addressed Greptile findings around version creation races, soft-deleted comments, fork metadata scoping, GitHub skill directory fallback, runtime snapshot materialization, shared runtime skill-selection helpers, and version-assignment semantics. ## Verification - `pnpm exec vitest run server/src/__tests__/heartbeat-project-env.test.ts server/src/__tests__/heartbeat-runtime-skills.test.ts` - `pnpm exec vitest run packages/shared/src/validators/company-skill.test.ts` - `pnpm exec vitest run server/src/__tests__/company-portability.test.ts server/src/__tests__/company-skills-service.test.ts` - `pnpm exec vitest run cli/src/__tests__/company-import-export-e2e.test.ts` - `pnpm exec vitest run server/src/__tests__/agent-skills-routes.test.ts` - `pnpm exec vitest run server/src/__tests__/openapi-routes.test.ts` - `pnpm exec vitest run server/src/__tests__/company-skills-service.test.ts server/src/__tests__/company-skills-routes.test.ts server/src/__tests__/heartbeat-runtime-skills.test.ts` - `pnpm exec vitest run server/src/__tests__/company-skills-service.test.ts` - `pnpm exec vitest run ui/src/components/IssueProperties.test.tsx -t "edits existing custom assignee model options from the properties pane"` - `pnpm --filter @paperclipai/server typecheck` - GitHub checks are green on `0823957a2`: Build, Canary Dry Run, General tests, Typecheck + Release Registry, serialized server suites, e2e, policy/review, Socket, Snyk, and aggregate `verify`. - Greptile Review succeeded on `0823957a2` with `40 files reviewed, 0 comments added`; GitHub unresolved review threads: 0. Not run in this heartbeat: - Browser screenshot capture for the UI changes. This PR intentionally omits screenshots per the Paperclip task direction not to add design screenshots/images. ## Risks - Broad feature branch touching DB, shared contracts, server, and UI; reviewers should still scan merge conflicts carefully if `master` moves again before landing. - Skill version/runtime behavior is sensitive: pinned skill versions must stay pinned while default selections should continue following the current version. - UI polish should get normal reviewer/browser attention before merge because this PR includes a large Skills Store surface and screenshots were intentionally omitted. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5-based coding agent with tool use and local command execution. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots (intentionally omitted per PAP-10921 direction) - [ ] 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
8ee3987d12 |
adapter-claude-local: recover from poisoned previous_message_id 400 (detect + clearSession) (#5972)
## Thinking Path
> - Paperclip's `claude_local` adapter persists Claude Code session
jsonls under `~/.claude/projects/…/{sessionId}.jsonl` and resumes them
on the next heartbeat
> - When Claude Code injects `<synthetic>` placeholder assistant
messages (after rate-limit, max-turn exhaustion, or transient-upstream
failures) those placeholders get UUID-format `message.id`s rather than
`msg_…`-format ids
> - On the next `--resume`, Claude Code passes that UUID as
`previous_message_id` and Anthropic's API rejects it with a 400:
``diagnostics.previous_message_id: must be the `id` from a prior
/v1/messages response (starts with `msg_`)``
> - The adapter had a session-rotation fallback only for "unknown
session" errors, so the poisoned session was `--resume`-d indefinitely
and the agent flipped between `idle` and `error` every heartbeat
> - Even worse, the *result* event of the failing run still carried a
`session_id`, and the adapter was persisting that id into the
issue-scoped session store (`agentTaskSessions`). So even after we
detected the 400, every subsequent continuation re-loaded the same
poisoned id and hit the same 400 again — the issue was permanently
stranded
> - We observed this on multiple agents in our deployment; the only
manual fix was to rename the `.jsonl`, which is not a viable long-term
workaround
> - This PR detects the 400, runs the same session-rotation fallback the
unknown-session path uses **and** stops persisting the poisoned id, so
the next attempt starts genuinely fresh
## Linked Issues or Issue Description
No external GitHub issue is linked. Describing the problem inline
following the bug-report template:
**What happened:** `claude_local` agents flipped between `idle` and
`error` on every heartbeat because the persisted session jsonl carried a
synthetic UUID `previous_message_id` (from `<synthetic>` assistant
placeholders injected after rate-limit/max-turn/upstream errors).
Anthropic's API rejected every `--resume` with a 400:
``diagnostics.previous_message_id: must be the `id` from a prior
/v1/messages response (starts with `msg_`)``.
**Expected behavior:** When the persisted session is poisoned and
unrecoverable, the adapter should rotate to a fresh session — the same
fallback path already used for unknown-session errors — and stop
re-persisting the poisoned `session_id`.
**Actual behavior:** The session-rotation fallback only matched the
"unknown session" pattern, so the poisoned session was `--resume`-d
forever. The result event of the failing run still carried `session_id`,
which was being persisted into `agentTaskSessions`, so every subsequent
continuation reloaded the same poisoned id and hit the same 400.
**Reproduction:** Inject any flow that causes Claude Code to emit a
`<synthetic>` placeholder (rate-limit, max-turn exhaustion, transient
upstream failure). The next `--resume` will fail with the 400 and the
agent will not self-recover.
**Scope of fix:** Add a `previous_message_id` 400 detector; route it
through the existing unknown-session fallback; drop the poisoned
`sessionId` and emit `clearSession: true` so the heartbeat service wipes
the persisted row; best-effort delete the local poisoned `.jsonl`.
## What Changed
Two commits:
1. **`adapter-claude-local: auto-rotate session on previous_message_id
400 (synthetic-msg poisoning)`** — detector + execute-time rotation
2. **`adapter-claude-local: guard against persisting poisoned
sessionId`** — validate-before-persist + `clearSession`
Combined diff:
- `parse.ts`: new `isClaudePoisonedPreviousMessageIdError(parsed)`
matching ``/diagnostics\.previous_message_id.*starts with `msg_`/i``
against `parsed.result` and `extractClaudeErrorMessages(parsed)`
- `parse.ts`: `isClaudeTransientUpstreamError()` excludes the new error
from transient classification so it isn't masked as retryable upstream
noise
- `execute.ts`: expand the resume-fallback branch so it triggers on both
`isClaudeUnknownSessionError` and the new
`isClaudePoisonedPreviousMessageIdError`, with a distinct log line
(`"returned a poisoned message-id"` vs `"is unavailable"`)
- `execute.ts`: for local (non-remote) execution targets, best-effort
delete the poisoned `~/.claude/projects/.../{sessionId}.jsonl` before
retrying so the file can't be accidentally resumed by an out-of-band
caller. The `fs.unlink` and follow-up log call are in separate try/catch
blocks so a closed log stream cannot mask a successful unlink (and vice
versa)
- `execute.ts` / `toAdapterResult`: when a result carries the poisoned
400, **drop** `sessionId`/`sessionParams`/`sessionDisplayId` (return
`null`) and emit `clearSession: true` so the heartbeat service's
`resolveNextSessionState` wipes the persisted row. The result also
surfaces `errorCode: "claude_poisoned_previous_message_id"` for
observability
- `docs/adapters/claude-local.md`: runbook entry — symptom,
auto-recovery flow, on-call checklist
- Tests:
- 4 new `parse.test.ts` cases covering positive detection in `result`
and `errors[]`, negative cases, and non-transient classification
- 3 new `claude-local-execute.test.ts` cases: (a) fresh run reports the
poisoned error → sessionId dropped + `clearSession: true`; (b) recovery
retry also reports the poisoned error → same guards apply; (c)
session-rotation success on retry
## Verification
```bash
pnpm --filter @paperclipai/adapter-claude-local exec vitest run src/server/parse.test.ts
pnpm --filter @paperclipai/server exec vitest run src/__tests__/claude-local-execute.test.ts
```
Both suites green locally. This patch is also currently running as a
hot-patch over the published `2026.513.0` adapter on the reporting
deployment — sessions that previously looped indefinitely now
self-recover on the first heartbeat after the 400 surfaces.
## Risks
- Low risk. The detector is conservative (regex over `result` +
`errors[]` only) and the rotation reuses the existing unknown-session
fallback path
- The local-only `fs.unlink` of the poisoned `.jsonl` is wrapped in
`try/catch` and ignored on failure — strictly an optimization; the
server-side session clear is the authoritative reset
- Remote execution targets (`executionTargetIsRemote`) skip the disk
cleanup because the file lives on a remote host that we can't safely
reach from the adapter
- The `clearSession: true` + nulled session fields path is a no-op on
healthy runs; it only fires when the new detector matches, so existing
successful continuations are unaffected
- No DB schema changes, no public API changes, no new dependencies
## Model Used
- Provider: Anthropic Claude
- Model: `claude-opus-4-7` (Opus 4.7)
- Context window: 1M
- Capabilities: extended reasoning, tool use, code execution
- Role: implemented the detector, expanded the fallback branch, added
the persist-guard + `clearSession`, wrote the unit + integration tests,
validated locally, and applied the equivalent hot-patch to the deployed
`2026.513.0` install while this PR is in review
## 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 similar or duplicate PRs and linked
them — closed #2295, #2361, #3572, #5438 as duplicates of this canonical
fix; complementary fixes #4838 (heartbeat_timer reset) and #4932 (gemini
context-overflow rotation) target different code paths
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots — N/A, adapter-only change
- [x] I have updated relevant documentation
(`docs/adapters/claude-local.md` runbook entry)
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Danial Jawaid <danial.jawaid@gmail.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Devin Foley <devin@paperclip.ing>
|
||
|
|
e0bf19fe1c |
build(deps-dev): bump drizzle-kit from 0.31.9 to 0.31.10 (#7572)
Bumps [drizzle-kit](https://github.com/drizzle-team/drizzle-orm) from 0.31.9 to 0.31.10. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/drizzle-team/drizzle-orm/releases">drizzle-kit's releases</a>.</em></p> <blockquote> <h2>drizzle-kit@0.31.10</h2> <ul> <li>Updated to <code>hanji@0.0.8</code> - native bun <code>stringWidth</code>, <code>stripANSI</code> support, errors for non-TTY environments</li> <li>We've migrated away from <code>esbuild-register</code> to <code>tsx</code> loader, it will now allow to use <code>drizzle-kit</code> seamlessly with both <code>ESM</code> and <code>CJS</code> modules</li> <li>We've also added native <code>Bun</code> and <code>Deno</code> launch support, which will not trigger <code>tsx</code> loader and utilise native <code>bun</code> and <code>deno</code> imports capabilities and faster startup times</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/drizzle-team/drizzle-orm/commit/4aa6ecfee4b4728dadf6f77f071a149878a3c6c0"><code>4aa6ecf</code></a> Kit updates (<a href="https://redirect.github.com/drizzle-team/drizzle-orm/issues/5490">#5490</a>)</li> <li>See full diff in <a href="https://github.com/drizzle-team/drizzle-orm/compare/drizzle-kit@0.31.9...drizzle-kit@0.31.10">compare view</a></li> </ul> </details> <br /> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
eaef47f4c7 |
Information Architecture + project/agent visual refresh (experimental) (#7543)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The board UI is the control surface for issues, projects, agents, goals, workspaces, and operator settings. > - The existing navigation and list surfaces make several high-frequency workflows feel harder to scan than they should, especially around projects and agents. > - The product direction is to improve those surfaces without breaking the existing route model or forcing a new IA on every operator at once. > - This pull request now keeps the dependent IA, project identity, and agent-list visual refresh work together while the Issue-to-Task copy migration is split into #7651. > - The benefit is a clearer left nav, better project identity, denser agent/project list rows, and brand-aligned status treatment while preserving the classic default experience behind a flag. ## Linked Issues or Issue Description Refs #7645 Refs #7651 Internal planning/work references: PAP-53, PAP-56, PAP-58, PAP-59, PAP-60, PAP-61, PAP-68, PAP-69, PAP-70, PAP-71, PAP-72, PAP-75, PAP-76, PAP-80, PAP-85, PAP-86, PAP-87, PAP-88, PAP-89. ## What Changed - Adds `enableStreamlinedLeftNavigation`, defaulting off, and gates sidebar presentation so classic navigation remains the default. - Adds project icon persistence, validation, portability, picker UI, and `ProjectTile` rendering while defaulting new projects to neutral gray. - Adds projects-list task-count and budget summary data with focused server/shared/UI coverage. - Refreshes agent list rows, row actions, active/recent sidebar behavior, and status capsule/chip styling for the approved brand state system. - Removes the placeholder Conference room and Artifacts nav/routes from the finalized experimental nav direction. - Removes `pnpm-lock.yaml` and the Issue-to-Task copy migration from this PR diff; the copy migration now lives in #7651. ## Verification - Existing branch verification from the authored commits: UI typecheck, targeted unit tests, and light/dark visual checks for `/agents`, agent detail, and design-guide status states. - Maintainer cleanup verification on `75e34e5`: `git diff --check origin/master...HEAD` passed, the `design/` diff is empty, and the PR diff is 61 files, below Greptile's 100-file review limit. - `pnpm --filter @paperclipai/ui build` passed. - `NODE_ENV=test pnpm exec vitest run ui/src/components/Sidebar.test.tsx` passed: 1 file, 8 tests. - CI and Greptile should rerun on the latest push. ## Risks - Broad UI surface area: the experimental flag keeps the classic nav default, but changed shared components such as `EntityRow`, `ProjectTile`, and agent status badges could affect multiple pages. - Database migration: `projects.icon` is additive and nullable, but migration ordering and portability import/export must stay aligned. - The Issue-to-Task copy migration is now separated into #7651, so reviewers should evaluate this PR as IA/project/agent presentation work only. - Visual regressions are possible across smaller widths because the PR intentionally changes dense list-row layouts. ## Model Used Claude Opus 4.8 assisted the original feature commits. Paperclip-Paperclip agents assisted some planning/design commits. Codex / GPT-5-class coding agent with shell, GitHub CLI, and repository access performed this PR-readiness cleanup and split. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Dotta <bippadotta@protonmail.com> |
||
|
|
20aea356cc |
refactor(deps-dev): bump vitest from 3.2.4 to 4.1.8 (#7581)
## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Test infrastructure across server, ui, packages/* runs on Vitest > - Dependabot opened a narrow bump (3.2.4 → 3.2.6), but the wider workspace is on 3.2.4 and the major-version bridge to v4 needs a coordinated change set across configs and tests > - Staying on 3.x indefinitely leaves us behind on Vitest 4 (perf, pool, and config improvements) and forces repeated patch-only dependabot churn > - This pull request upgrades Vitest to 4.1.8 across the workspace, updates `server/vitest.config.ts` and `scripts/run-vitest-stable.mjs` for the new API, and adjusts two UI tests for the new assertion semantics > - The benefit is a single, coherent Vitest 4 upgrade that supersedes #7570 and gets us on the supported major line ## What Changed - Bump `vitest` from `3.2.4` to `4.1.8` across root, `server`, `ui`, and all `packages/*` (including plugin examples and sandbox providers) - Update `server/vitest.config.ts` for Vitest 4 config surface - Update `scripts/run-vitest-stable.mjs` to match the new runner behavior - Adjust `ui/src/components/CommentThread.test.tsx` and `ui/src/components/MarkdownEditor.test.tsx` for Vitest 4 matcher/timing semantics - Refresh `pnpm-lock.yaml` ## Verification - `pnpm install` resolves cleanly with the new lockfile - `pnpm -w -r test` (server, ui, packages) runs under Vitest 4.1.8 ## Risks - Major-version Vitest bump: behavioral changes in pools, fake timers, and matcher strictness can surface flake. Test config and the two UI tests were updated to match v4 semantics; broader test runs should be watched on CI before merge. - Supersedes dependabot PR #7570 (3.2.4 → 3.2.6); that PR should be closed. ## Model Used - Claude (Anthropic) — `claude-opus-4-7`, extended thinking, tool use enabled ## 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 - [ ] I have run tests locally and they pass - [ ] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Closes #7570 |
||
|
|
dbebf30c89 |
Add low-trust review containment (#7530)
## Thinking Path > - Paperclip is a control plane for AI-agent companies, so execution policy and trust boundaries are part of the product's safety contract. > - Low-trust review work needs narrower authority than normal same-company agents because hostile PRs, comments, attachments, and generated output can carry prompt-injection payloads. > - The current V1 shape gives trusted workers broad company context, which is useful for normal execution but too permissive for a reviewer assigned to hostile content. > - This branch adds a `low_trust_review` preset, source-trust tagging, route-level containment, and quarantine handling so low-trust output does not automatically flow into higher-trust wake context. > - The branch has been rebased onto current `origin/master`, and the low-trust migration was renumbered to `0097_low_trust_source_trust.sql` to avoid collisions with existing `0091` through `0096` migrations. > - Greptile feedback was addressed by tightening low-trust detection, preserving project-level trust policy checks, fixing issue-kind promotion lookup, removing duplicate post-lease isolation assertion, documenting fail-closed source-trust behavior, bounding ancestry checks, enforcing runtime issue context for CEOs, awaiting accepted-plan monitor authorization, and making low-trust issue source-trust tagging atomic. > - The benefit is a first production slice of deny-by-default review containment with regression coverage for the main control-plane pivot surfaces. Fixes #7531. ## What Changed - Added shared trust-policy types and validators, plus database/source-trust fields for issues, comments, documents, and work products. - Implemented server enforcement for low-trust issue scope, agent self-view redaction, secret/plugin/runtime denial paths, promotion checks, and quarantined continuation/wake context. - Added focused low-trust regression tests for resolver behavior, source trust, route authorization, heartbeat preflight ordering, runtime containment, and quarantine redaction. - Added board UI affordances for selecting/reviewing the low-trust preset and surfacing source-trust badges in relevant issue views. - Added `doc/LOW-TRUST-PRESETS.md`, updated `doc/SPEC-implementation.md`, and committed the low-trust review contract plan under `doc/plans/`. - Rebasing note: the original `0097_low_trust_source_trust.sql` migration was renamed to `0097_low_trust_source_trust.sql`; the SQL uses `ADD COLUMN IF NOT EXISTS` so users who already applied the old-numbered migration are not broken by the renumbered migration. ## Verification - Rebased branch onto current `origin/master` and force-pushed with lease to `origin/PAP-10211-low-trust-agent` at head `2719f31e3`. - Confirmed the PR diff does not include `pnpm-lock.yaml` or `.github/workflows` changes. - Resolved upstream UI/comment conflicts by preserving deleted-comment tombstone behavior and low-trust source-trust badges/metadata. - Renumbered the low-trust source-trust migration to `0097_low_trust_source_trust.sql`; the SQL uses `ADD COLUMN IF NOT EXISTS` so users who already applied an old-numbered copy are not broken. - `pnpm exec vitest run ui/src/lib/issue-chat-messages.test.ts server/src/__tests__/heartbeat-workspace-session.test.ts` - `pnpm exec vitest run server/src/__tests__/source-trust.test.ts server/src/__tests__/workspace-runtime-service-authz.test.ts ui/src/lib/trust-policy-ui.test.ts ui/src/components/TrustPresetSection.test.tsx` - `pnpm run typecheck:build-gaps` - `git diff --check` - GitHub checks pass on head `2719f31e3`: build, typecheck/release registry, general tests, serialized server suites, e2e, canary, verify, policy/review, Socket, and Snyk. - Greptile Review passes with Confidence Score 5/5 and zero unresolved Greptile review threads. - No design screenshots/images were added because the task explicitly says not to add them unless they are specifically part of the work. ## Risks - Medium risk: this touches shared trust-policy contracts, server authorization paths, heartbeat context generation, migration metadata, and UI preset controls. - Low-trust containment is intentionally deny-by-default; legitimate future review workflows may need explicit allowlisted exceptions. - Plugin/runtime/security surfaces are broad, so regression tests cover the current known routes but future integrations must route through the same containment layer. - The PR is ready for review; GitHub checks are green and Greptile is 5/5. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, GPT-5 coding agent, tool-enabled shell and GitHub CLI workflow. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] UI changes are covered by focused tests; no screenshots were added per task instruction not to add design images unless specifically required - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
3657854e5e |
Merge pull request #7554 from paperclipai/codex/pap-10343-comment-redaction
[codex] Redact deleted issue comments |
||
|
|
c288debf66 |
build(deps): bump postgres from 3.4.8 to 3.4.9 (#7567)
Bumps [postgres](https://github.com/porsager/postgres) from 3.4.8 to 3.4.9. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/porsager/postgres/releases">postgres's releases</a>.</em></p> <blockquote> <h2>v3.4.9</h2> <ul> <li>Fix <a href="https://redirect.github.com/porsager/postgres/issues/1143">porsager/postgres#1143</a> 1e92809</li> </ul> <hr /> <p><a href="https://github.com/porsager/postgres/compare/v3.4.8...v3.4.9">https://github.com/porsager/postgres/compare/v3.4.8...v3.4.9</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/porsager/postgres/commit/e7dfa14519f363229ccc3ead7b1b2f2051937efb"><code>e7dfa14</code></a> 3.4.9</li> <li><a href="https://github.com/porsager/postgres/commit/cc29931aa1280fc62b9452647a48a89fe5d443a2"><code>cc29931</code></a> build</li> <li><a href="https://github.com/porsager/postgres/commit/1e92809e79dda7873d96646403c068cd6998ea73"><code>1e92809</code></a> Fix <a href="https://redirect.github.com/porsager/postgres/issues/1143">porsager/postgres#1143</a></li> <li>See full diff in <a href="https://github.com/porsager/postgres/compare/v3.4.8...v3.4.9">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
1afc8b1a60 | Add missing migration snapshot for comment deletion | ||
|
|
7f70759e61 | Redact deleted issue comments | ||
|
|
93206f73fa |
fix: Stop archived companies from waking agents (#7478)
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - Each agent has a heartbeat scheduler that wakes it on timers and on
events; every wake spawns an adapter (Claude / Codex / …) run that bills
the operator's subscription
> - When an operator archives a company, the agents inside it remain in
invokable states — the heartbeat scheduler never consults company status
— so timers keep firing and event-driven wakes (comments, mentions,
blockers-resolved, etc.) keep cascading
> - On real deployments this silently drains the operator's
subscription: idle archived companies wake their CEOs hourly, plus any
cross-company event cascade
> - This pull request enforces "archived ⇒ never spawns a run" as a
structural invariant by guarding the wake path AND cascading agent state
on archive/reactivate
> - The benefit is that archived companies stop billing the operator,
and the UI/queue stays consistent with the invariant
## What Changed
- `server/src/services/heartbeat.ts`:
- `enqueueWakeup()` loads the company and short-circuits when status is
not `active`. Background sources (timer, automation, events) write a
`company.inactive` skipped wake and return `null`; explicit user invokes
throw a `conflict` so the UI surfaces the real reason.
- `tickTimers()` joins agents to active companies so the scheduler does
not iterate archived-company agents at all (no skip-row noise).
- `server/src/services/companies.ts`:
- `archive(id, actor?)` pauses runnable agents with `pauseReason =
"company_archived"` inside the transaction (preserving
`pending_approval`, `terminated`, and agents paused for unrelated
reasons), then cancels `queued`/`running` heartbeat runs after the
transaction commits.
- `update(id, data, actor?)` reverses the cascade only for agents whose
`pauseReason === "company_archived"` on the `archived → active`
transition; manually-paused agents stay paused.
- Both methods emit activity-log entries (`company.archived` with
`agentsPaused` + `runsCancelled`, `company.reactivated` with
`agentsRestored`) so the audit trail fires regardless of caller.
- `packages/shared/src/constants.ts` + `server/src/services/budgets.ts`:
add `company_archived` to the legal `PauseReason` union so the
restorable marker is a first-class value.
-
`packages/db/src/migrations/0094_backfill_archived_company_agent_pauses.sql`:
backfill so existing archived-company agents become `paused /
company_archived` (excludes `pending_approval`).
- `ui/src/lib/activity-format.ts`: add the `company.reactivated` label.
## Verification
- `npx vitest run src/__tests__/companies-service.test.ts` — archive
cascade, reactivate cascade, and activity-log entries (with counts) all
pass.
- `npx vitest run
src/__tests__/heartbeat-archived-company-guard.test.ts` — timer +
on-demand + event-wake paths all blocked for archived companies;
`company.inactive` skipped-wake row written; user-initiated wakes throw
`conflict`.
- `pnpm typecheck` — clean.
- Manual repro from the bug description: archive a company, wait an
interval / post a comment on one of its issues, observe zero new
heartbeat runs.
## Risks
- Migration `0094` is a single bulk UPDATE on `agents` joined to
archived `companies`. On large deployments it briefly holds row locks on
archived-company agent rows; should be quick because the predicate is
narrow (`status NOT IN (paused, terminated, pending_approval)` and
`companies.status = 'archived'`).
- New `pauseReason` value (`company_archived`) is opaque to older
clients that only know the previous union. Acceptable because the union
is read as plain text and the contract is sync'd in the same change.
- Behavior change for users: invoking an agent in an archived company
now fails with a conflict instead of silently spawning a run. Intended.
## Model Used
- Claude (Anthropic) — model `claude-opus-4-7` ("Opus 4.7"), Claude Code
CLI, with tool use (Read/Edit/Bash/Grep). No extended thinking mode.
## 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 run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots — N/A, no UI changes beyond an activity-log label string
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
## Related Work
Fixes #1348 (`[Bug] Archived companies still running heartbeats and
consuming tokens`).
Prior attempts and parallel work in this area:
- #1365 and #1429 by @hungdqdesign (March 2026) — both closed without
merging. Same three-layer shape (`tickTimers` / `enqueueWakeup` /
`resumeQueuedRuns` + archive-route cancellation) targeting #1348. Credit
for first publicly proposing the wake-path-guard approach.
- #5865 by @stubbi (May 2026, open) — adds the same `companies.status !=
'archived'` joins to `tickTimers`, `enqueueWakeup`, `resumeQueuedRuns`,
**and** routines `tickScheduledTriggers`, bundled with plugin-table
tenant isolation (`plugin_entities` / `plugin_job_runs` / `plugin_logs`
/ `plugin_webhook_deliveries` get a `companyId` FK with `ON DELETE
CASCADE`). This PR is narrower — it does not touch routines or plugin
tables — but adds the **archive cascade** (pause agents with
`pauseReason = "company_archived"`), the **reactivate reverse**
(un-pause only that subset), the **`company_archived` pause-reason
marker**, and a **backfill migration** for pre-existing archived
companies, which #5865 does not include. Happy to coordinate sequencing
or rebase if #5865 lands first.
|
||
|
|
1f70fd9a22 |
PAPA-430: workspace finalize gates + no-remote-git enforcement (#6969)
## Thinking Path > - Paperclip orchestrates AI agents across isolated execution workspaces; the local cwd is the only persistence boundary between runs. > - Workspace lifecycle (worktree_prepare → execute → workspace_finalize) and the wake/accept flow are what guarantee that dependent issues see a consistent worktree. > - PAPA-380 / PAPA-431 / PAPA-432 / PAPA-440 surfaced three holes in that contract: silent env reuse across assignees, dependent wakes firing before finalize, and `issue.interaction.accept` advancing before finalize landed. > - PAPA-441 / PAPA-442 then needed to document the "no remote git" contract and prevent future adapter/runtime code from quietly reintroducing `git push` as a backdoor sync. > - This pull request lands those server fixes, the static `check-no-git-push` enforcement, the AUTHORING.md cross-link, and the Cody-review follow-ups on the PAPA-430 thread. > - The benefit is that finalize is a real barrier — board accepts, dependent wakes, and operator-set env all respect it — and adapter code can't bypass it via raw `git push`. ## What Changed - **server (PAPA-380, PAPA-431):** `execution-workspace-policy` refuses silent env reuse when the assignee's resolved env disagrees with the workspace it would inherit. The inheritance protection is now scoped to the actual inheritance signal — explicit issue-level `environmentId` is honored even when the agent's default env is `null`. - **server (PAPA-432):** `heartbeat.ts` gates dependent wakes on `listUnfinalizedExecutionWorkspaceIds`, and writes a `workspace_finalize` row on the succeeded path. Write failures now surface instead of being swallowed so dependents aren't silently stranded behind a missing row. - **server (PAPA-440):** `issue-thread-interactions.acceptInteraction` adds a workspace_finalize precondition for `request_confirmation` (not `suggest_tasks`). Accept returns 409 if finalize hasn't succeeded for the latest workspace operation. - **ci (PAPA-442):** new `scripts/check-no-git-push.mjs` static check scans `packages/adapters/`, `packages/adapter-utils/`, `server/src/`, and `cli/src/` for any `git push` invocation (string or args-array). Wired into the `policy` PR job and `test:release-registry`. Operators can opt in per-call with `// paperclip:allow-git-push: <reason>`. Release scripts are out of scope by design. - **docs (PAPA-441):** `AUTHORING.md` documents the no-remote-git contract and cross-links the static check so adapter authors learn the rule and the enforcement together. - **review follow-up (PAPA-430, Cody):** three fixes — env resolver bug, accept-gate scope (request_confirmation only), and finalize record write on the succeeded path. ## Verification - `pnpm exec vitest run server/src/__tests__/execution-workspace-policy.test.ts server/src/__tests__/issue-thread-interactions-service.test.ts` → 33/33 pass - `node scripts/check-no-git-push.test.mjs` → check covers string form, args-array form, comment exclusions, and per-line allow-comment. - Manual: server compiles; the policy job runs the check in <1s before heavier jobs. ## Risks - **Behavioral shift in accept:** boards accepting `request_confirmation` while finalize is in-flight now get 409s. This is intentional — they can retry — but it changes timing on a hot path. `suggest_tasks` is unaffected. - **Workspace policy:** the env-reuse refusal is a new error path. Issues that previously silently reused an env from a different-assignee workspace will now fail-loud; the resolver still honors explicit issue-level `executionWorkspaceSettings.environmentId`. - **CI rule:** any future legitimate `git push` in scoped dirs must be marked with the allow-comment, which is the intended ergonomic. ## Model Used - Claude Opus 4.7 (`claude-opus-4-7`, extended thinking), via Claude Code in the Paperclip executor adapter. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots (N/A — server/CI/docs only) - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Closes related issues: PAPA-430, PAPA-380, PAPA-431, PAPA-432, PAPA-440, PAPA-441, PAPA-442 --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
d9f91576a0 |
Add accepted-plan decomposition exact-once guards and UI state (#6831)
## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies, so planning approvals and child-issue fan-out are part of the core control-plane loop. > - Accepted plans are supposed to be a safe bridge from planning into execution, especially when agents wake from review decisions and reuse isolated workspaces. > - The duplicate-subtask incident showed that an accepted plan revision could be interpreted more than once across overlapping runs, which broke the single-source-of-truth model for issue decomposition. > - Fixing that required tightening the backend contract first: accepted-plan decomposition needs an exact-once fingerprint, durable claim state, and retry-safe child creation. > - Once that backend behavior existed, the board still needed visibility into what happened, so the issue detail view needed a dedicated decomposition section instead of forcing operators to reconstruct child creation from raw activity. > - This pull request adds the exact-once decomposition primitive, hardens wake routing and regressions around the incident, and surfaces decomposition state in the UI so future incidents are both prevented and easier to inspect. ## What Changed - Added accepted-plan decomposition semantics to `doc/execution-semantics.md`, including the exact-once fingerprint, durable claim/result expectations, and retry/resume behavior. - Added persistent accepted-plan decomposition claims in the backend, including schema, shared types/validators, service logic, and issue routes for creating and listing decomposition state. - Hardened heartbeat routing so an accepted-plan continuation stays scoped to the relevant planning issue instead of opportunistically re-decomposing another accepted issue on the same assignee. - Added regression coverage for the original failure modes: concurrent same-parent retries, cross-issue accepted-plan isolation, and partial child recreation under the same fingerprint. - Added the `Plan decomposition` issue-detail section plus supporting API/query-key/activity formatting updates so operators can see revision status, owner, child counts, and the linked child issues directly in the UI. - Included the small follow-up UI fix so the decomposition section still renders when the issue work mode is no longer `planning`. ## Verification - `pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/ui typecheck` - `pnpm --filter @paperclipai/db typecheck` - `pnpm exec vitest run server/src/__tests__/issues-service.test.ts` - `pnpm exec vitest run server/src/__tests__/issues-service.test.ts -t "lists persisted decompositions with child issue summaries"` - `pnpm exec vitest run server/src/__tests__/issues-service.test.ts -t "accepted plan decomposition" server/src/__tests__/heartbeat-accepted-plan-workspace-refresh.test.ts server/src/__tests__/heartbeat-context-summary.test.ts` - Manual UI path: create a planning issue without an isolated execution workspace, add a `plan` document, accept the `request_confirmation`, let Paperclip create child issues, then reopen the parent issue detail page and confirm the `Plan decomposition` section shows the accepted revision, status, idempotent-claim badge, and child links. - Separate follow-up bug noted during manual UI validation: accepting a plan on an issue whose run never records `workspace_finalize` is tracked in `PAPA-445` and is not part of this PR’s fix scope. ## Risks - This adds a new migration and a large Drizzle snapshot update; reviewers should confirm the schema shape and generated metadata match the intended decomposition table. - The exact-once claim changes sit on the accepted-plan fan-out path, so regressions there could block legitimate child creation or mis-handle retries if the claim state machine is wrong. - The new UI only appears when decomposition records exist; reviewers should use the manual verification path above rather than expecting existing issues on a stale local instance to show the section automatically. - `PAPA-445` remains an open follow-up for the `workspace_finalize` accept gate when a planning handoff never records finalize; that bug can interfere with reproducing the UI flow on isolated workspaces but does not change the correctness of the exact-once decomposition feature itself. > Checked `ROADMAP.md`: this PR is a bug fix / control-plane hardening change for accepted-plan decomposition, not a new uncoordinated roadmap feature. ## Model Used - OpenAI Codex via Paperclip `codex_local` (GPT-5-based coding agent; exact backend model ID/context window not exposed in the run context), with repository tool use, shell execution, and code-editing capabilities. <img width="806" height="1069" alt="Screenshot 2026-05-27 at 11 05 48 PM" src="https://github.com/user-attachments/assets/5b00b670-96cd-4470-b0a3-581743bcae28" /> ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
b7545823be |
[codex] Add document annotations and comments (#6733)
## Thinking Path > - Paperclip orchestrates AI-agent companies through issues, documents, runs, and durable company-scoped state. > - Issue documents are where agents and operators capture plans, handoffs, and work products. > - Before this change, document collaboration could only happen through whole-document edits and detached issue comments. > - Inline document annotations need stable anchors, revision-aware persistence, and UI affordances that do not break existing document editing. > - This pull request adds company-scoped document annotation threads, comments, anchor snapshots, API routes, and board UI. > - The benefit is that operators and agents can discuss specific document passages without losing context as documents evolve. ## What Changed - Added document annotation tables, schema exports, shared types, validators, anchor hashing, and text-anchor helpers. - Added server-side document annotation services and issue routes for listing, creating, commenting, resolving, and reopening annotation threads. - Included annotation summaries in relevant issue document reads and backup/recovery document workspace behavior. - Added React UI for inline document highlights, comment panels, mobile sheet behavior, deep-link focus, and resolved/open filtering. - Added annotation design artifacts, Storybook coverage, screenshots, and a screenshot helper script. - Rebased the branch onto current `paperclipai/paperclip` `master` and renumbered the annotation migration from `0085_old_swarm` to `0091_old_swarm`; the SQL uses `IF NOT EXISTS` guards so environments that previously applied the old migration number can safely apply the new one. - Adjusted the new annotation UI tests to use a local async flush helper because this workspace's React 19.2.4 export does not expose `React.act`. ## Verification - `pnpm run preflight:workspace-links && pnpm exec vitest run packages/shared/src/document-anchors.test.ts server/src/__tests__/document-annotation-routes.test.ts server/src/__tests__/document-annotations-service.test.ts ui/src/components/DocumentAnnotationLayer.test.tsx ui/src/components/IssueDocumentAnnotations.test.tsx ui/src/lib/document-annotation-hash.test.ts ui/src/lib/document-annotation-selection.test.ts` - Confirmed `git diff --check` passes. - Confirmed no `pnpm-lock.yaml` or `.github/workflows/*` files are included in the PR diff. ## Risks - Medium risk: this adds new persisted annotation tables and routes across db/shared/server/ui. - Migration risk is reduced by moving the branch migration to `0091_old_swarm` after upstream `0090_resource_memberships` and keeping the SQL idempotent for old `0085_old_swarm` adopters. - UI risk is mostly around text range anchoring and panel positioning across long documents, folded content, and mobile layouts; the PR includes focused unit coverage and design screenshots. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, GPT-5 coding agent, tool-using software engineering mode. Context window size is not exposed in this Paperclip runtime. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
9aea3e3d35 |
[codex] Add resource membership controls (#6677)
## Thinking Path > - Paperclip orchestrates AI-agent companies through company-scoped issues, projects, agents, and board-visible workflows. > - The board sidebar and project list are the daily navigation surface for that control plane. > - Users need to keep all projects and agents accessible while hiding resources they have intentionally left from their own sidebar. > - That requires user-scoped resource membership state backed by company-scoped API and database contracts. > - The branch also needed to preserve HTTP worktree login sessions and keep the project list easier to scan after membership grouping. > - This pull request adds resource membership controls, sidebar leave actions, grouped/sortable project listings, and focused tests. > - The benefit is a cleaner personal workspace view without weakening company-scoped access to the underlying project or agent detail pages. ## What Changed - Added `project_memberships` and `agent_memberships` tables with API/shared/server contracts for current-user join/leave state. - Renumbered the membership migration to `0090_resource_memberships` after rebasing onto current `master`, and made it idempotent for anyone who had applied the old branch-local `0087` migration. - Added project and agent sidebar leave actions, plus list filtering that waits for membership state before hiding resources. - Added grouped project listing, project sorting controls, and reserved row subtitle height for cleaner scanning. - Fixed HTTP auth cookie security handling so HTTP worktree sessions can persist. - Updated focused server and UI tests for the new membership, sidebar, project list, and auth behavior. ## Verification - `pnpm exec vitest run server/src/__tests__/better-auth.test.ts server/src/__tests__/resource-memberships-routes.test.ts ui/src/pages/Projects.test.tsx ui/src/components/SidebarProjects.test.tsx ui/src/components/SidebarAgents.test.tsx ui/src/components/MembershipAction.test.tsx ui/src/components/EntityRow.test.tsx` - Confirmed the branch is rebased on current `origin/master`. - Confirmed the PR diff does not include `pnpm-lock.yaml` or `.github/workflows` changes. ## Risks - Migration safety: low to medium. The migration now uses `IF NOT EXISTS` / guarded constraints and is numbered after current master migrations, but it should still get CI coverage against fresh databases. - UI behavior: low. Left resources are hidden from sidebar only after membership state loads; direct detail access remains available. - Auth behavior: low. Cookie security is relaxed only for HTTP/private local-style origins where secure cookies would prevent login persistence. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI GPT-5 Codex coding agent, tool-enabled shell/git workflow, context window not exposed by runtime. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Screenshot note: no browser screenshots were captured in this heartbeat; the UI changes are covered by focused component tests above. --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
ad6effa65c |
[codex] Improve runtime and import reliability (#6549)
## Thinking Path > - Paperclip coordinates autonomous company work through local and hosted runtime surfaces. > - Local embedded Postgres and tenant import/export paths are foundational reliability pieces. > - A runtime failure in either path can stop agents or imports before useful work begins. > - The branch included remaining fixes for embedded native library bootstrap and async tenant import handling. > - This pull request groups those runtime/import reliability changes into one standalone PR. > - The benefit is a more robust local runtime and safer cloud tenant import behavior. ## What Changed - Prepared embedded Postgres native runtime before startup in CLI/server/test entrypoints. - Added embedded Postgres native bootstrap coverage. - Added async tenant import job handling and deferred validation coverage. - Kept the runtime/import changes based directly on current `origin/master` after related upstream PRs had already merged. ## Verification - `pnpm --filter @paperclipai/plugin-sdk build` - `NODE_ENV=test pnpm exec vitest run packages/db/src/embedded-postgres-native.test.ts server/src/__tests__/company-portability-routes.test.ts` ## Risks - Medium-low: this touches startup/import paths, but the branch is small and covered by targeted tests. - The embedded Postgres change depends on platform-specific native-library behavior, so CI and follow-up checks should still verify supported runners. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI GPT-5 Codex via `codex_local`, tool-enabled coding session; exact context window not exposed by this runtime. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge |