Files
paperclip/CONTRIBUTING.md
DottaandPaperclip 2f35eb1080 feat(dev): add incremental local verification and pass reuse (#19345)
## Thinking Path

> - Paperclip coordinates agents that make and verify repository
changes.
> - Local verification currently defaults to the complete Vitest suite.
> - Contributor instructions also require broad local checks at each PR
handoff.
> - CI already owns conservative affected-test selection and broad
final-revision checks.
> - This pull request adds local selection and pass reuse from those
existing contracts.
> - Agents can get focused feedback and use CI to close the remaining
coverage gaps.

## Linked Issues or Issue Description

**Subsystem affected**

Developer verification scripts and contributor guidance. Related
selection work: #18398 and #18464.

**Problem or motivation**

An agent that repeats an unchanged local verification step starts the
complete suite again. The handoff guidance also duplicates broad CI
coverage locally.

**Proposed solution**

Add `pnpm verify` for the actual working tree. Select affected Vitest
specifications with the CI task policy and dependency graph. Reuse
successful checks whose inputs are modeled. Run opaque checks fresh.
Report exit 2 when broader verification is required. Update the
contributor contract to accept applicable final-revision CI coverage.

**Alternatives considered**

Plain `vitest related` omits filesystem and opaque dependencies.
Commit-only cache keys miss dirty files. Running full local suites at
every handoff repeats CI work.

**Roadmap alignment**

This is repository development tooling. It does not change the product
roadmap.

## What Changed

- Add `pnpm verify`, `--explain`, `--base`, `--full`, and `--no-cache`.
- Reuse CI selection and exact runner ownership for dirty, staged,
committed, deleted, renamed, and untracked inputs.
- Keep native server suites and serialized suites in their local owners.
Keep six sequential chat shards.
- Cache selected passes within one worktree. Hash source, fixtures,
installed package contents, dependency bindings and installation
metadata, dotenv files, child environment, toolchains, platform, and
selection.
- Run opaque consumers fresh. Preserve failed, interrupted,
mutated-input, and partial-coverage outcomes.
- Update AGENTS.md, CONTRIBUTING.md, and DEVELOPING.md guidance. Record
the shared `verify` command as the sole exception to the package-script
rule. Register the new tests in the existing CI contract-test command.
- Add optional root/environment inputs to shared graph helpers. Existing
CI defaults stay the same.

## Verification

- Fourteen new integration tests pass locally across focused runs with
real Vitest selection and execution; CI colors are covered.
- 51 existing targeted selector/input, project-isolation, and
stable-runner checks passed. Four relevant runner contracts also pass
after the workspace change.
- Repeated unchanged execution skips reusable tests. Source,
environment, installed code, dependency bindings, and new untracked
tests invalidate results.
- Installed-code mutation with a restored modification time still
invalidates a cached pass. Internal skill-directory links preserve
reuse.
- Workspace B/C tests prove discovery, reusable/fresh partition
execution, pass reuse, and external-input failure. Chat selection
produces exactly six single-worker partitions.
- A deliberate unrelated failing test is omitted by narrow selection and
caught by `--full`.
- Red/green regressions prove fingerprints preserve file boundaries and
reject edits made between diff discovery and snapshotting.
- Opaque external-file changes still fail on a subsequent run. Source
mutation and process interruption cannot publish reusable passes.
- `pnpm verify --explain` works in the checkout and requests broad CI
coverage for this tooling change. No duplicate full local suite was
started.
- [Final-revision
CI](https://github.com/paperclipai/paperclip/actions/runs/42117291789)
passed on `ed85d96ddff82c05c325948680b593b0f48c473d` (attempt 2). The
scoped Canary retry preserved all passing test/build results.
- [Greptile
review](https://github.com/paperclipai/paperclip/pull/19345#issuecomment-6670050175)
is 5/5; all four review threads are resolved.
- The additional Paperclip review concluded neutral because its
execution stopped; it produced no assessment.

## Risks

- Pass reuse depends on conservative dependency classification. Opaque
consumers, external database/live settings, and non-isolated projects
retain fresh or broad coverage.
- Local passes cover selected Vitest checks. Required CI,
build/typecheck, release, browser, and platform acceptance remain
separate obligations.
- Cross-worktree caching and cross-agent scheduling are outside this
change.
- The initial installation scan reads dependency contents;
stat-validated, worktree-local digest memoization avoids rereading
unchanged contents. Subsequent scans still inspect file identity and
nanosecond change/modification times.
- No dependency lockfile or workflow changes.

## Model Used

OpenAI Codex, `gpt-6.1-sol`, max reasoning, with local shell and file
tools. Context window size is not exposed by this host.

## 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 <[email protected]>
2026-11-06 07:29:10 -06:00

13 KiB

Contributing Guide

Thanks for wanting to contribute!

We really appreciate both small fixes and thoughtful larger changes.

Before You Start: Search First

Before you start work, search GitHub for existing PRs and issues that touch the same area:

  • Look for duplicate or in-flight PRs. If something close already exists, prefer helping that PR over the line (see Helping Other Contributors) instead of opening a parallel one.
  • Look for related open issues. Link them in your PR body.
  • If an older PR is effectively dead (stale, unmaintained, would be painful to rebase/merge), a fresh PR is fine — just call out the prior PR in your description so the reviewer has context.

Duplicate PRs create extra work for reviewers and make merging harder. A 60-second search saves hours later.

Affirm that you did this search by checking the dedup-search box in the PR template (I have searched GitHub for duplicate or related PRs and linked them above). Commitperclip checks for this checkbox on non-trivial PRs.

Two Paths to Get Your Pull Request Accepted

Path 1: Small, Focused Changes (Fastest way to get merged)

  • Pick one clear thing to fix/improve
  • Touch the smallest possible number of files
  • Make sure the change is very targeted and easy to review
  • All tests pass and CI is green
  • Greptile score is 5/5 with all comments addressed
  • Use the PR template

These almost always get merged quickly when they're clean.

Path 2: Bigger or Impactful Changes

  • First talk about it in Discord → #dev channel
    → Describe what you're trying to solve
    → Share rough ideas / approach
  • Once there's rough agreement, build it
  • In your PR include:
    • Clear description of what & why
    • Proof it works (manual testing notes)
    • All tests passing and CI green
    • Greptile score 5/5 with all comments addressed
    • PR template fully filled out

PRs that follow this path are much more likely to be accepted, even when they're large.

PR Requirements (all PRs)

  • Do not submit a PR that moves a code file from less than 1,000 lines of code to more than 1,000 lines of code.
  • Do not submit a PR that includes code comments.

Use the PR Template

Every pull request must follow the PR template at .github/PULL_REQUEST_TEMPLATE.md. If you create a PR via the GitHub API or other tooling that bypasses the template, copy its contents into your PR description manually. The template includes required sections: Thinking Path, What Changed, Verification, Risks, Model Used, and a Checklist.

We do not gate PRs on a pre-existing issue. Two acceptable paths:

  1. Issue exists — search the Issues database for anything this PR addresses and tag each one with Fixes: #123 / Closes #123 / Refs #123 so GitHub auto-links them. If there are duplicate or closely related issues, link all of them, not just the one you picked. If there are related PRs (prior attempts, dependent work, follow-ups, abandoned predecessors), link those too.
  2. No issue exists — describe the problem directly in your PR body, following one of our issue templates so a reviewer has the same fields they'd get from a filed issue:
    • Bug fix: what happened, expected behavior, steps to reproduce, Paperclip version/commit, deployment mode. See bug_report.yml.
    • Feature: problem/motivation, proposed solution, alternatives considered, roadmap alignment. See feature_request.yml.
    • New adapter: agent or provider, why it's useful, how it's invoked. See adapter_request.yml.

Either way, a reviewer should be able to understand the underlying issue without leaving the PR. Commitperclip may check that one of these two paths is satisfied. Only link public GitHub issues — see No Internal Issue References for what to leave out.

No Internal Issue References

Many contributors run their own Paperclip instance to manage their work. Issue ids and links from your instance are private — reviewers and other contributors cannot open them, so they show up as clutter or broken links.

In your PR title, description, commits, and comments, only reference public GitHub issues and PRs — #123, Fixes #123 / Closes #123 / Refs #123, or full https://github.com/paperclipai/paperclip/... URLs.

Do not include references to internal/instance-local Paperclip work, such as:

  • Internal ticket ids like PAPA-123, PAP-224, or any {PREFIX}-{NUMBER} identifier that isn't a public GitHub issue number.
  • Instance UI links such as /PAP/issues/..., /PAP/agents/..., agent://..., or document deep links.
  • localhost, private IP, or tailnet URLs pointing at your own instance.

If an internal issue captured useful context, restate that context in plain English in the PR body instead of linking to it.

Branch Naming

Tooling (including Paperclip) often names a working branch after an internal issue and task — e.g. PAPA-42-why-did-this-break. That name leaks instance-local context, isn't meaningful to reviewers, and ends up as the public branch on your PR.

Before you push, rename the branch to something descriptive of the change itself, not of your instance:

  • Use short, kebab-case names scoped to the change, optionally with a conventional prefix: docs/no-internal-issue-references, fix/sandbox-secret-resolution, feat/adapter-retry-backoff.
  • Do not include internal Paperclip ticket ids (PAPA-123, PAP-224), instance task slugs, or other instance-derived details in the branch name.

To rename and push under the new name:

git branch -m <descriptive-name>
git push -u origin <descriptive-name>
# If your tooling already pushed the old branch, delete it from origin:
git push origin --delete <old-name>

Keep Screenshots Out of the Repo

Screenshots, screen recordings, and other review evidence belong in the PR description or a PR comment, not in the repository. Do not commit them (for example under docs/pr-screenshots/). Committed review images land on master permanently and make every clone bigger, even though nobody needs them after the PR merges.

To show a visual change, drag the image into the PR description or a comment on GitHub, which hosts the file for you. If your tooling cannot upload to GitHub, leave the images out and describe what you checked under Verification.

Images that are part of the product documentation itself, such as a screenshot embedded in a guide under doc/, are fine to commit.

Model Used (Required)

Every PR must include a Model Used section specifying which AI model produced or assisted with the change. Include the provider, exact model ID/version, context window size, and any relevant capability details (e.g., reasoning mode, tool use). If no AI was used, write "None — human-authored". This applies to all contributors — human and AI alike.

Tests Must Pass

All required checks must pass before a PR can be merged. Run relevant local checks with pnpm verify, then require applicable typecheck, build, and test CI checks on the final tested revision. Fresh CI can supply broad coverage. Run a full local suite when it resolves a remaining local/platform-specific gap or is explicitly required for qualification. See AGENTS.md and doc/DEVELOPING.md for result reuse and coverage requirements.

Telemetry Changes

This repo has three separate data paths: Telemetry, Observability, and the run log. See rule 7 in AGENTS.md for the full definitions and the review level each path needs.

If your change adds, removes, or modifies emitted telemetry events, update the Telemetry Data Contract in the same PR. Keep clients emitting raw dimension values and avoid documenting or relying on private delivery details. If your change adds, removes, or modifies an OpenTelemetry span or span attribute, keep the change inside the closed span-attribute allowlist in packages/adapter-utils/src/acpx-engine/startup-timing.ts. If your change adds or modifies a run-log event, update doc/run-log-events.md in the same PR.

Paperclip Gates Must Pass

All Paperclip CI gates (lint, typecheck, tests, build, and any other required checks) must be satisfied before a PR can be merged. Don't ask for a merge while gates are red — fix them first.

Greptile Review

We use Greptile for automated code review. Your PR must achieve a 5/5 Greptile score before it can be merged, with:

  • No open P2 (or higher) comments
  • No open recommendations
  • No open follow-ups

We hold the bar high here on purpose — we want code quality to be as high as possible. If Greptile leaves comments, fix them (or, if a comment is wrong, reply explaining why) and request a re-review.

Helping Other Contributors

Fixing up someone else's stalled or almost-there PR is strongly encouraged. If a contributor has done most of the work but ran out of time or got stuck, picking up their branch, polishing it, and getting it over the line is one of the most valuable things you can do here.

When you do:

  • Give credit. Mention the original author in the PR description and thank them.
  • Preserve their commits where reasonable — don't squash them out of existence.
  • Be kind in comments and reviews. People put real effort into their PRs, even the ones that didn't quite land.

A culture where contributors help each other ship is worth more than any single PR. Be generous with thanks.

Feature Contributions

We actively manage the core Paperclip feature roadmap.

Uncoordinated feature PRs against the core product may be closed, even when the implementation is thoughtful and high quality. That is about roadmap ownership, product coherence, and long-term maintenance commitment, not a judgment about the effort.

If you want to contribute a feature:

  • Check ROADMAP.md first
  • Start the discussion in Discord -> #dev before writing code
  • If the idea fits as an extension, prefer building it with the plugin system
  • If you want to show a possible direction, reference implementations are welcome as feedback, but they generally will not be merged directly into core

Bugs, docs improvements, and small targeted improvements are still the easiest path to getting merged, and we really do appreciate them.

General Rules (both paths)

  • Write clear commit messages
  • Keep PR title + description meaningful
  • One PR = one logical change (unless it's a small related group)
  • Run tests locally first
  • Be kind in discussions 😄

Writing a Good PR message

Write all PR text in Simplified Technical English (ASD-STE100): use short sentences, one instruction per sentence, simple approved vocabulary, and the active voice.

Your PR description must follow the PR template. All sections are required. The "thinking path" at the top explains from the top of the project down to what you fixed. E.g.:

Thinking Path Example 1:

  • Paperclip is the open source app people use to manage AI agents for work
  • There are many types of adapters for each LLM model provider
  • But LLM's have a context limit and not all agents can automatically compact their context
  • So we need to have an adapter-specific configuration for which adapters can and cannot automatically compact their context
  • This pull request adds per-adapter configuration of compaction, either auto or paperclip managed
  • That way we can get optimal performance from any adapter/provider in Paperclip

Thinking Path Example 2:

  • Paperclip is the open source app people use to manage AI agents for work
  • But humans want to watch the agents and oversee their work
  • Human users also operate in teams and so they need their own logins, profiles, views etc.
  • So we have a multi-user system for humans
  • But humans want to be able to update their own profile picture and avatar
  • But the avatar upload form wasn't saving the avatar to the file storage system
  • So this PR fixes the avatar upload form to use the file storage service
  • The benefit is we don't have a one-off file storage for just one aspect of the system, which would cause confusion and extra configuration

Then have the rest of your normal PR message after the Thinking Path.

This should include details about what you did, why you did it, why it matters & the benefits, how we can verify it works, and any risks.

Questions? Just ask in #dev — we're happy to help.

Happy hacking!