Commit Graph

122 Commits

Author SHA1 Message Date
Devin Foley 71e9d6bb0b
feat(release): candidate-branch beta builds and the release checklist (#11209)
> Follow-up to #11208 (merged): rebased onto master and ready for
review.

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release channels promote artifacts along canary → nightly → beta
→ stable, with the happy path being promotion of an existing build
> - When one or two targeted fixes are needed before a beta or stable,
the only options today are waiting for the next nightly or absorbing a
whole day of unrelated master changes
> - The channel model was designed with an escape hatch for exactly
this: short-lived candidate branches carrying only cherry-picked fixes
> - This pull request implements candidate-branch beta builds with full
verification, documents the stable fix path through the
soak-justification gate, and adds the release captain's checklist
> - The benefit is that a surgical fix can ship forward without either
delay or blast radius, with its provenance recorded

## Linked Issues or Issue Description

Refs #11008 — completes the fix-path half of the channel model
introduced there.

**Subsystem affected**

Release automation: `scripts/release.sh`,
`.github/workflows/release.yml`, `doc/RELEASING.md`, new
`doc/RELEASE-CHECKLIST.md`, tests.

**Problem or motivation**

Beta promotion only accepts commits that already shipped as a nightly,
and stable promotion expects a soaked beta. There is no supported way to
ship one or two cherry-picked fixes between lanes: an urgent fix must
wait for the nightly cycle or pull in every unrelated master change from
the day. The original channel design called for candidate branches to
cover this, and they were deferred from the initial implementation.

**Proposed solution**

Candidate-branch beta builds: cut `candidate/beta-<target>` from a
nightly's source commit, cherry-pick the fixes, and dispatch `channel:
beta` with the new `candidate_branch` input. Selection enforces the
naming convention, rejects heads that already shipped as a beta or
predate the candidate tooling, and records the cherry-picked commits in
the job summary. Because candidate heads never went through a canary or
nightly, publication is gated on a full `release-verify` run (promoted
nightlies keep skipping re-verification). The stable fix path
(`candidate/release-<target>` as `source_ref`) works through the
existing soak gate: the justification requirement is the deliberate,
recorded trade-off for shipping unsoaked bits, and is now documented as
such.

## What Changed

- `scripts/release.sh`: `--from-candidate` flag (beta only) waives the
shipped-a-nightly requirement while keeping the duplicate-beta guard
- `.github/workflows/release.yml`: `candidate_branch` dispatch input;
candidate mode in `select_beta` (naming validation, duplicate and
tooling-era rejection, cherry-pick recording); new
`verify_beta_candidate` job gating candidate publishes on full
verification
- `doc/RELEASING.md`: beta fix-path and stable fix-path sections
- `doc/RELEASE-CHECKLIST.md` (new): the release captain's checklist for
all four lanes as built
- Tests: dry-run fixture coverage for `--from-candidate` (waives the
nightly guard, keeps the duplicate guard, rejected outside beta) and
wiring tests for candidate validation plus the verification gate

## Verification

- `node --test` on the four affected suites: 42 pass in total (17 + 25
across the two runs), including the 5 new tests
- `bash -n` on `release.sh`; YAML parse of the workflow
- After merge: exercise the path end to end the first time a real
cherry-picked beta is needed — dispatch with a `candidate/beta-*` branch
and confirm the summary records the picks and verification runs

## Risks

- Candidate builds bypass the smoke-tested-nightly provenance by design;
the compensating controls are full verification before publish, the
post-publish beta smoke, the human `npm-beta` gate, and recorded
cherry-picks
- The stable fix path rides the existing justification mechanism rather
than adding a second bypass — one recorded escape hatch, not two

## Model Used

Claude Fable 5 (`claude-fable-5`, Anthropic) in Claude Code, with
extended thinking and full tool use. All changes model-authored under
human direction.

## 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 (pending — will confirm before
merge)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending — will confirm before merge)
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-11 10:05:13 -07:00
Devin Foley 2da6a248c3
fix(release): surface recovery commands when a lane tag push is rejected (#11208)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release subsystem's promotion lanes publish to npm, then push a
lane tag and dispatch the Docker image build at that tag
> - The first nightly of the beta-tooling merge published to npm and
then died at the tag push: GITHUB_TOKEN may not create refs pointing at
workflow-modifying commits from dispatch or scheduled runs
> - The failure was a bare `remote rejected` with no guidance, leaving
the release half-finished (npm live, no tag, no images) until an
operator reverse-engineered the recovery
> - This pull request makes every lane's tag push degrade into exact
recovery instructions in the job summary
> - The benefit is that a rare platform-permission rejection becomes a
two-minute runbook operation instead of a forensic exercise

## Linked Issues or Issue Description

Refs #11008 — the incident occurred promoting that change's own merge
commit, the first workflow-modifying commit to flow through the lanes it
introduced.

**Subsystem affected**

Release automation: `.github/workflows/release.yml`, `doc/RELEASING.md`,
workflow wiring tests.

**Problem or motivation**

Run 31445344811 published `2026.811.0-nightly.0` to npm, then failed
pushing `nightly/v2026.811.0-nightly.0`: `refusing to allow a GitHub App
to create or update workflow .github/workflows/release.yml without
workflows permission`. The tagged commit modifies workflow files, and
GITHUB_TOKEN may not create refs pointing at such commits from dispatch
or scheduled runs (push-event runs are exempt, which is why the canary
tag on the same commit succeeded). The job failed with no explanation
and the Docker dispatch never ran.

**Proposed solution**

Wrap the nightly, beta, and stable tag pushes: on rejection, write the
exact recovery commands into the job summary — create and push the tag
with maintainer credentials, dispatch `docker.yml` at the tag, and for
stable also run `create-github-release.sh` — then fail the job. Document
the cause and recovery in the failure playbooks and pin the three
recovery blocks with a wiring test.

## What Changed

- `.github/workflows/release.yml`: recovery-summary wrappers on the
nightly, beta, and stable tag-push steps
- `doc/RELEASING.md`: failure-playbook entry for the
workflows-permission rejection
- `scripts/__tests__/release-verify-workflow.test.mjs`: wiring test
asserting all three lanes carry the recovery summary

## Verification

- Wiring tests: 6 pass; YAML parse of the workflow
- The recovery commands are exactly the ones used to resolve the real
incident (tag push + `docker.yml` dispatch for
`nightly/v2026.811.0-nightly.0`)

## Risks

- Low. The happy path is unchanged (a successful push skips the
wrapper); the failure path trades a bare error for actionable output and
still fails the job, since the release state is genuinely incomplete

## Model Used

Claude Fable 5 (`claude-fable-5`, Anthropic) in Claude Code, with
extended thinking and full tool use. All changes model-authored under
human direction.

## 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 (pending — will confirm before
merge)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending — will confirm before merge)
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-11 08:48:13 -07:00
Devin Foley d648becb90
refactor(ci): split workspaces-a into two Vitest native shards
Split the slow workspaces-a CI lane into two Vitest native shards and keep release verification in parity.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-08-10 17:32:44 -07:00
Devin Foley 6601014898
fix(release): reject promotion sources that predate their channel tooling (#11197)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release subsystem promotes builds along canary → nightly → beta
→ stable, and each publish job checks out the promotion's source commit
and runs that tree's release tooling
> - The first beta dispatch failed with `unexpected argument: beta`: the
selected nightly's source predated the beta channel, so its `release.sh`
did not know the argument
> - The failure was clean (argument parsing, nothing published) but
cryptic, and the same trap waits for any promotion of a source older
than its target channel's tooling
> - This pull request makes the selection jobs reject such sources with
an actionable error and documents the property
> - The benefit is that a bootstrapping or old-source promotion fails in
seconds with instructions, instead of mid-publish with a parser error

## Linked Issues or Issue Description

Refs #11008 — the guard hardens the beta promotion flow introduced
there, after its first dispatch surfaced the gap described below.

**Subsystem affected**

Release automation: `.github/workflows/release.yml`, `doc/RELEASING.md`,
workflow wiring tests.

**Problem or motivation**

Run 31444045044 (first beta dispatch) failed in `publish_beta` with
`unexpected argument: beta`. Promotions deliberately build from the
pinned source commit, which means they also run that commit's
`scripts/release.sh` — and a source that predates the target channel's
introduction cannot publish it. Nothing guards this today; the error
surfaces deep in the publish job with no explanation.

**Proposed solution**

Guard at selection time: `select_nightly` requires the source canary's
`release.sh` to know the nightly channel, and `select_beta` requires the
source nightly's `release.sh` to know the beta channel. Each guard
literally matches the channel case arm and fails closed with a clear
message naming the remedy (promote a newer source). Document the
tooling-era property in `RELEASING.md` and pin the guards with a wiring
test.

## What Changed

- `.github/workflows/release.yml`: tooling-era guards in
`select_nightly` and `select_beta`
- `doc/RELEASING.md`: documents that promotions run the source commit's
release tooling
- `scripts/__tests__/release-verify-workflow.test.mjs`: wiring test
pinning both guards

## Verification

- Wiring tests: 5 pass
- Guard expressions exercised against real commits: accepts the
beta-capable merge commit of the beta-channel change, rejects a pre-beta
commit
- YAML parse of the workflow
- After merge: the next beta dispatch selects a beta-capable nightly and
passes the guard

## Risks

- Low. Selection-time check only; the guards match the channel case arm
literally and fail closed (with the same actionable message) if that
line is ever reformatted

## Model Used

Claude Fable 5 (`claude-fable-5`, Anthropic) in Claude Code, with
extended thinking and full tool use. All changes model-authored under
human direction.

## 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 (pending — will confirm before
merge)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending — will confirm before merge)
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-10 17:22:54 -07:00
Devin Foley 8f7b8b3fda
feat(release): add human-gated beta channel with stable soak enforcement (#11008)
> Follow-up to #11006 (merged): rebased onto master and ready for
review.

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release subsystem now publishes canary (every master push),
nightly (scheduled, smoke-gated, added in #11006), and stable (manual)
> - There is still no human-approved release-candidate lane between
nightly and stable, and nothing enforces that a stable actually soaked
anywhere before shipping
> - Betas need a real approval gate, and stables need a soak policy that
is data, not prose
> - This pull request adds the beta channel: a manual promotion of a
chosen nightly behind the `npm-beta` environment gate, re-smoked after
publish, plus a stable preflight that enforces a 3-day beta soak with a
written-justification bypass
> - The benefit is a complete canary → nightly → beta → stable train
where every stable shipped as a beta first, and emergencies leave a
written trace

## Linked Issues or Issue Description

**Subsystem affected**

Release automation: `scripts/release.sh`, `scripts/release-lib.sh`,
`.github/workflows/release.yml`, `.github/workflows/docker.yml`,
`.github/workflows/release-smoke.yml`.

**Problem or motivation**

After #11006 the project has canary and nightly prerelease lanes, but no
release-candidate lane. Stable promotion has no enforced soak: any ref
can ship as stable directly. There is no approval boundary for a
broader-audience prerelease, and no structured way to record why an
emergency release skipped validation.

**Proposed solution**

Add a `beta` channel: a manual dispatch that promotes a chosen nightly's
source commit, publishes behind the `npm-beta` GitHub environment
(required reviewers are the gate), re-smokes the published beta, and
tags `beta/vX`. Enforce in the stable path that the source commit
shipped as a beta at least 3 days earlier (measured from the beta's npm
publish time), with a `skip_soak_justification` input as the recorded
emergency bypass.

**Alternatives considered**

Codifying the soak policy in docs only. Rejected: an unenforced policy
decays; the preflight makes the policy executable while the
justification input keeps the emergency path usable and auditable.

## What Changed

- `scripts/release.sh` + `scripts/release-lib.sh`: `beta` channel —
requires HEAD to carry a `nightly/v*` tag, publishes the package set as
`YYYY.MDD.P-beta.N` under dist-tag `beta`, tags
`beta/vYYYY.MDD.P-beta.N`
- `.github/workflows/release.yml`:
- `channel: beta` dispatch path: `select_beta` resolves the newest (or
an explicit `source_version`) nightly and fails loudly on selection
problems; `publish_beta` runs behind the `npm-beta` environment, pushes
the tag, and dispatches `docker.yml`; `smoke_beta` re-runs the release
smoke suite against the exact published beta version
- stable path: new `preflight_stable` job enforces the 3-day beta soak
from the beta's npm publish time; `skip_soak_justification` bypasses
with the reason echoed into the job summary; dry runs report without
blocking
- `.github/workflows/docker.yml`: `beta/v*` tags publish `:beta` on both
images, with exact version stamping
- `.github/workflows/release-smoke.yml`: `beta` added to the dispatch
choice list
- Docs: `CHANNELS.md` beta entries; `RELEASING.md` beta lane, soak gate,
and failure playbook; `RELEASE-AUTOMATION-SETUP.md` `npm-beta`
environment setup, including the warning to create the environment
before the first beta dispatch (GitHub auto-creates unprotected
environments on first reference)
- Tests: beta version-counting coverage in
`scripts/release-registry-versions.test.mjs`; beta identity and
nightly-tag guard coverage in
`scripts/__tests__/release-dry-run-notes.test.mjs`

## Verification

- `node --test` on the two touched suites: 17 pass, including the 3 new
beta tests
- `bash -n` on both shell scripts and YAML parse of all three workflows
- After merge, in order: create the `npm-beta` environment, dispatch
`channel: beta` with `dry_run: true` to preview, then a real promotion
of a published nightly through the approval gate, then a stable dry-run
against a young beta to see the soak gate report

## Risks

- If the `npm-beta` environment does not exist when the first beta
dispatch runs, GitHub creates it with no protection rules and the beta
publishes without approval. Mitigated by documentation and by creating
the environment before merge (operator step)
- Until the first beta exists, every stable dispatch requires
`skip_soak_justification`. This is deliberate — the first beta ships
immediately after this merges — but it is a behavior change to the
stable dispatch
- The soak clock reads the beta's npm publish time from the registry; a
registry outage makes the preflight fall back to requiring justification
(fail-closed)

## Model Used

Claude Fable 5 (`claude-fable-5`, Anthropic) in Claude Code, with
extended thinking and full tool use (repository exploration, local test
execution, live registry and git verification). All code, tests, and
docs in this PR were model-authored under human direction.

## 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 (pending — will confirm before
merge)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending — will confirm before merge)
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-10 16:52:59 -07:00
Devin Foley 30f6999cbe
fix(release-smoke): configurable readiness timeout and diagnostics for slow containers (#11187)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release subsystem's nightly lane (#11006) gates every nightly
publish on the release smoke suite, which boots the published artifact
in a Docker container
> - The suite's first CI execution failed at the health readiness check:
the harness hard-codes a 90 second budget, but a CI container
cold-installs paperclipai from npm and initializes embedded postgres
with no warm caches
> - When the timeout expired with the container still running, the
harness printed no container logs, so the failure gave no diagnostics
> - This pull request makes the readiness budget configurable, raises it
for CI, and dumps container logs on timeout
> - The benefit is that the nightly gate measures the artifact, not the
runner's cold caches, and a red smoke run is diagnosable from its logs

## Linked Issues or Issue Description

**Subsystem affected**

Release smoke testing: `scripts/docker-onboard-smoke.sh`,
`.github/workflows/release-smoke.yml`.

**Problem or motivation**

Run 31426044332 (first forced nightly after #11006) failed in
`smoke_nightly` with `server did not become ready at
http://localhost:3232/api/health` after exactly 90 seconds. The
harness's readiness window is hard-coded to 90 attempts at 1 second.
Locally that works because the npm cache is warm; in CI the container
downloads the full package set and embedded postgres first. The timeout
path also printed no container logs when the container was still
running, so there was no way to see how far boot had progressed.

**Proposed solution**

Make the readiness budget an environment variable
(`SMOKE_READY_TIMEOUT_SECONDS`, default unchanged at 90 for local use),
set it to 420 in the CI workflow, and dump the last 150 container log
lines when the readiness check times out on a still-running container.

## What Changed

- `scripts/docker-onboard-smoke.sh`: `SMOKE_READY_TIMEOUT_SECONDS` env
var (default 90) replaces the hard-coded readiness budget; timeout with
a still-running container now prints the tail of `docker logs`
- `.github/workflows/release-smoke.yml`: sets
`SMOKE_READY_TIMEOUT_SECONDS=420` for CI runs

## Verification

- `bash -n` on the harness and YAML parse of the workflow
- The real proof is the next `channel: nightly` dispatch of
`release.yml`, which re-runs this suite in CI with the new budget

## Risks

- Low. The local default is unchanged; CI runs simply wait longer before
declaring failure, and a genuinely broken artifact still fails (with
logs now)

## Model Used

Claude Fable 5 (`claude-fable-5`, Anthropic) in Claude Code, with
extended thinking and full tool use. Diagnosis from CI run logs; patch
model-authored under human direction.

## 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 (pending — will confirm before
merge)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending — will confirm before merge)
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-10 13:19:33 -07:00
Devin Foley f9173782cd
feat(release): add smoke-gated nightly channel and lane-separated Docker tags (#11006)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release subsystem publishes the `paperclipai` npm package set
and the Docker images on two lanes: canary on every master push, and
stable on manual promotion
> - There is no middle ground between those lanes. Users must track
every merge or wait weeks for a stable. Docker `:latest` also tracks
master, so Docker users have no stable image at all
> - A calm prerelease lane needs to exist, and it must never ship a
build that failed its checks
> - This pull request adds the nightly channel: a scheduled job that
selects the newest master commit with a green canary publish, runs the
full release smoke suite against that exact published canary, and only
then republishes it as the nightly. It also separates Docker tags by
lane, so `:latest` finally means stable
> - The benefit is that users can follow prereleases at a nightly
cadence with a smoke-tested guarantee, and Docker users get real
`:canary`, `:nightly`, and stable image tags

## Linked Issues or Issue Description

**Subsystem affected**

Release automation: `scripts/release.sh`, `scripts/release-lib.sh`,
`.github/workflows/release.yml`, `.github/workflows/docker.yml`,
`.github/workflows/release-smoke.yml`.

**Problem or motivation**

The project publishes only `canary` (every master push) and `latest`
(manual stable). Users who want prereleases without per-merge churn have
no option. Docker has a second problem: master builds overwrite
`:latest`, and CI-published stables never produced Docker images,
because tags pushed with `GITHUB_TOKEN` do not fire the `v*` tag trigger
in `docker.yml`. No stable-versioned image exists in ghcr today.

**Proposed solution**

Add a `nightly` channel. A scheduled job selects the newest
canary-tagged master commit, smoke-tests that exact published canary,
and republishes the same commit as `YYYY.MDD.P-nightly.N` under the
`nightly` dist-tag. Separate Docker tags by lane (`:canary` for master,
`:nightly` for nightly tags, `:latest` plus version tags for stable tags
only), and have the release jobs dispatch `docker.yml` at the new tag so
lane images actually build.

**Alternatives considered**

Moving the `nightly` dist-tag to the existing canary version without a
republish. Rejected: the version string would say `canary` while the
user is on nightly, which breaks at-a-glance lane identification in bug
reports and `--version` output.

## What Changed

- `scripts/release-lib.sh`: channel-parameterized
`next_prerelease_version` and `prerelease_tag_name` helpers (canary
helpers delegate to them), a `require_channel_tag_at_head` guard, and
the no-provenance retry for Sigstore transparency-log duplicates now
covers the `nightly` dist-tag as well as `canary`
- `scripts/release.sh`: new `nightly` channel. It requires HEAD to carry
a `canary/v*` tag, publishes the full public package set as
`YYYY.MDD.P-nightly.N` under dist-tag `nightly`, and tags the source
commit `nightly/vYYYY.MDD.P-nightly.N`
- `.github/workflows/release.yml`: scheduled nightly chain (09:00 UTC) —
select candidate, smoke it via `release-smoke.yml`, publish on green
under the existing `npm-canary` environment, push the tag, dispatch
`docker.yml`. New `channel` dispatch input (default `stable`, so
existing stable dispatches are unchanged) with `nightly_source_version`
and `dry_run` support for forced runs. The stable path now also
dispatches `docker.yml` at the new `v*` tag
- `.github/workflows/docker.yml`: lane tag mapping for both image jobs —
master pushes publish `:canary` and no longer move `:latest`;
`nightly/v*` tags publish `:nightly`; only stable `v*` tags publish
`:latest` and the versioned tags. New `workflow_dispatch` trigger for
the release-job dispatches. Build-version stamping uses the exact
nightly version on nightly tag builds
- `.github/workflows/release-smoke.yml`: `nightly` added to the dispatch
choice list
- `doc/CHANNELS.md` (new): user-facing guide to the channels
- `doc/RELEASING.md`: nightly lane documentation, Docker tag mapping
table, and a nightly failure playbook
- `doc/RELEASE-AUTOMATION-SETUP.md`: note that nightly reuses
`npm-canary` and needs no npm trusted-publisher changes
- Tests: channel-parameterized version helper coverage in
`scripts/release-registry-versions.test.mjs`, and nightly flow coverage
(publish identity, notes not required, canary-tag guard) in
`scripts/__tests__/release-dry-run-notes.test.mjs`

## Verification

- `node --test` on the release script suites: 68 pass, including 6 new
tests. The only failure, `acpx-patch-packaging.test.mjs`, needs
installed `node_modules` and fails identically on a pristine checkout of
master in the same environment
- `bash -n` on both shell scripts and YAML parse of all three workflows
- Live fail-path check: `./scripts/release.sh nightly --print-version`
from a master tip with no canary tag fails with `HEAD has no canary/v*
tag`
- Live success-path check: the same command from the
`canary/v2026.806.0-canary.7` commit prints `2026.806.0-nightly.0`
- Live selection check: the candidate-selection shell logic run against
the real repository selects the commit of `canary/v2026.806.0-canary.7`,
which matches the current npm `canary` dist-tag exactly
- After merge: dispatch `release.yml` with `channel: nightly` and
`dry_run: true` to preview, then a real forced run to validate end to
end before the first scheduled run

## Risks

- Docker `:latest` changes meaning from "latest master build" to "latest
stable release". This is deliberate and will be announced. Users who
want the old behavior pull `:canary`. Until the first stable release
after this change, `:latest` stays at its current (master-built) image
- The nightly is a rebuild of the same source commit, not the
byte-identical canary artifact that was smoked. The lockfile pins
dependencies, and the publish path's registry-visibility and
clean-prefix install gates still run on the nightly artifacts
- All npm publishing must stay inside `release.yml` because npm trusted
publishing pins that workflow file per package. The nightly jobs were
added to `release.yml` for exactly that reason; this constraint is now
documented in `RELEASING.md`
- The stable-lane Docker dispatch fails gracefully (a warning with
manual instructions) when the source ref predates `docker.yml`'s
`workflow_dispatch` trigger

## Model Used

Claude Fable 5 (`claude-fable-5`, Anthropic) in Claude Code, with
extended thinking and full tool use (repository exploration, local test
execution, live registry and git verification). All code, tests, and
docs in this PR were model-authored under human direction.

## 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 (pending — will confirm before
merge)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending — will confirm before merge)
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-10 12:16:55 -07:00
Devin Foley 00a24d7e8f
ci: split general-server tests into five shards with refreshed durations (#10925)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The PR workflow runs the server vitest suite across sharded runners
because the suite is pinned to one worker.
> - In successful PR run 30930345729 (2026-08-04), shard `server (3/4)`
took 311 seconds of wall time and was the slowest check in the run.
> - The suite has grown to about 946 seconds of serial vitest time, but
the duration manifest was last sampled on 2026-08-01 at about 882
seconds.
> - This pull request refreshes the per-suite duration manifest from
that run's logs and splits the lane into five shards.
> - The benefit is a shorter PR critical path: each shard carries about
196 seconds of suite time, level with the other lanes.

## Linked Issues or Issue Description

Refs #10663 (previous split of this lane into four shards).
Related: #10923 splits the separate serialized-suites lane into five
shards. Both PRs touch `.github/workflows/pr.yml` in different matrix
blocks; whichever merges second needs a trivial rebase.

**What existing behavior does this improve?**

The `general-server` vitest lane runs in four shards with a duration
manifest sampled on 2026-08-01.

**Current behavior**

In PR run 30930345729, shard 3/4 ran for 311 seconds (273 seconds in the
test step) and was the longest check in the run. The suite now totals
about 946 seconds of serial vitest time.

**Proposed behavior**

Run the same suite set in five shards, balanced with a per-suite
duration manifest refreshed from that run's shard logs (279 suites
measured by diffing consecutive completion timestamps).

**Reason and benefit**

The refreshed LPT partition balances at about 196 seconds of suite time
per shard (about 240 seconds per job), level with the other PR lanes. No
test coverage is lost.

**Breaking changes**

None. The change only alters the CI partition size and the duration
manifest.

## What Changed

- Bump the `general-server` shard matrix in `.github/workflows/pr.yml`
from four to five shards.
- Refresh `scripts/general-server-shard-durations.json` from the
2026-08-04 run's shard logs.
- Update `SHARD_COUNT` in
`scripts/__tests__/run-vitest-stable-shard.test.mjs` to five.

## Verification

- `node --test scripts/__tests__/run-vitest-stable-shard.test.mjs` — 9/9
pass, including the complete non-overlapping partition proof and the
duration-balance check.
- `node --test scripts/__tests__/release-verify-workflow.test.mjs` — 2/2
pass.
- `node --test scripts/__tests__/e2e-shard.test.mjs` — 7/7 pass.
- A 5-way dry-run partition covers all suites exactly once with equal
projected weights.

## Risks

- Low risk. The change only alters CI partition size and duration
weights; the suite set is unchanged.
- One more runner is used per PR run for this lane.
- Stale duration weights degrade gracefully: suites missing from the
manifest get the median weight.

## Model Used

- Claude (Anthropic), Claude Code CLI, model ID `claude-fable-5`,
extended thinking with 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
(workflow comments explain the new shard math)
- [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: Claude <claude@paperclip.ing>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-05 16:44:29 -07:00
Devin Foley b6e58019f2
ci: split serialized tests into five shards (#10923)
## Thinking Path

> - Paperclip uses CI to keep control-plane changes safe and mergeable.
> - The PR workflow splits serialized server tests across isolated
runners.
> - A recent successful run spent 305 seconds in serialized shard 2/4.
> - That job was the slowest check in the run.
> - The four shards reported about 739 seconds of Vitest suite time.
> - This pull request adds a fifth serialized shard and keeps release
verification aligned.
> - The benefit is a shorter PR critical path with no loss of test
coverage.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The PR and release verification workflows run serialized server tests in
four shards.

**Current behavior**

Successful PR run 30876682788 spent 305 seconds in `Verify serialized
server suites (2/4)`. The test step used 256 seconds and made this job
the slowest check.

**Proposed behavior**

Run the same serialized suite set in five complete and non-overlapping
shards.

**Reason and benefit**

The measured suites reported about 739 seconds of total Vitest time.
Five runners reduce the expected average suite time from about 185
seconds to about 148 seconds before setup overhead.

**Breaking changes**

None. The change only alters CI partition size.

## What Changed

- Split serialized server tests into five shards in the PR workflow.
- Apply the same five-shard layout to release verification.
- Add a partition test that proves complete and non-overlapping
serialized coverage.
- Update release workflow coverage tests for five shards.

## Verification

- `node --test scripts/__tests__/run-vitest-stable-shard.test.mjs
scripts/__tests__/release-verify-workflow.test.mjs`
- `git diff --check`

## Risks

- Low risk. CI uses one additional runner for the serialized lane.
- Round-robin partition weights can still vary as suite timings change.

> This change does not overlap with planned core work in `ROADMAP.md`.
Related PR #10663 optimized the separate general-server lane.

## Model Used

- OpenAI Codex, GPT-5, agentic coding with reasoning, tool use, and code
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)
- [ ] 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: Devin Foley <139239+devinfoley@users.noreply.github.com>
2026-08-05 16:29:49 -07:00
Devin Foley 8540ce2973
ci: shard general-server tests 4 ways (#10663)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Pull request CI must give contributors fast and stable feedback.
> - The `general-server` Vitest lane runs many single-worker server
suites.
> - A recent completed PR run showed this lane as the slowest completed
check.
> - Three shards still left one runner with the largest share of work.
> - This pull request splits that lane into four duration-balanced
shards.
> - The benefit is a shorter critical path for the same server test
coverage.

## Linked Issues or Issue Description

No public GitHub issue exists for this CI maintenance change.

**Pre-submission checklist**

- I confirmed this improves existing behavior. It does not add a new
command, endpoint, or concept.
- I searched open public issues and pull requests for related CI
sharding work.

**What existing behavior does this improve?**

The pull request workflow's `general-server` Vitest lane.

**Subsystem affected**

Cross-cutting. This affects GitHub Actions CI and the Vitest shard
duration manifest.

**Current behavior**

The `general-server` lane uses three shards. The server suites now total
about 880 seconds of serial Vitest wall time. The slowest shard was
about 313 seconds in the measured run.

**Proposed behavior**

The `general-server` lane uses four shards. Each shard receives about
220 seconds of predicted suite weight from the refreshed duration
manifest.

**Reason and benefit**

The slowest PR check controls how soon a reviewer can trust the PR. Four
balanced shards reduce the slowest `general-server` shard while keeping
the same suite selection rules.

**Breaking changes**

None. This only changes CI partitioning and duration data for existing
test suites.

**Additional context**

Related public searches found no exact open issue or pull request for
this `general-server` sharding change.

## What Changed

- Split the `general-server` CI matrix from three shards to four shards.
- Refreshed `scripts/general-server-shard-durations.json` with wall-time
weights from a recent completed PR run.

## Verification

- `node --test scripts/__tests__/run-vitest-stable-shard.test.mjs`
- `git diff --check origin/master...HEAD`
- Dry-ran the four `general-server` shards locally during
implementation. The partition covers 300 unique suites with about 220.56
seconds of predicted weight per shard.
- Ran a local sensitive-data scan before push. It found only test
filenames that contain words such as `secret` or `token`, not credential
values.

## Risks

Low risk. The main risk is that the duration manifest becomes stale as
suite costs move. Missing suites fall back to the median weight, so the
lane still runs if the manifest is incomplete.

## Model Used

OpenAI Codex, GPT-5, 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
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-01 19:03:28 -07:00
Devin Foley 8444e5735c
ci: pass e2e shard specs without separator (#10640)
## Thinking Path

> - Paperclip uses pull request CI to test changes before merge.
> - The e2e PR lane runs Playwright specs in a shard matrix.
> - Each shard builds a list of spec files for its matrix entry.
> - The workflow passed that list after a literal `--` separator.
> - Playwright did not receive the list as file filters.
> - This pull request removes the separator and adds a guard test.
> - The benefit is that each e2e shard runs only its assigned specs.

## Linked Issues or Issue Description

Refs #10629.

**What happened?**

The e2e shard step used `pnpm run test:e2e -- $specs`. The shard spec
list was not applied as Playwright file filters.

**Expected behavior**

Each e2e shard should pass only its selected specs to Playwright.

**Steps to reproduce**

1. Inspect `.github/workflows/pr.yml` at the merge commit for #10629.
2. Find the `e2e_shards` command that invokes `pnpm run test:e2e`.
3. See the literal `--` before `$specs`.

**Paperclip version or commit**

`86767951`

**Deployment mode**

GitHub Actions PR CI.

## What Changed

- Removed the literal `--` from the e2e shard `pnpm run test:e2e $specs`
invocation.
- Added a regression test that checks the workflow passes `$specs`
without that separator.

## Verification

- `node --test scripts/__tests__/e2e-shard.test.mjs`

## Risks

Low risk. This changes one CI command and one workflow guard test. The
main risk is shell argument handling in the workflow, and the guard now
covers the expected command shape.

## Model Used

OpenAI GPT-5 through Codex. The run used shell and GitHub CLI tool
access. 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 does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-01 15:04:21 -07:00
Devin Foley 8676795188
ci: split e2e PR lane into three shards (#10629)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The pull request workflow protects changes with a Playwright e2e
lane.
> - That lane already uses a weighted file partition so slow specs do
not cluster by test count.
> - Recent green PR runs showed the two e2e shard jobs were slower than
the next slow required lane.
> - The largest spec is indivisible, so a third shard lets that spec run
alone and lets the rest split by duration.
> - This pull request changes only the PR e2e shard matrix and the guard
test.
> - The benefit is a shorter expected PR critical path while the
required `e2e` aggregate check name stays stable.

## Linked Issues or Issue Description

Refs #9923

**What existing behavior does this improve?**

The `pull_request` workflow Playwright e2e lane.

**Subsystem affected**

Cross-cutting: GitHub Actions CI and test scripts.

**Current behavior**

The PR workflow runs the weighted Playwright e2e partition across two
jobs. Recent green runs showed those jobs as the slowest required
checks.

**Proposed behavior**

The PR workflow runs the same e2e spec set across three weighted jobs.
The aggregate required check stays named `e2e`.

**Reason and benefit**

The third shard lets the slow smoke-lab spec run alone while the rest of
the catalog stays balanced. This should shorten the PR critical path.
The win is bounded by fixed per-job setup time.

**Breaking changes**

None. The required aggregate check contract is preserved.

## What Changed

- Change the PR e2e shard matrix from two entries to three entries.
- Update the shard guard test to expect three shards.
- Floor the balance bound at the largest single spec weight.
- Assert that the workflow does not define more shard indexes than
`SHARD_COUNT`.

## Verification

- `node --test ./scripts/__tests__/e2e-shard.test.mjs` passes with 6
tests.
- The recorded-weight partition is complete and non-overlapping: 168.0s,
116.5s, and 114.4s.
- I checked `ROADMAP.md` and found no overlapping roadmap-level core
feature.
- I searched public GitHub PRs and issues for related e2e shard work. I
found related PR #9923 and no open duplicate for this branch or change.

## Risks

- This adds one extra GitHub Actions runner to the PR e2e lane.
- The wall-clock win is bounded by fixed per-job setup.
- Behavior risk is low because the aggregate required check remains
named `e2e`.

## Model Used

OpenAI Codex, GPT-5, tool-enabled coding agent in this repository. The
runtime did not expose the context-window size.

## Checklist

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

---------

Co-authored-by: Cody <noreply@paperclip.ing>
2026-08-01 10:10:22 -07:00
Devin Foley ea0dd3917e
build: make image layer caching actually hit (#10571)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Published container images are the deployable unit for self-hosted
and managed instances, so merge-to-image latency bounds every deploy
iteration
> - The docker workflow configures BuildKit caching, but builds still
ran ~12+ minutes essentially cold
> - Two causes: the most expensive layer (four CLI toolchains + apt) is
ordered after the always-changing app copy so it can never cache, and
the type=gha cache's 10GB repo cap means the two multi-arch mode=max
jobs evict each other
> - This pull request reorders the tool layer above the app copy (with a
weekly epoch so @latest tools keep advancing) and switches both jobs to
registry-backed cache in ghcr
> - The benefit is that warm builds shrink to roughly the app build +
push, targeting the sub-5-minute range together with the amd64-only
cloud variant

## Linked Issues or Issue Description

No existing public issue — inline description following the feature
request template:

**Subsystem affected**

CI / release publishing (docker workflow, Dockerfile)

**Problem or motivation**

Despite `cache-from/cache-to` being configured, image builds run
effectively cold: (1) the production stage installs four CLI toolchains
+ apt packages *after* `COPY --from=build /app /app`, and since the app
copy changes every commit, that most-expensive layer rebuilds every
build, per arch; (2) the `type=gha` BuildKit cache is capped at 10GB per
repository, and two multi-arch `mode=max` jobs overflow and evict each
other's entries.

**Proposed solution**

Order the tool/OS layer before the app copy (it references nothing from
`/app`), refresh it weekly via a `CLI_TOOLS_CACHE_EPOCH` build arg so
the `@latest` tools don't freeze in the cache, and move both jobs to
registry-backed BuildKit cache (`:buildcache` / `:buildcache-cloud` refs
in ghcr, no size cap, separate refs so the parallel jobs don't clobber
each other).

**Alternatives considered**

Pinning CLI tool versions instead of the weekly epoch — more
deterministic, but adds a version-bump chore; the weekly epoch preserves
current freshness semantics with bounded staleness. Keeping type=gha
with `mode=min` — smaller cache but loses intermediate-stage reuse,
which is where most of the win is.

**Roadmap alignment**

Not on ROADMAP.md; CI/publishing speed improvement only.

## What Changed

- `Dockerfile`: the production stage's tool/OS `RUN` (npm --global CLIs,
apt, `/paperclip` setup) moves above `COPY --from=build /app /app`; new
`CLI_TOOLS_CACHE_EPOCH` arg consumed by that layer. The `cloud` stage is
unaffected — it only layers plugin dists on top of the finished
production stage.
- `.github/workflows/docker.yml`: both jobs stamp the ISO week into
`CLI_TOOLS_CACHE_EPOCH`, and both switch `cache-from/cache-to` from
`type=gha` to `type=registry` with per-job refs.
- Includes the one-line amd64-only cloud-variant commit from #10570 so
the two PRs can't conflict; if #10570 merges first, this PR rebases down
to a single commit automatically.

## Verification

- Image content is unchanged by layer reordering: the moved `RUN`
references nothing from `/app`, and Docker layer ordering only affects
caching, not the final filesystem (tool installs and app copy touch
disjoint paths).
- The cache ref is written only by this workflow — `docker.yml` runs on
master/tag pushes, never on PRs — so the workflow's existing "no shared
caches into build inputs" supply-chain stance is unchanged (BuildKit
layer cache was already accepted via type=gha; the registry backend has
the same writer trust).
- Runtime proof lands with the first two master builds after merge: the
first warms the cache, the second should show the tool layer and
deps/build stages as CACHED in the build log, with wall clock dropping
accordingly. I'll be watching those as part of managed-deploy work.

## Risks

- Low. Worst case the registry cache misses (cold-build behavior, same
as today). The weekly epoch means CLI tools update at most a week late
inside images; a release built mid-week ships the tools from that week's
first build. Cache refs add two small artifacts to ghcr.

## Model Used

Claude Fable 5 (`claude-fable-5`, extended thinking, via Claude Code
with tool use and code 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 (no test-affecting changes)
- [x] I have added or updated tests where applicable (n/a — build config
and layer ordering only)
- [x] I have updated relevant documentation to reflect my changes
(in-file comments document both mechanisms)
- [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
2026-07-31 14:47:25 -07:00
Devin Foley ce40343b9c
build: publish the cloud image variant for amd64 only (#10570)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Published container images are how both self-hosted users and
managed-deployment hosts run it
> - The repository publishes two variants: the self-hosted image and a
cloud variant for managed deployments
> - The cloud variant was built for amd64+arm64, but its only consumers
are managed-deployment hosts, which run amd64
> - The QEMU-emulated arm64 half dominates the build's wall clock,
delaying every merge-to-deployable-image cycle
> - This pull request drops arm64 from the cloud variant only, keeping
the self-hosted image multi-arch
> - The benefit is roughly halving the time from merge to a deployable
cloud image, with no change for any actual consumer

## Linked Issues or Issue Description

No existing public issue — inline description following the feature
request template:

**Subsystem affected**

CI / release publishing (docker workflow)

**Problem or motivation**

The cloud image variant builds for `linux/amd64,linux/arm64`, but the
arm64 half runs under QEMU emulation and dominates the job's wall clock
— while no consumer of the cloud variant runs arm64 (managed-deployment
hosts are amd64). Every deploy iteration pays ~double the necessary
build time.

**Proposed solution**

Build the cloud variant amd64-only. The self-hosted image keeps
`amd64+arm64` so ARM users (Apple Silicon, ARM servers) are unaffected.

**Alternatives considered**

Keeping multi-arch but building arm64 on native arm64 runners with a
manifest merge — faster than QEMU and worth doing for the self-hosted
image if its build time becomes a pain point, but unnecessary complexity
for a variant with no arm64 consumers.

**Roadmap alignment**

Not on ROADMAP.md; CI/publishing speed improvement only.

## What Changed

- `.github/workflows/docker.yml`: the `build-and-push-cloud` job's
`platforms` is now `linux/amd64` (with a comment explaining why). The
self-hosted `build-and-push` job is untouched.

## Verification

- Build-config-only change; the workflow runs on merge to master. The
published `-cloud` manifest will be amd64-only, which its consumers
already pull.
- No test changes: nothing at runtime differs on any platform that
actually runs the image.

## Risks

- Low. If an arm64 consumer of the cloud variant ever appears (e.g.
local `docker run` on Apple Silicon for debugging), it would fall back
to emulation on the consumer's machine or need this reverted — a
one-line change. The self-hosted image's platform matrix is unchanged.

## Model Used

Claude Fable 5 (`claude-fable-5`, extended thinking, via Claude Code
with tool use and code 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 (no test-affecting changes)
- [x] I have added or updated tests where applicable (n/a — CI platform
matrix only)
- [x] I have updated relevant documentation to reflect my changes
(in-workflow comment documents the rationale)
- [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
2026-07-31 13:41:44 -07:00
Devin Foley 521271ebb7
build: bake the build commit into published images (#10566)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Instances commonly run from published container images, and
operators need to observe which build a container actually serves
> - `/api/health` now reports the running build commit, and server-info
already falls back to `PAPERCLIP_BUILD_COMMIT` when git is unavailable
> - But published images carry no `.git` and never received
`PAPERCLIP_BUILD_COMMIT`, so containers report `commit: null` — verified
live against a current image
> - That leaves the new deployment-verification field inert exactly
where it matters most: containerized deploys
> - This pull request bakes the exact build commit into both image
variants at build time, mirroring how `PAPERCLIP_BUILD_VERSION` is
already stamped
> - The benefit is that containers report their true commit on
`/api/health`, so deploy tooling can verify a rollout actually shipped

## Linked Issues or Issue Description

Companion to #10563 (which exposed the `commit` field on `/api/health`).
Inline description following the bug report template:

**What happened?**

A container from a published image responds to `GET /api/health` with
`"commit": null`. The image has no `.git` directory and the
`PAPERCLIP_BUILD_COMMIT` fallback that `server-info` supports is never
provided at build time, so git metadata resolves as unavailable.

**Expected behavior**

A container reports the commit it was built from, the same way it
already reports its build version via the baked
`PAPERCLIP_BUILD_VERSION`.

**Steps to reproduce**

Run any published image (e.g.
`ghcr.io/paperclipai/paperclip:sha-c4f6264-cloud`) and `curl
/api/health` — `commit` is `null` even though the build commit is known
at image-build time.

**Paperclip version or commit**

`sha-c4f6264-cloud` (first image containing #10563).

## What Changed

- `Dockerfile`: new `PAPERCLIP_BUILD_COMMIT` build arg, exported as an
ENV in the production stage (the `cloud` stage inherits it), directly
parallel to `PAPERCLIP_BUILD_VERSION`. Empty for local `docker build`,
which keeps the normal fallbacks.
- `.github/workflows/docker.yml`: both build jobs pass
`PAPERCLIP_BUILD_COMMIT=${{ github.sha }}`.

## Verification

- Reviewed the plumbing end-to-end: `build-commit.ts` reads
`PAPERCLIP_BUILD_COMMIT` (validated as a full SHA), `server-info.ts`
`readGitInfo` falls back to it when the git CLI fails, producing
`available: true, fullSha` — which `/api/health` surfaces as `commit`.
- Verified live that a current published image reports `commit: null`;
this change repairs that on the next build. Post-merge, the first master
image should report its commit — I'll be verifying that as part of
managed-deploy validation.
- No test changes: the fallback path is already covered by existing
server-info tests; this PR only supplies the env at image build.

## Risks

- Low. Two build-time stamps; no runtime code changes. A wrong SHA would
only mislabel the build (same failure mode `PAPERCLIP_BUILD_VERSION`
already carries), and `${{ github.sha }}` is the exact commit the
workflow builds.

## Model Used

Claude Fable 5 (`claude-fable-5`, extended thinking, via Claude Code
with tool use and code execution); diagnosis included live probes of a
running container's `/api/health`.

## 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 (no test-affecting changes;
server suites unaffected)
- [x] I have added or updated tests where applicable (n/a — build-time
stamps only)
- [x] I have updated relevant documentation to reflect my changes
(Dockerfile comments document the arg)
- [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
2026-07-31 13:01:52 -07:00
Nicky Leach 131d476a7e
fix(ci): make PR-template inline-description contract explicit (#10558)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Contributors use the PR template to describe changes before review
> - The linked-issue gate reads literal template labels, not freeform
prose
> - The template did not state that rule, so a good prose summary could
fail on first submission
> - The gate also skipped two issue template paths that the PR template
already points to
> - This pull request makes the template and the gate match the same
contract
> - The benefit is that a good-faith author can pass the check on the
first try

## Linked Issues or Issue Description

No public issue exists.

Related public PR: #7762.

The problem is a mismatch between the PR template and the linked-issue
gate.
The template gave a bare placeholder and did not explain the
literal-label rule.
The gate also missed the enhancement and docs issue templates.

## What Changed

- Replaced the bare PR-template placeholder with labeled inline
skeletons for bug, feature, and adapter paths.
- Added one sentence that says the gate reads literal labels on separate
lines.
- Added the enhancement and docs issue template field sets to the
linked-issue gate.
- Added and updated tests for prose-only bodies, template skeleton
bodies, and extra issue template coverage.

## Verification

- `node --test .github/scripts/tests/check-pr-linked-issue.test.mjs`
- The branch contains one commit:
`561f1ed3a1434ed4562306f74d40968163ef1444`

## Risks

Low risk.
The three-field minimum stays in place.
The main change is clearer author guidance in the PR template.

## Model Used

OpenAI Codex, GPT-5, 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 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 and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 09:46:26 -07:00
Dotta 2dca2df71f
docs: require Simplified Technical English for PR text (#10447)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Many contributors are AI agents, and they write the pull request
text.
> - PR descriptions vary in clarity, and long or ambiguous prose slows
down review.
> - Simplified Technical English (ASD-STE100) is a controlled language
that makes technical text short, clear, and unambiguous.
> - This pull request adds one line to `CONTRIBUTING.md` and one line to
the pull request template. Both lines instruct the author to write PR
text in Simplified Technical English (ASD-STE100).
> - The benefit is clearer, faster-to-review pull request descriptions.

## Linked Issues or Issue Description

No related GitHub issue exists. This is a small documentation change. It
sets a writing-style rule for pull request text: authors must use
Simplified Technical English (ASD-STE100).

## What Changed

- Add one line to `CONTRIBUTING.md` (in "Writing a Good PR message")
that requires Simplified Technical English (ASD-STE100).
- Add one comment line to `.github/PULL_REQUEST_TEMPLATE.md` that gives
the same instruction to PR authors.

## Verification

- Read the two changed files. Confirm each new line is present and
correct.
- `git diff --stat origin/master` shows only the two files, with 4
inserted lines.

## Risks

Low risk. The change is documentation only. It adds guidance text and
does not change code or behavior.

## Model Used

Claude Opus 4.8 (claude-opus-4-8), 1M context window, extended thinking,
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 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
- [ ] 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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-29 13:50:15 -05:00
Nicky Leach ca92f727c5
ci: publish the cloud image in its own parallel job (#10408)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The CI workflow is responsible for producing and publishing the
Docker images that power Paperclip deployments
> - The cloud image publish was previously coupled to the stock publish
job, so a failure or delay in one path could gate the other
> - That coupling makes the release pipeline less resilient than it
needs to be
> - This pull request gives the cloud publish its own top-level job so
both publishes can run in parallel without a `needs:` dependency
> - The benefit is better failure isolation and less wasted time when
one publish path is slow or broken

## Linked Issues or Issue Description

No public GitHub issue was found for this change.

Problem statement:
- The cloud image publish was implemented as trailing work inside the
stock publish job.
- That setup meant the cloud publish could be delayed or skipped if the
stock job failed early.
- The desired behavior is for the cloud publish to run independently so
a failure in one publish path does not gate the other.

Proposed solution:
- Split the cloud publish into its own top-level workflow job.
- Keep the same cloud-specific build settings and cache behavior.
- Preserve the existing top-level concurrency behavior.

Alternatives considered:
- Keeping both publishes in one job with conditionals or later steps.
Rejected because it still couples success and runtime between the two
publish paths.

## What Changed

- Split the cloud image publish into a separate top-level Docker
workflow job.
- Removed the dependency coupling so the cloud job does not need the
stock job.
- Expanded the drift-guard test to assert the two-job structure and the
absence of `needs:` on the cloud job.

## Verification

- The workflow YAML was parsed successfully and confirmed to contain two
jobs: `build-and-push` and `build-and-push-cloud`.
- The cloud job was confirmed to have no `needs:` entry.
- The drift-guard assertions were reproduced in a dependency-free
harness and passed.
- PR #10408 completed GitHub Actions with all required checks green,
including the e2e shards.
- Greptile review completed at 5/5 with no unresolved comments.
- No documentation files changed because this is a workflow/test-only
change.

## Risks

- The workflow now duplicates the prep steps across two runners, so any
shared setup change must be kept in sync between both jobs.
- The new job increases workflow surface area slightly, which can make
future maintenance more verbose.
- Overall risk is low because the change is limited to CI orchestration
and test coverage.

## Model Used

OpenAI Codex (GPT-5, tool-using code assistant)

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-28 15:38:01 -07:00
Nicky Leach db02ca7402
ci: keep in-flight docker builds from being cancelled (#10403)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The repository uses GitHub Actions workflows to build and publish
Docker images
> - A workflow-level concurrency policy controls whether newer pushes
cancel in-flight builds
> - The current job-level setting can cancel a running image build
before it finishes publishing
> - That leaves the Docker image pipeline brittle when a new push
arrives during an active publish
> - This pull request moves concurrency to the workflow level and
disables cancel-in-progress so running builds finish
> - The benefit is that only pending work is superseded, while a build
already publishing is allowed to complete

## Linked Issues or Issue Description

No public GitHub issue exists for this change. This PR addresses the
Docker workflow concurrency behavior directly: it ensures in-flight
image builds are not cancelled by newer pushes, while still serializing
builds per ref.

## What Changed

- Moved the Docker workflow concurrency block from the job level to the
workflow level.
- Set `cancel-in-progress: false` so an active build can finish
publishing.
- Added a drift-guard test that parses `.github/workflows/docker.yml`
and asserts the workflow-level concurrency policy remains `false`.

## Verification

- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/cloud-image-bundled-plugins.test.ts`
- `python3 -c "import yaml;
yaml.safe_load(open('.github/workflows/docker.yml'))"`
- Verified the fetched remote branch contains a single commit on top of
`origin/master`.
- Searched GitHub for duplicate or related PRs and issues; none found.
- Checked `ROADMAP.md` and did not find overlapping planned core work.

## Risks

- Low risk: the change is limited to workflow concurrency behavior and a
targeted test assertion.
- If the workflow concurrency key is changed later, the drift-guard test
will fail and require an update.

## Model Used

OpenAI Codex (GPT-5, tool use; context window not surfaced 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] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-28 15:08:17 -07:00
Devin Foley d1b9448b57
fix(server): stamp the real build version into images instead of the package.json placeholder (#10257)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work; it ships as a Docker image that self-hosters and managed
deployments run.
> - The server resolves its own version at runtime in
`server/src/version.ts` (`resolveServerVersion()`), which feeds
analytics and the server debug panel.
> - That resolver derives the real version from `git describe`, and
falls back to `server/package.json`'s `version` when git isn't
available.
> - But `server/package.json`'s version is a static placeholder — CI
only stamps the real CalVer at publish, so in source it is never the
real version (currently `0.3.1`).
> - A Docker image has no `.git` (it's dockerignored), so `git describe`
can't run inside it. Every image therefore falls back to the placeholder
and reports `0.3.1` in analytics and the debug panel, regardless of
which commit it was built from.
> - This PR computes the real version once on the CI build runner (where
`.git` and tags exist), bakes it into the image, and has
`resolveServerVersion()` prefer that stamp when `git describe` is
unavailable.
> - The benefit: self-hosted and cloud images report their true version
instead of a misleading placeholder, with no change to dev checkouts,
`git describe`-based resolution, or local `docker build`.

## Linked Issues or Issue Description

No public issue exists — describing the bug inline (per the bug report
template).

**What happened?**
Docker images built from `master` (and release tags) report the server
version as the `0.3.1` placeholder in analytics and the server debug
panel, instead of the real version of the commit the image was built
from.

**Expected behavior**
An image reports the real version of its build commit (e.g.
`2026.722.0+51.git.<sha>`), so operators can tell which build is
running.

**Steps to reproduce**
1. Build the server Docker image from any `master` commit (the `Docker`
workflow, `production` target).
2. Run the image and open the server debug panel (or inspect the version
reported to analytics).
3. Observe the version is `0.3.1` rather than the commit's real version.

**Root cause**
`resolveServerVersion()` derives the real version from `git describe`,
but the image has no `.git` (dockerignored), so it falls back to
`server/package.json`'s `version` — a static placeholder CI only
replaces with the real CalVer at publish time. Nothing bakes the real
version into the image.

**Paperclip version or commit:** reproduces on `master` (`4c55f0d8`) and
any published image.
**Deployment mode:** self-hosted and managed (both the `production` and
`-cloud` images).
**Installation method:** Docker image (`ghcr.io/paperclipai/paperclip`).

**Related PRs (dedup search):** #9103 (merged — added the `git
describe`-based source-install resolution this builds on) and #9637
(closed). Neither bakes a version into the image; this PR closes that
gap. No duplicate found.

## What Changed

- **`.github/workflows/docker.yml`** — checkout with full history + tags
(`fetch-depth: 0`), and a new `Compute build version` step that runs
`git describe --tags --match 'v*' --long --dirty` on the pristine runner
checkout. The result is passed as a `PAPERCLIP_BUILD_VERSION` build-arg
to both the `production` and `-cloud` image builds.
- **`Dockerfile`** — the `production` stage takes an `ARG
PAPERCLIP_BUILD_VERSION` (default empty) and bakes it into the runtime
`ENV`; the `cloud` stage inherits it via `FROM production`.
- **`server/src/build-version.ts`** (new) — `readBuildVersion()` /
`parseBuildVersion()`, mirroring `build-commit.ts`: reads
`PAPERCLIP_BUILD_VERSION` (or a `.paperclip-build-version` file) as a
single-token stamp.
- **`server/src/version.ts`** — `resolveServerVersion()` prefers the
baked build version when `git describe` is unavailable, parsing it with
the same rules as a live checkout (`parseGitDescribeVersion`), and
falling through to the existing `build-commit` stamp and package version
when unset. A live checkout's `git describe` still wins over any stamp.
- Tests for the new behavior and the precedence.

## Verification

- `pnpm --filter @paperclipai/plugin-sdk ensure-build-deps && tsc
--noEmit` in `server/` — clean.
- `vitest run server/src/__tests__/version.test.ts
server/src/__tests__/build-version.test.ts` — **23 tests pass**,
covering: stamped version used when git describe fails, stamp parsed to
real CalVer, stamp preferred over the build-commit fallback, on-tag
stamp collapses to the release version, a pre-resolved stamp used
verbatim, and a live git describe still winning over a stamp.
- `git describe --tags --match 'v*' --long` for this commit →
`v2026.722.0-51-g<sha>`, which `resolveServerVersion()` reports as
`2026.722.0+51.git.<sha>` — no longer `0.3.1`.
- Not run locally: the full multi-arch image build (CI-only). The
workflow change is verified by inspection; the version is computed on
the pristine checkout before any lockfile refresh, so it carries no
spurious `-dirty`.

## Risks

Low. Additive and image-only:
- No runtime behavior changes for dev checkouts (git describe still
primary and wins over any stamp) or for local `docker build` (empty arg
→ server keeps its existing fallbacks).
- Not a breaking change; no schema or API surface. The stamp is
informational (version reporting only).
- `fetch-depth: 0` makes the release-image checkout fetch full
history/tags — a modest cost on a workflow that already runs at release
cadence with a 60-minute budget.
- Rollback: revert the commit; images simply return to reporting the
placeholder.

## Model Used

Claude Opus 4.8 (`claude-opus-4-8`, 1M-context variant), extended
thinking, with tool use / code execution — agentic edits, `tsc` +
`vitest` runs, and a `git describe` resolution check.

## 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 (bugfix, not core feature work)
- [x] I have searched GitHub for duplicate or related PRs and linked
them above (#9103, #9637 — related, not duplicates)
- [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 (`fix/build-version-stamp`)
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 docs affected; behavior is documented inline in `version.ts`
/ `build-version.ts` and the workflow/Dockerfile)
- [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>
2026-07-25 10:06:28 -07:00
Devin Foley 965a827ee7
feat(docker): publish a cloud image variant with built bundled plugins (#10157)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Managed (cloud-hosted) deployments configure instances through
`PAPERCLIP_MANAGED_CONFIG`, including a `plugins.autoInstall` key list
that the boot-time installer resolves against the bundled plugin catalog
> - The installer requires each bundled plugin's `dist/manifest.js`
(`server/src/services/bundled-plugins.ts`), but the published image only
ships the sandbox providers' *source* — they are intentionally excluded
from the pnpm workspace, and the Dockerfile never builds them
> - Every managed auto-install therefore logs `bundled plugin bundle not
present; skipping auto-install` and no sandbox provider can be
provisioned through managed config
> - Baking built plugins into the single published image would fix it
but makes every self-hosted pull carry the providers' `node_modules` for
a managed-only mechanism
> - This pull request adds a `cloud` Dockerfile target extending
`production` with built bundled plugins — parameterized by build arg and
currently just `daytona` — published alongside the default image with a
`-cloud` tag suffix
> - The benefit is working plugin auto-provisioning for managed
deployments while the self-hosted image stays byte-identical and the
cloud variant only carries what is actually deployed

## Linked Issues or Issue Description

Fixes #10158 (filed for this problem; no prior issue existed — searched
for duplicate/related PRs and issues around bundled plugins, docker
image variants, and auto-install). Summary: **What happened:** on a
managed instance with `plugins.autoInstall: ["daytona"]` delivered via
`PAPERCLIP_MANAGED_CONFIG`, boot logs `bundled plugin bundle not
present; skipping auto-install` with `pluginPath:
/app/packages/plugins/sandbox-providers/daytona`, and the plugin is
never installed. **Expected:** the advertised bundled-catalog keys are
installable from the published image. **Why:** the image ships plugin
source without `dist/` — nothing in the Dockerfile builds the
workspace-excluded sandbox providers.

## What Changed

- `Dockerfile`: new `cloud-plugins` stage (based on `build`, so
devDependencies are available for `tsc`) that installs and builds each
provider named in the `CLOUD_BUNDLED_PLUGINS` build arg standalone
(`pnpm install --ignore-workspace --no-lockfile && pnpm build`, exactly
as the providers' READMEs prescribe), asserting `dist/manifest.js`
exists per plugin and failing loudly on unknown names; new `cloud` stage
= `production` + the built plugin tree. The arg defaults to `daytona` —
the only provider managed deployments auto-install today; every entry
adds its `node_modules` to the image, so the list grows only with actual
need (a one-line workflow change).
- `.github/workflows/docker.yml`: the existing build step is pinned to
`target: production` (without this, the new trailing stage would
silently become the default build target — this pin is what keeps the
self-hosted image identical); new metadata + build-push steps publish
the `cloud` target (with `CLOUD_BUNDLED_PLUGINS=daytona`) under the same
tag set with a `-cloud` suffix (`sha-<short>-cloud`, `latest-cloud`,
`<version>-cloud`), same schema labels, reusing the GHA layer cache

## Verification

- All seven sandbox providers build standalone from a clean checkout
with the exact commands the new stage runs, each producing
`dist/manifest.js` — so the current `daytona` default works and future
list additions are known-good
- The stage's shell loop was dry-run against the checkout (directory
existence + per-plugin assertion logic)
- Workflow YAML lints clean
- **Not run:** a full multi-arch `docker build` (no local docker
daemon). The `cloud` stage is additive and the default target is pinned,
so the risk is contained to the new build step; the first master build
after merge proves it end-to-end

## Risks

- Self-hosted behavior: unchanged. The default image build is pinned to
the `production` target, which produces the same layers as before this
change; the `cloud` stages run only for the new build step.
- The plugin installs in the `cloud-plugins` stage use `--no-lockfile`
(the providers are workspace-excluded and lockfile-less by design), so
plugin dependency resolution is not pinned at image-build time. This
mirrors the existing Plugins-page install path, which resolves from npm
at install time.
- CI cost: one additional build-push per master push. It reuses the
layer cache from the production build, so the marginal work is the
single plugin's build layers.
- An unknown name in `CLOUD_BUNDLED_PLUGINS`, or a provider that stops
producing `dist/manifest.js`, fails the cloud build loudly rather than
publishing a broken variant.

## Model Used

Claude (Anthropic), model ID `claude-fable-5[1m]` via Claude Code CLI —
extended thinking and tool use (code edits, standalone plugin build
verification, workflow lint).

## Checklist

- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] Self-hosted behavior unchanged (default build target pinned to
`production`)
- [x] One clear change: publish a cloud image variant with built bundled
plugins
2026-07-24 08:22:34 -07:00
Devin Foley 14f20be92b
ci: harden Docker image build workflow against lockfile drift and runner disk exhaustion (#10142)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Docker image publish workflow (`.github/workflows/docker.yml`)
builds and pushes the multi-arch `ghcr.io` image on every master push,
so users pulling the container get the latest code
> - The two newest master runs of that workflow failed, so no images
have been published past a recent master commit
> - The failures had two distinct causes: run
[30054330748](https://github.com/paperclipai/paperclip/actions/runs/30054330748)
hit `ERR_PNPM_LOCKFILE_CONFIG_MISMATCH` (committed `pnpm-lock.yaml`
drifted from `patchedDependencies` in package metadata), and run
[30050197392](https://github.com/paperclipai/paperclip/actions/runs/30050197392)
hit `no space left on device` during the multi-arch buildx export
> - This pull request hardens the publish job against both failure
modes: it refreshes the lockfile (lockfile-only, guarded) before the
build, and frees runner disk space before buildx setup
> - The benefit is that image publishing keeps working through routine
lockfile drift and the growing multi-arch build footprint, so `ghcr.io`
images stay current with master

## Linked Issues or Issue Description

- Refs #8286 — same class of Docker-build lockfile mismatch failure
- Refs #8827 — pnpm 9.15.x pin / lockfile regeneration discussion
- Note: the immediate lockfile drift on master was fixed by #10132; the
refresh step here prevents the *next* drift from breaking image
publishing again

## What Changed

- Added a pnpm + Node setup and a **"Refresh lockfile for Docker build
context"** step to the image job in `.github/workflows/docker.yml`: runs
`pnpm install --lockfile-only --ignore-scripts --no-frozen-lockfile`,
exits cleanly if nothing changed, and **fails the job if anything other
than `pnpm-lock.yaml` was modified** by the refresh
- Added a **"Free runner disk"** step (before buildx setup) that prunes
the pnpm store, apt caches, preinstalled toolchains
(`/usr/share/dotnet`, Android SDK, Swift, Boost, PowerShell, GHC,
CodeQL/PyPy/Ruby toolcache), and dangling Docker state, logging `df -h`
before/after
- No changes outside the workflow file (54 added lines, nothing removed)

## Verification

- Pulled the logs of both failed master runs and matched each failure to
the step that addresses it:
[30054330748](https://github.com/paperclipai/paperclip/actions/runs/30054330748)
failed with `ERR_PNPM_LOCKFILE_CONFIG_MISMATCH`,
[30050197392](https://github.com/paperclipai/paperclip/actions/runs/30050197392)
failed with `no space left on device` during the buildx export
- Confirmed pnpm `9.15.4` in the new setup step matches the repo
`packageManager` field and the version used in the Dockerfile, so the
refreshed lockfile is generated by the same pnpm the image build
consumes
- Validated the workflow YAML parses cleanly
- The workflow triggers on master pushes / manual dispatch; the
definitive check is the first master run after merge — reviewers can
also `workflow_dispatch` it from this branch if desired

## Risks

- The lockfile refresh runs with `--ignore-scripts` and a guard that
aborts on any non-lockfile change, so it cannot silently pull unexpected
code into the image; worst case it fails the job with a clear diff
- The published image could be built from a refreshed lockfile that
differs from the committed one when drift exists — that keeps publishing
alive but can mask drift on master, which still needs the committed
lockfile fixed (as #10132 did)
- Disk cleanup removes preinstalled toolchains only on the ephemeral
runner for this job; other jobs/workflows are unaffected
- Low risk overall: additive steps in a single workflow file

## Model Used

- Claude (Anthropic) — `claude-fable-5` (Claude Code agent harness,
extended thinking, tool use). Used to diagnose the failing CI runs from
logs, author the workflow changes, and prepare this PR.

## 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 (no runtime code touched;
workflow YAML validated — see Verification)
- [ ] I have added or updated tests where applicable (n/a — CI workflow
change)
- [x] I have updated relevant documentation to reflect my changes (none
needed)
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green (pending — will confirm once
checks run)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending review pass)
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-23 21:19:30 -07:00
Nicky Leach 58ae799dbd
fix(ci): regenerate lockfile for patch changes (#10132)
## Thinking Path

> - Paperclip uses GitHub Actions to keep generated lockfile changes
deterministic in CI
> - The workflow decides when to regenerate the lockfile based on
file/path changes
> - Patch changes can live under a top-level `patches/` directory, and
those changes also affect dependency resolution
> - If the workflow misses that path, CI can skip lockfile regeneration
when it should run
> - This pull request adds top-level `patches/` to the trigger so patch
updates participate in the existing lockfile regeneration flow
> - The benefit is that patch-related dependency changes continue to get
the same CI protection as the other manifest and workspace triggers

## Linked Issues or Issue Description

No public GitHub issue is linked here. The underlying problem is that
top-level `patches/` files are part of pnpm's dependency graph, but the
PR workflow's lockfile-regeneration gate only looked at package
manifests, workspace config, `.npmrc`, and `pnpmfile.*` changes. That
meant patch-only edits could skip `pnpm install --lockfile-only` and
leave downstream frozen-install jobs on a stale lockfile.

This PR keeps the existing manual lockfile edit guard in place. The
intended behavior is still: CI owns lockfile regeneration, and patch
changes are allowed to trigger that regeneration without letting
contributors commit `pnpm-lock.yaml` directly.

## What Changed

- Added top-level `patches/` to the PR workflow's dependency-resolution
trigger.
- Left the manual `pnpm-lock.yaml` edit blocker unchanged so CI still
owns lockfile regeneration.

## Verification

- `git diff --check .github/workflows/pr.yml`
- Verified the workflow path predicate matches
`patches/acpx@0.12.0.patch`, `package.json`,
`packages/shared/package.json`, `pnpm-workspace.yaml`, `.npmrc`,
`pnpmfile.cjs`, `pnpmfile.js`, and `pnpmfile.mjs`, while excluding
nested patch paths and unrelated files.

## Risks

- Low risk: this only broadens the workflow trigger set for lockfile
regeneration.
- The main behavioral change is that patch updates at the repository
root now participate in the same CI path as manifest and workspace
changes.

## Model Used

OpenAI Codex, GPT-5-based tool-using 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)
- [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
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-23 15:14:52 -07:00
Dotta 4e8cd757eb
fix(release): add npm publish crash diagnostics (#10041)
## Thinking Path

> - Paperclip publishes a coordinated set of packages through its
release workflows
> - Bundled packages use a pinned npm CLI so trusted publishing works
consistently
> - The canary publisher now crashes deterministically inside npm before
useful output reaches the workflow log
> - The npm debug log that contains the underlying failure disappears
with the hosted runner
> - This pull request upgrades the pinned publish CLI and preserves both
verbose HTTP activity and npm debug logs on failure
> - The benefit is that the plausible HTTP-layer fix ships immediately,
while any remaining CI-only failure becomes diagnosable

## Linked Issues or Issue Description

- **Problem:** The canary release workflow fails on the first bundled
package with `npm error Exit handler never called!` and no preceding
diagnostic output.
- **Expected behavior:** Bundled packages publish through trusted
publishing, or the workflow retains enough npm diagnostics to identify
the actual failure.
- **Reproduction:** Run the canary release workflow in GitHub Actions;
the failure reproduced on both attempts of run 29948506814.
- **Version/commit:** Current `master` after #10024 and #10030.
- **Deployment mode:** GitHub-hosted release workflow using Node.js 24
and npm trusted publishing.
- Related: #10024, #10030.

## What Changed

- Bumped the bundled publish CLI from npm 11.16.0 to npm 11.18.0.
- Added `--loglevel verbose` to bundled npm publish invocations.
- Dumped the last 300 lines of every npm debug log after failed canary
or stable publishes, with common registry credential forms redacted.
- Updated release assertions to pin npm 11.18.0 and verify verbose
logging.

## Verification

- `pnpm test:release-registry` — 66 tests passed.
- `bash -n scripts/release-lib.sh`.
- Parsed `.github/workflows/release.yml` with Python/PyYAML.
- Smoke-tested npm log redaction with representative Authorization,
`_authToken`, and token environment values.
- Smoke-tested npm debug-log redaction against Authorization,
`_authToken`, and `npm_token` examples.
- `git diff --check origin/master...HEAD`.
- The merge-triggered canary workflow remains the live
trusted-publishing verification.

## Risks

- Low code risk: changes are isolated to the release publisher and its
workflow diagnostics.
- npm 11.18.0 could expose a different registry/runtime regression;
failure-time debug log dumping makes that actionable.
- Verbose npm output increases release log volume but does not change
package contents or dist-tags; common credential forms are redacted
before debug logs are printed.

> 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.3 Codex, tool-enabled coding agent with repository
and shell execution; 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] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-22 14:48:54 -05:00
dependabot[bot] 18fe9486a0
build(deps): bump actions/setup-node from 6 to 7 (#9884)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 6
to 7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-node/releases">actions/setup-node's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>What's Changed</h2>
<h3>Enhancements:</h3>
<ul>
<li>Add cache-primary-key and cache-matched-key as outputs by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1577">actions/setup-node#1577</a></li>
<li>Migrate to ESM and upgrade dependencies by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1574">actions/setup-node#1574</a></li>
</ul>
<h3>Bug fixes:</h3>
<ul>
<li>Remove dummy NODE_AUTH_TOKEN export by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-node/pull/1558">actions/setup-node#1558</a></li>
<li>Only use <code>mirrorToken</code> in <code>getManifest</code> if
it's provided by <a
href="https://github.com/deiga"><code>@​deiga</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li>
</ul>
<h3>Documentation updates:</h3>
<ul>
<li>Add documentation for publishing to npm with Trusted Publisher
(OIDC) by <a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li>
<li>docs: Update restore-only cache documentation by <a
href="https://github.com/priya-kinthali"><code>@​priya-kinthali</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1550">actions/setup-node#1550</a></li>
<li>docs: Update caching recommendations to mitigate cache poisoning
risks by <a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1567">actions/setup-node#1567</a></li>
</ul>
<h3>Dependency update:</h3>
<ul>
<li>Upgrade <code>@​actions/cache</code> to 5.1.0, log cache write
denied by <a
href="https://github.com/jasongin"><code>@​jasongin</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/chiranjib-swain"><code>@​chiranjib-swain</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li>
<li><a href="https://github.com/deiga"><code>@​deiga</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li>
<li><a href="https://github.com/jasongin"><code>@​jasongin</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-node/compare/v6...v7.0.0">https://github.com/actions/setup-node/compare/v6...v7.0.0</a></p>
<h2>v6.5.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update <code>@​actions/cache</code> to 5.1.0 and add security
overrides for undici and fast-xml-parser by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1579">actions/setup-node#1579</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0">https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0</a></p>
<h2>v6.4.0</h2>
<h2>What's Changed</h2>
<h3>Dependency updates:</h3>
<ul>
<li>Upgrade <a
href="https://github.com/actions"><code>@​actions</code></a>
dependencies by <a
href="https://github.com/Copilot"><code>@​Copilot</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1525">actions/setup-node#1525</a></li>
<li>Update Node.js versions in versions.yml and bump package to v6.4.0
by <a
href="https://github.com/priya-kinthali"><code>@​priya-kinthali</code></a>
in <a
href="https://redirect.github.com/actions/setup-node/pull/1533">actions/setup-node#1533</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Copilot"><code>@​Copilot</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/setup-node/pull/1525">actions/setup-node#1525</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-node/compare/v6...v6.4.0">https://github.com/actions/setup-node/compare/v6...v6.4.0</a></p>
<h2>v6.3.0</h2>
<h2>What's Changed</h2>
<h3>Enhancements:</h3>
<ul>
<li>Support parsing <code>devEngines</code> field by <a
href="https://github.com/susnux"><code>@​susnux</code></a> in <a
href="https://redirect.github.com/actions/setup-node/pull/1283">actions/setup-node#1283</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8207627860"><code>8207627</code></a>
Migrate to ESM and upgrade dependencies (<a
href="https://redirect.github.com/actions/setup-node/issues/1574">#1574</a>)</li>
<li><a
href="04be95cf35"><code>04be95c</code></a>
Add cache-primary-key and cache-matched-key as outputs (<a
href="https://redirect.github.com/actions/setup-node/issues/1577">#1577</a>)</li>
<li><a
href="7c2c68d20d"><code>7c2c68d</code></a>
docs: Update caching recommendations to mitigate cache poisoning risks
(<a
href="https://redirect.github.com/actions/setup-node/issues/1567">#1567</a>)</li>
<li><a
href="6a61c0375d"><code>6a61c03</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/setup-node/issues/1569">#1569</a>
from jasongin/update-actions-cache-5.1.0</li>
<li><a
href="30eb73b41d"><code>30eb73b</code></a>
Resolve high-severity audit issues</li>
<li><a
href="4e1a87a501"><code>4e1a87a</code></a>
Update dist</li>
<li><a
href="360237f0c0"><code>360237f</code></a>
Strict equality</li>
<li><a
href="4f8aac5beb"><code>4f8aac5</code></a>
Bump <code>@​actions/cache</code> to 5.1.0, log cache write denied</li>
<li><a
href="f4a67bbeca"><code>f4a67bb</code></a>
Only use <code>mirrorToken</code> in <code>getManifest</code> if it's
provided (<a
href="https://redirect.github.com/actions/setup-node/issues/1548">#1548</a>)</li>
<li><a
href="0355742c94"><code>0355742</code></a>
Remove dummy NODE_AUTH_TOKEN export (<a
href="https://redirect.github.com/actions/setup-node/issues/1558">#1558</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/setup-node/compare/v6...v7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-node&package-manager=github_actions&previous-version=6&new-version=7)](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>
2026-07-21 12:04:06 -05:00
Devin Foley 1944c86153
fix(ci): preserve required e2e check for sharded runs (#9923)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The pull request workflow is the main merge gate for changes to that
app.
> - The Playwright e2e lane is expensive because every spec shares one
isolated server and runs serially.
> - Splitting that lane across runners shortens the critical path, but
the public required-check contract still needs a check named exactly
`e2e`.
> - This pull request shards the real e2e work while preserving a fast
aggregate `e2e` job for branch protection.
> - The benefit is a faster PR workflow without making otherwise-good
PRs unmergeable because a legacy required check disappeared.

## Linked Issues or Issue Description

No public GitHub issue exists for this CI follow-up.

Related prior CI work:

- Refs #8360
- Refs #9168
- Refs #9516

Bug report:

### What happened?

Sharding the PR e2e lane directly at the workflow job level changes the
emitted check names to shard-specific names, while existing branch
protection expects a check named exactly `e2e`.

### Expected behavior

The PR workflow should be able to run e2e specs across multiple runners
while still emitting a stable aggregate check named `e2e`.

### Steps to reproduce

1. Open a PR against `master`.
2. Run the PR workflow with the e2e lane split only as a matrix job.
3. Observe that the shard checks complete, but a required check named
exactly `e2e` never appears.

### Paperclip version or commit

Current `master`.

### Deployment mode

GitHub Actions pull request workflow.

## What Changed

- Added `scripts/e2e-shard.mjs`, which partitions default Playwright e2e
specs by recorded per-spec duration.
- Added `scripts/e2e-shard-durations.json` with measured e2e spec
durations so the slow smoke-lab spec does not dominate one runner.
- Split the PR workflow e2e lane into two `e2e_shards` matrix jobs and
added a fast aggregate job named exactly `e2e`.
- Added `scripts/__tests__/e2e-shard.test.mjs` to lock the shard
partition, ignored-spec sync, manifest coverage, and aggregate
required-check contract.

## Verification

- `node --test scripts/__tests__/e2e-shard.test.mjs`
- `node --test scripts/__tests__/run-vitest-stable-shard.test.mjs`
- `git diff --check upstream/master..HEAD`
- Searched GitHub for duplicate or related e2e-shard / required-check
PRs and issues before opening this PR; no direct duplicate was found.

## Risks

Low risk. The main risk is that the duration manifest can drift as specs
are added or runtimes change; missing specs fall back to the median
known duration, and the focused shard test catches empty, overlapping,
or badly imbalanced partitions.

## Model Used

OpenAI GPT-5 via Codex CLI coding agent, with shell/tool execution and
repository inspection.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-20 16:40:19 -07:00
Devin Foley fa4f900d1a
ci: label Docker images with their bundled schema migration set (#9908)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip publishes Docker images from this repo that self-hosters
and orchestration tooling deploy; the server refuses to start when its
database is missing any schema migration the build bundles
(`ensureMigrations`)
> - Anything that deploys these images therefore needs to know an
image's schema expectations *before* deploying it — today that requires
pulling the image or checking out the matching commit, both heavyweight
for tooling that just wants to answer "will this image boot against a
database migrated to N?"
> - Getting this wrong is expensive: an image ahead of the applied
schema crash-loops at startup and fails healthchecks after deployment
resources are already created
> - This pull request labels every published image with its bundled
migration set (last migration file and count), computed at build time
from `packages/db/src/migrations` in the same tree the image is built
from
> - The benefit is image/schema compatibility verification with two
cheap registry requests (manifest + config blob), no pull, and no drift
risk between label and image contents

## Linked Issues or Issue Description

No existing public issue; inline description per the feature request
template:

- **Subsystem affected**: Docker image publishing
(`.github/workflows/docker.yml`), `packages/db` migrations
- **Problem or motivation**: deployment tooling cannot cheaply determine
which schema migrations a published image expects; the only options are
pulling the image or checking out the matching commit. Deploying an
image whose bundled migrations exceed the applied schema makes the
server refuse to start, so this check is needed *before* resources are
created.
- **Proposed solution**: OCI labels
(`io.github.paperclipai.schema.last-migration`,
`io.github.paperclipai.schema.migration-count`), computed from the
migrations directory at build time via the existing
`docker/metadata-action` step. Keys use org-based reverse-DNS (the
GitHub org) so the label contract survives product-domain migrations.
- **Alternatives considered**: a schema manifest published beside the
image (second artifact to keep in sync — rejected); encoding schema info
in tags (tags already carry semver/sha meaning — rejected).
- **Roadmap alignment**: checked `ROADMAP.md` — no overlap with planned
core work; this is build metadata only.

## What Changed

- `.github/workflows/docker.yml`: a `Compute schema migration labels`
step (`ls` + `sort` over `packages/db/src/migrations/*.sql`) feeding two
custom labels into the existing `docker/metadata-action` step.

## Verification

- Workflow YAML validated locally.
- The label-computation commands run against the current tree produce
`last=0181_decision_training_retention_policy.sql`, `count=180`.
- After merge, verify with: fetch the image config blob for a fresh
`sha-*` tag from ghcr and confirm both `io.github.paperclipai.schema.*`
labels are present.

## Risks

- Low. Labels are metadata only; no change to image contents. If the
migrations directory ever moves, the label step fails the workflow
loudly (`ls` exits non-zero) rather than publishing wrong labels.

## Model Used

- Claude (Anthropic) — model id `claude-fable-5`, via the Claude Code
CLI harness with tool use (shell, file edits). Change authored and
verified agent-assisted, human-directed.

## 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 (YAML validation; label
commands — no app code changed)
- [x] I have added or updated tests where applicable (n/a — CI metadata
only)
- [x] I have updated relevant documentation to reflect my changes (n/a —
workflow comment documents the labels)
- [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
2026-07-20 15:54:31 -04:00
dependabot[bot] b41e992a12
build(deps): bump actions/cache from 5 to 6 (#9476)
Bumps [actions/cache](https://github.com/actions/cache) from 5 to 6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/cache/releases">actions/cache's
releases</a>.</em></p>
<blockquote>
<h2>v6.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update packages, migrate to ESM by <a
href="https://github.com/Samirat"><code>@​Samirat</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1760">actions/cache#1760</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v5...v6.0.0">https://github.com/actions/cache/compare/v5...v6.0.0</a></p>
<h2>v5.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump <code>@​actions/cache</code> to v5.1.0 - handle read-only cache
access by <a
href="https://github.com/jasongin"><code>@​jasongin</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1775">actions/cache#1775</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v5...v5.1.0">https://github.com/actions/cache/compare/v5...v5.1.0</a></p>
<h2>v5.0.5</h2>
<h2>What's Changed</h2>
<ul>
<li>Update ts-http-runtime dependency by <a
href="https://github.com/yacaovsnc"><code>@​yacaovsnc</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1747">actions/cache#1747</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v5...v5.0.5">https://github.com/actions/cache/compare/v5...v5.0.5</a></p>
<h2>v5.0.4</h2>
<h2>What's Changed</h2>
<ul>
<li>Add release instructions and update maintainer docs by <a
href="https://github.com/Link"><code>@​Link</code></a>- in <a
href="https://redirect.github.com/actions/cache/pull/1696">actions/cache#1696</a></li>
<li>Potential fix for code scanning alert no. 52: Workflow does not
contain permissions by <a
href="https://github.com/Link"><code>@​Link</code></a>- in <a
href="https://redirect.github.com/actions/cache/pull/1697">actions/cache#1697</a></li>
<li>Fix workflow permissions and cleanup workflow names / formatting by
<a href="https://github.com/Link"><code>@​Link</code></a>- in <a
href="https://redirect.github.com/actions/cache/pull/1699">actions/cache#1699</a></li>
<li>docs: Update examples to use the latest version by <a
href="https://github.com/XZTDean"><code>@​XZTDean</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1690">actions/cache#1690</a></li>
<li>Fix proxy integration tests by <a
href="https://github.com/Link"><code>@​Link</code></a>- in <a
href="https://redirect.github.com/actions/cache/pull/1701">actions/cache#1701</a></li>
<li>Fix cache key in examples.md for bun.lock by <a
href="https://github.com/RyPeck"><code>@​RyPeck</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1722">actions/cache#1722</a></li>
<li>Update dependencies &amp; patch security vulnerabilities by <a
href="https://github.com/Link"><code>@​Link</code></a>- in <a
href="https://redirect.github.com/actions/cache/pull/1738">actions/cache#1738</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/XZTDean"><code>@​XZTDean</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1690">actions/cache#1690</a></li>
<li><a href="https://github.com/RyPeck"><code>@​RyPeck</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1722">actions/cache#1722</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v5...v5.0.4">https://github.com/actions/cache/compare/v5...v5.0.4</a></p>
<h2>v5.0.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump <code>@actions/cache</code> to v5.0.5 (Resolves: <a
href="https://github.com/actions/cache/security/dependabot/33">https://github.com/actions/cache/security/dependabot/33</a>)</li>
<li>Bump <code>@actions/core</code> to v2.0.3</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v5...v5.0.3">https://github.com/actions/cache/compare/v5...v5.0.3</a></p>
<h2>v.5.0.2</h2>
<h1>v5.0.2</h1>
<h2>What's Changed</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions/cache/blob/main/RELEASES.md">actions/cache's
changelog</a>.</em></p>
<blockquote>
<h1>Releases</h1>
<h2>How to prepare a release</h2>
<blockquote>
<p>[!NOTE]
Relevant for maintainers with write access only.</p>
</blockquote>
<ol>
<li>Switch to a new branch from <code>main</code>.</li>
<li>Run <code>npm test</code> to ensure all tests are passing.</li>
<li>Update the version in <a
href="https://github.com/actions/cache/blob/main/package.json"><code>https://github.com/actions/cache/blob/main/package.json</code></a>.</li>
<li>Run <code>npm run build</code> to update the compiled files.</li>
<li>Update this <a
href="https://github.com/actions/cache/blob/main/RELEASES.md"><code>https://github.com/actions/cache/blob/main/RELEASES.md</code></a>
with the new version and changes in the <code>## Changelog</code>
section.</li>
<li>Run <code>licensed cache</code> to update the license report.</li>
<li>Run <code>licensed status</code> and resolve any warnings by
updating the <a
href="https://github.com/actions/cache/blob/main/.licensed.yml"><code>https://github.com/actions/cache/blob/main/.licensed.yml</code></a>
file with the exceptions.</li>
<li>Commit your changes and push your branch upstream.</li>
<li>Open a pull request against <code>main</code> and get it reviewed
and merged.</li>
<li>Draft a new release <a
href="https://github.com/actions/cache/releases">https://github.com/actions/cache/releases</a>
use the same version number used in <code>package.json</code>
<ol>
<li>Create a new tag with the version number.</li>
<li>Auto generate release notes and update them to match the changes you
made in <code>RELEASES.md</code>.</li>
<li>Toggle the set as the latest release option.</li>
<li>Publish the release.</li>
</ol>
</li>
<li>Navigate to <a
href="https://github.com/actions/cache/actions/workflows/release-new-action-version.yml">https://github.com/actions/cache/actions/workflows/release-new-action-version.yml</a>
<ol>
<li>There should be a workflow run queued with the same version
number.</li>
<li>Approve the run to publish the new version and update the major tags
for this action.</li>
</ol>
</li>
</ol>
<h2>Changelog</h2>
<h3>6.1.0</h3>
<ul>
<li>Bump <code>@actions/cache</code> to v6.1.0 to pick up <a
href="https://redirect.github.com/actions/toolkit/pull/2435">actions/toolkit#2435
Handle cache write error due to read-only token</a></li>
<li>Switch redundant &quot;Cache save failed&quot; warning to debug log
in save-only</li>
</ul>
<h3>6.0.0</h3>
<ul>
<li>Updated <code>@actions/cache</code> to ^6.0.1,
<code>@actions/core</code> to ^3.0.1, <code>@actions/exec</code> to
^3.0.0, <code>@actions/io</code> to ^3.0.2</li>
<li>Migrated to ESM module system</li>
<li>Upgraded Jest to v30 and test infrastructure to be ESM
compatible</li>
</ul>
<h3>5.0.4</h3>
<ul>
<li>Bump <code>minimatch</code> to v3.1.5 (fixes ReDoS via globstar
patterns)</li>
<li>Bump <code>undici</code> to v6.24.1 (WebSocket decompression bomb
protection, header validation fixes)</li>
<li>Bump <code>fast-xml-parser</code> to v5.5.6</li>
</ul>
<h3>5.0.3</h3>
<ul>
<li>Bump <code>@actions/cache</code> to v5.0.5 (Resolves: <a
href="https://github.com/actions/cache/security/dependabot/33">https://github.com/actions/cache/security/dependabot/33</a>)</li>
<li>Bump <code>@actions/core</code> to v2.0.3</li>
</ul>
<h3>5.0.2</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="55cc834586"><code>55cc834</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/cache/issues/1768">#1768</a>
from jasongin/readonly-cache</li>
<li><a
href="d8cd72f230"><code>d8cd72f</code></a>
Bump <code>@​actions/cache</code> to v6.1.0 - handle cache write error
due to RO token</li>
<li><a
href="2c8a9bd745"><code>2c8a9bd</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/cache/issues/1760">#1760</a>
from actions/samirat/esm_migration_and_package_update</li>
<li><a
href="e9b91fdc3f"><code>e9b91fd</code></a>
Prettier fixes</li>
<li><a
href="e4884b8ff7"><code>e4884b8</code></a>
Rebuild dist</li>
<li><a
href="10baf0191a"><code>10baf01</code></a>
Fixed licenses</li>
<li><a
href="e39b386c90"><code>e39b386</code></a>
Fix test mock return order</li>
<li><a
href="b692820337"><code>b692820</code></a>
PR feedback</li>
<li><a
href="60749128a4"><code>6074912</code></a>
Rebuild dist bundles as ESM to match type:module</li>
<li><a
href="5a912e8b4a"><code>5a912e8</code></a>
Fix lint and jest issues</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/cache/compare/v5...v6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/cache&package-manager=github_actions&previous-version=5&new-version=6)](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>
2026-07-14 10:02:46 -07:00
Dotta cec0fc249a
[codex] Parallelize release verify workflow (#9168)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Releases publish the same app and package set that operators
install, so release verification should keep full release-strength
coverage.
> - The release workflow currently verifies stable and canary releases
with one serial job that typechecks, runs all tests, and builds.
> - The PR workflow already proves the test surface can be split into
grouped general suites and serialized shards without changing coverage.
> - This pull request extracts the release verify work into a reusable
workflow and fans out the independent lanes.
> - The benefit is faster stable and canary release verification while
preserving the existing publish and preview gates.

## Linked Issues or Issue Description

No public GitHub issue exists for this CI improvement.

**Subsystem affected**

Cross-cutting (multiple of the above)

**Problem or motivation**

Release verification spends most of its wall time in a single serial
test step even though the same stable test surface is already
partitioned for PR CI. Stable dispatches and master-push canaries
therefore wait on one long runner after setup, typecheck, tests, and
build run sequentially.

**Proposed solution**

Add a reusable release verification workflow with parallel typecheck,
grouped general tests, serialized test shards, and build lanes. Have
both stable and canary release verification call it with the ref they
need to verify.

**Alternatives considered**

Keeping the serial `pnpm test:run` job preserves the old shape but keeps
stable and canary releases waiting on one long runner. Skipping
verification when a source SHA already has green CI would be faster, but
adds stale-check and lookup risk beyond this change.

**Roadmap alignment**

No overlapping item found in `ROADMAP.md`; this is release CI
maintenance.

**Additional context**

The new workflow keeps the release-strength full `pnpm -r typecheck`,
uses the existing stable test grouping/sharding entry points, and leaves
publish/preview jobs unchanged.

## What Changed

- Added `.github/workflows/release-verify.yml` as a `workflow_call`
workflow accepting a `ref` input.
- Split release verification into parallel `typecheck`, `general_tests`,
`serialized_tests`, and `build` jobs with 20-minute lane timeouts.
- Mirrored the PR workflow's stable test partition: `general-server`
shards 1-3, `general-workspaces-a`, `general-workspaces-b`, and four
serialized shards.
- Replaced `release.yml` `verify_canary` and `verify_stable` job bodies
with calls to the reusable workflow while leaving publish and preview
jobs unchanged.
- Added a Node test that guards the release workflow delegation and
split verify surface.

## Verification

- `actionlint 1.7.12 .github/workflows/release.yml
.github/workflows/release-verify.yml`
- `node ./scripts/release-package-map.mjs check`
- `node --test ./scripts/__tests__/release-verify-workflow.test.mjs
./scripts/__tests__/run-vitest-stable-shard.test.mjs`
- `git diff --check`

## Risks

- Release verification now starts more jobs per release event,
increasing total runner setup/install minutes. This matches the existing
PR CI tradeoff and should reduce release wall time substantially.
- The called workflow checks out the requested ref shallowly. That is
intentional for verify lanes; publish and preview jobs still retain
their existing full-history checkouts.

> 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 local tool-use mode with shell
execution, repository editing, GitHub connector access, and medium
reasoning.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-09 19:28:00 -05:00
scotttong c07e650cd7
feat(ui): single-source design tokens, visual regression suite, and theme retune (#9134)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Its UI is the operator's daily surface: task lists, boards, budgets,
agent status — all built on shadcn components and Tailwind
> - Visual values (colors, spacing, type sizes, radii) were hardcoded at
~1,600 call sites: the same "small gray label" was 9/10/11px depending
on the file, charts disagreed with chips about status colors, two
toggle-switch implementations coexisted in two greens, and there was no
visual regression coverage
> - This made the UI drift-prone and made any restyle a
hundreds-of-files project, which discourages design iteration
> - This pull request extracts visual values into a single token layer
in `ui/src/index.css`, adds a Storybook visual regression suite backed
by external immutable baseline archives, and then applies a deliberate
retune reviewed change-by-change on screenshot diffs
> - The benefit is that Paperclip's look becomes a config surface:
retheming is a token edit reviewed as a snapshot diff, drift is blocked
by a token gate, and future UI PRs can prove exactly what changed
visually without committing hundreds of PNGs

## Linked Issues or Issue Description

No existing public issue covers this work (searched "design tokens",
"visual regression", "design system" across issues and PRs). Related in
spirit: Refs #8982 (theming a hardcoded panel — a one-off instance of
the same problem class this PR addresses systematically).

**Problem (feature-request form):** UI visual values are hardcoded per
call site with no source of truth and no regression coverage;
consistency depends on reviewer memory, and restyling requires mass file
edits.
**Proposed solution (this PR):** a single token layer + enforcement gate
+ externally stored visual snapshot suite, then an intentional restyle
on top of that foundation.

## What Changed

- **Token extraction (zero visual change, machine-verified during
development):** committed codemods (`scripts/codemod-*.mjs`) moved
~1,600 hardcoded color/type/spacing/radius/shadow/misc values into named
tokens in a non-inline `:root` block of `ui/src/index.css`.
- **Visual regression suite:** `pnpm test:storybook-visual` covers 255
stories × light/dark = 510 Playwright screenshots at `maxDiffPixels: 0`,
plus new primitive-coverage stories and deterministic-render fixes.
- **External visual baselines:** committed PNG snapshots were removed.
`tests/storybook-visual/baseline-manifest.json` pins an immutable
archive URL/hash/size/count, and `scripts/storybook-visual-baseline.mjs`
handles `download`, `verify`, `pack`, and trusted maintainer `upload`
flows.
- **Opt-in visual CI artifacts:** added a `Storybook Visual` workflow
that runs on manual dispatch or PRs labeled `storybook-visual`,
downloads/verifies the baseline, runs Playwright, and uploads Playwright
report/test-result artifacts for review. Normal PR runs do not mutate
baseline objects.
- **Token gate:** `pnpm check:token-gates` — zero hex literals, zero
arbitrary bracket values, zero raw font-sizes in `ui/src/components/**`
and `ui/src/pages/**`, with a documented inline allowlist for legitimate
opt-outs.
- **Theme retune (intentional, snapshot-reviewed):** new base theme
values; radius ladder derived from a single `--radius` knob; micro-type
cluster collapsed to a named ladder (`--text-nano/micro/compact` +
Tailwind `text-xs`/`text-sm`); letter-spacing collapsed to named steps.
- **One status-color vocabulary:** charts, quota/budget bar fills,
RUNNING/live chips, and liveness indicators all use the canonical
`--status-*` hues. Light-mode legibility fixes for red alert surfaces
that used dark-tuned text classes.
- **One switch:** `ToggleSwitch` restyled to the registry capsule form,
second hand-rolled implementation removed, and all call sites unified.
- **Docs:** `DESIGN.md` is the design contract; `doc/design/` holds
audit reports, decision logs, and updated guidance for external baseline
review/update workflows.
- Dead code removed (`agentStatusBadge` duplicate map), byte-identical
contrast constants consolidated, semantic renames
(`--project-seed`/`--project-none`, `--liveness-blue`).

## Verification

- `pnpm check:token-gates` — 3/3 gates CLEAN during the design-system
run
- `pnpm typecheck` && `pnpm --filter @paperclipai/ui build` — green
during the design-system run
- `node --test scripts/__tests__/storybook-visual-baseline.test.mjs` —
pass after external-baseline rework
- `pnpm exec tsc --noEmit --pretty false --module NodeNext
--moduleResolution NodeNext --target ES2022 --types
node,@playwright/test tests/storybook-visual/playwright.config.ts
tests/storybook-visual/storybook-visual.spec.ts` — pass after
external-baseline rework
- `git diff --check origin/pr/9134..HEAD` — pass after external-baseline
rework
- `find tests/storybook-visual -type f -name '*.png' -print | wc -l` —
`0`
- `node scripts/storybook-visual-baseline.mjs verify` — intentionally
fails closed until the first trusted maintainer publishes the baseline
archive and updates `baseline-manifest.json`

## Risks

- **Large but shallow:** the PR still touches many UI files due to
mechanical token extraction and retune work, but committed PNG snapshot
churn has been removed from the branch.
- **Baseline publication required before the visual suite can pass in
clean clones:** the manifest currently has placeholder archive metadata.
A trusted maintainer must publish the first immutable archive, then
update `baseline-manifest.json`.
- **Rendering platform variance:** the external baseline should be
captured in the documented Linux/Chromium environment. Future CI runs
verify against the pinned archive and fail closed on checksum/count
mismatch.
- **Visual CI is opt-in while stabilizing:** add the `storybook-visual`
label or dispatch the workflow manually to produce downloadable
Playwright report/test-result artifacts.
- **Scheduled follow-ups, deliberately out of scope:** Tailwind palette
classes map to semantic tokens in a dedicated pass; card/pill component
consolidation; ESLint ratchet. Tracked in
`doc/design/DECISION-SHEET.md`.

## Model Used

Claude Fable 5 (Anthropic, `claude-fable-5`, Mythos-class tier) with
extended thinking, running in Claude Code with tool use; mechanical
phases delegated to Claude Sonnet subagents. Follow-up external-baseline
rework assisted by OpenAI Codex (`gpt-5` coding agent with repository,
terminal, and GitHub tool use). All bulk rewrites executed via
deterministic, idempotent scripts committed in `scripts/`; intentional
visual changes were human-reviewed on screenshot contact sheets.

## 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 targeted local verification and documented the
intentional baseline-publication failure 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 *(pending new CI run after this
rework)*
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
*(pending review)*
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code) and
OpenAI Codex

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Dotta <bippadotta@protonmail.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-07 16:22:16 -05:00
Devin Foley ef37203a48
perf(ci): build standalone public packages concurrently (#8567)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - CI runs a Canary Dry Run job that exercises `release.sh`, which
builds the standalone sandbox-provider packages for publish
> - That step (`scripts/build-standalone-public-packages.mjs`) built the
7 provider plugins serially — each doing `rm -rf dist && tsc` — making
it the dominant cost (~49s) inside the slowest PR check (~4.9m wall)
after the general-server lane was already sharded
> - The packages are independent (their own `node_modules` via
`--ignore-workspace`, their own `dist`), so the serial build is pure
latency with no correctness benefit
> - This pull request builds them with a bounded-concurrency pool sized
to the runner CPU count (overridable via
`STANDALONE_BUILD_CONCURRENCY`), buffering each package's output and
flushing it as one block so parallel logs stay readable, and aggregating
failures by original index
> - The benefit is a faster Canary Dry Run / PR feedback loop without
changing what gets built or published

## Linked Issues or Issue Description

No public GitHub issue exists. Inline feature/perf description:

### Problem or motivation

`build-standalone-public-packages.mjs` builds standalone provider
packages serially, making it the largest single cost inside the slowest
PR check.

### Proposed solution

Run independent per-package builds through a bounded-concurrency worker
pool sized to runner CPU count, with an env override and readable
buffered logs.

### Alternatives considered

Keep the serial build for simpler logs, but that preserves the avoidable
CI latency.

### Roadmap alignment

This is CI maintenance and does not overlap planned core roadmap work.

## What Changed

- `scripts/build-standalone-public-packages.mjs`: replaced the serial
per-package build loop with a bounded-concurrency pool (default = runner
CPU count, override via `STANDALONE_BUILD_CONCURRENCY`); per-package
stdout/stderr is buffered and flushed as a single block; failures are
aggregated by original package index so one failure neither aborts the
others mid-flight nor obscures which package broke.
- `scripts/__tests__/build-standalone-concurrency.test.mjs`: new
`node:test` unit suite covering the pool (limit respected, all items
run, ordered failure aggregation, env-override resolution).
- `.github/workflows/pr.yml`: wired the new unit test into the policy
job.

## Verification

- `node --test
./scripts/__tests__/build-standalone-concurrency.test.mjs` → 6/6 pass
- `node ./scripts/release-package-map.mjs check` → OK (29 enabled for CI
publish)
- `git diff --check origin/master..HEAD` → clean

## Risks

- Low risk. Build inputs/outputs are unchanged; only scheduling differs.
The concurrency is bounded by CPU count and overridable; output is
buffered per package so logs remain attributable. If a package fails,
all failures are still reported with their package index.

## Model Used

- Claude (Anthropic), `claude-opus-4-8`, extended thinking 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 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 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
- [ ] 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>
2026-06-23 17:52:12 -07:00
dependabot[bot] b18cbb0dd3
build(deps): bump actions/checkout from 6 to 7 (#8461)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to
7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>block checking out fork pr for pull_request_target and workflow_run
by <a href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li>
<li>Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the
minor-actions-dependencies group across 1 directory by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2458">actions/checkout#2458</a></li>
<li>Bump flatted from 3.3.1 to 3.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2460">actions/checkout#2460</a></li>
<li>Bump js-yaml from 4.1.0 to 4.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2461">actions/checkout#2461</a></li>
<li>Bump <code>@​actions/core</code> and
<code>@​actions/tool-cache</code> and Remove uuid by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2459">actions/checkout#2459</a></li>
<li>upgrade module to esm and update dependencies by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2463">actions/checkout#2463</a></li>
<li>Bump the minor-npm-dependencies group across 1 directory with 3
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2462">actions/checkout#2462</a></li>
<li>getting ready for checkout v7 release by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2464">actions/checkout#2464</a></li>
<li>update error wording by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2467">actions/checkout#2467</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6.0.3...v7.0.0">https://github.com/actions/checkout/compare/v6.0.3...v7.0.0</a></p>
<h2>v6.0.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Update changelog by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2357">actions/checkout#2357</a></li>
<li>fix: expand merge commit SHA regex and add SHA-256 test cases by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li>
<li>Fix checkout init for SHA-256 repositories by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2439">actions/checkout#2439</a></li>
<li>Update changelog for v6.0.3 by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2446">actions/checkout#2446</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/yaananth"><code>@​yaananth</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6...v6.0.3">https://github.com/actions/checkout/compare/v6...v6.0.3</a></p>
<h2>v6.0.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Add orchestration_id to git user-agent when ACTIONS_ORCHESTRATION_ID
is set by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2355">actions/checkout#2355</a></li>
<li>Fix tag handling: preserve annotations and explicit fetch-tags by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2356">actions/checkout#2356</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6.0.1...v6.0.2">https://github.com/actions/checkout/compare/v6.0.1...v6.0.2</a></p>
<h2>v6.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Update all references from v5 and v4 to v6 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2314">actions/checkout#2314</a></li>
<li>Add worktree support for persist-credentials includeIf by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2327">actions/checkout#2327</a></li>
<li>Clarify v6 README by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2328">actions/checkout#2328</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6...v6.0.1">https://github.com/actions/checkout/compare/v6...v6.0.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9c091bb21b"><code>9c091bb</code></a>
update error wording (<a
href="https://redirect.github.com/actions/checkout/issues/2467">#2467</a>)</li>
<li><a
href="1044a6dea9"><code>1044a6d</code></a>
getting ready for checkout v7 release (<a
href="https://redirect.github.com/actions/checkout/issues/2464">#2464</a>)</li>
<li><a
href="f0282184c7"><code>f028218</code></a>
Bump the minor-npm-dependencies group across 1 directory with 3 updates
(<a
href="https://redirect.github.com/actions/checkout/issues/2462">#2462</a>)</li>
<li><a
href="d914b262ff"><code>d914b26</code></a>
upgrade module to esm and update dependencies (<a
href="https://redirect.github.com/actions/checkout/issues/2463">#2463</a>)</li>
<li><a
href="537c7ef99c"><code>537c7ef</code></a>
Bump <code>@​actions/core</code> and <code>@​actions/tool-cache</code>
and Remove uuid (<a
href="https://redirect.github.com/actions/checkout/issues/2459">#2459</a>)</li>
<li><a
href="130a169078"><code>130a169</code></a>
Bump js-yaml from 4.1.0 to 4.2.0 (<a
href="https://redirect.github.com/actions/checkout/issues/2461">#2461</a>)</li>
<li><a
href="7d09575332"><code>7d09575</code></a>
Bump flatted from 3.3.1 to 3.4.2 (<a
href="https://redirect.github.com/actions/checkout/issues/2460">#2460</a>)</li>
<li><a
href="0f9f3aa320"><code>0f9f3aa</code></a>
Bump actions/publish-immutable-action (<a
href="https://redirect.github.com/actions/checkout/issues/2458">#2458</a>)</li>
<li><a
href="f9e715a95f"><code>f9e715a</code></a>
block checking out fork pr for pull_request_target and workflow_run (<a
href="https://redirect.github.com/actions/checkout/issues/2454">#2454</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/checkout/compare/v6...v7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=6&new-version=7)](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>
2026-06-23 10:13:39 -07:00
Devin Foley 254b01d2af
docs: drop contributor screenshot requirement in favor of cutter.sh bot (#8409)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Contributors follow `CONTRIBUTING.md` and the PR template when
opening pull requests
> - Those docs still tell contributors to manually capture and attach
before/after screenshots for UI changes
> - That requirement is now redundant: the `cutter.sh` bot automatically
captures and posts before/after UI screenshots to every PR
> - Asking contributors to also do it by hand adds friction and produces
duplicate screenshots
> - This pull request removes the manual screenshot obligation from
`CONTRIBUTING.md` and the PR template, and documents that `cutter.sh`
handles it
> - The benefit is a clearer, lower-friction contribution flow that
matches how screenshots actually get posted today

## Linked Issues or Issue Description

No public GitHub issue. Underlying change:

Our contributor docs and PR template instructed contributors to attach
before/after screenshots for any UI change. We now run a bot
(`cutter.sh`) that automatically captures and posts before/after UI
screenshots to the PR, so the manual step is no longer needed. This
change removes the manual requirement and instead documents that the bot
handles screenshots, asking contributors to simply describe the visible
change.

## What Changed

- `CONTRIBUTING.md`: removed the "Before / After screenshots"
requirement from the Path 2 PR checklist and from the "Writing a Good PR
message" section; both now explain that the `cutter.sh` bot posts UI
screenshots automatically and ask contributors to describe the visible
change instead.
- `.github/PULL_REQUEST_TEMPLATE.md`: updated the Verification guidance
to note that `cutter.sh` posts before/after screenshots automatically,
and removed the "include before/after screenshots" item from the
checklist.
- Issue templates were intentionally left unchanged — they only offer
screenshots as an optional "if helpful" field, never a requirement.

## Verification

- Docs-only change; no code paths affected.
- `grep -rin "screenshot" CONTRIBUTING.md .github/` confirms no
screenshot *requirement* remains — only the new `cutter.sh` wording and
the optional "if helpful" fields in issue templates.
- Render `CONTRIBUTING.md` and the PR template to confirm the wording
reads cleanly.

## Risks

Low risk — documentation-only change. No build, runtime, or migration
impact.

## Model Used

Claude (Anthropic), model `claude-opus-4-8`, extended thinking 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 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 (docs-only; no tests apply)
- [ ] I have added or updated tests where applicable (N/A — docs-only)
- [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)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending review)
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-06-20 17:58:14 -07:00
Devin Foley 2853a9ae69
perf(ci): shard the general-server test lane across 3 runners (#8360)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Every PR runs the `PR` GitHub Actions workflow, whose `verify` gate
fans out into parallel test lanes (general tests, serialized server
route suites, build, typecheck)
> - The `General tests (server)` lane had grown into the run's critical
path: it executed all ~213 non-route server suites serially in a single
job (~7.2m of test time), more than 2x any other job
> - It runs serially because `server/vitest.config.ts` pins `maxWorkers:
1`, so server suites cannot parallelize within a single runner — the
only lever is spreading them across runners
> - This pull request shards that lane into 3 even partitions that run
on separate runners, mirroring the 4-way sharding already used for the
serialized route suites
> - The benefit is the lane drops from ~7.7m to ~2.4m/shard, cutting
overall PR wall time roughly in half (~8.5m → ~4.2m)

## Linked Issues or Issue Description

No public GitHub issue exists for this work, so the underlying issue is
described inline following the feature-request template.

### Problem or motivation

PR CI wall time had crept back up to ~8.5m. On a recent fully-green run,
the `General tests (server)` job took 7.72m — more than double any other
job and the clear critical path. Of that, 7.23m was pure test execution
(dependency install was a cached 0.27m). The job ran all server suites
that are not route/authz tests (213 files) one after another, because
the server vitest project pins `maxWorkers: 1`, making these suites
inherently serial within a single runner.

### Proposed solution

Shard the general-server lane across 3 parallel runners — the same
technique the route/authz suites already use — so the suite set is split
into even, deterministic partitions that run concurrently. Add a
regression test that proves the shards always cover the full suite set
with no gaps or overlap.

### Alternatives considered

- **Raise `maxWorkers` for the server project** to parallelize within
one runner — rejected: the server suites share process-level state
(DB/port), which is exactly why `maxWorkers: 1` is pinned.
- **Two shards instead of three** — would leave the lane at ~3.6m, still
above the next bottleneck (Canary Dry Run, ~4.1m wouldn't be the gate).
Three lands the lane comfortably below it.
- **Do nothing / accept the slow lane** — rejected: it gates every PR.

### Roadmap alignment

Developer-experience / CI tooling. Not core product roadmap work; does
not overlap with planned features in `ROADMAP.md`.

## What Changed

- `scripts/run-vitest-stable.mjs`: the `general-server` general-test
group now accepts `--shard-index` / `--shard-count`. It enumerates the
full server test set (the whole `server/src` tree, minus the route/authz
suites that already run in their own serialized shards) and splits it
deterministically by modulo. The non-sharded local invocation (`pnpm
test:run:general --group general-server`) is unchanged.
- `.github/workflows/pr.yml`: the `general_tests` matrix runs
`general-server` as 3 parallel shards (1/3, 2/3, 3/3). Workspace groups
are unchanged. The `verify` gate already aggregates the whole matrix
result, so the required check name is unaffected.
- `scripts/__tests__/run-vitest-stable-shard.test.mjs`: a `node:test`
suite asserting the 3 shards form a complete, non-overlapping partition
of the general-server set, that no route/authz suite leaks into it, and
that shard flags are rejected for the parallel workspace groups. Wired
into the `policy` job.

## Verification

- New partition test passes locally: `node --test
./scripts/__tests__/run-vitest-stable-shard.test.mjs` (3/3).
- Confirmed the 3 shards form a complete, non-overlapping partition of
all 213 files (71/71/71).
- Ran a live thin shard (3 real server suites, including one outside
`__tests__`) — 23 tests passed, confirming positional-include execution
works end to end.
- This PR's own CI is the authoritative check: all three `General tests
(server (n/3))` jobs went green on the prior run, collectively covering
every suite the old single job ran.

## Risks

- Low risk. No product code changes — only test orchestration and CI
matrix. Shard partitioning is deterministic and is now covered by an
automated test that fails if the partition ever develops a gap or
overlap. Modulo-on-sorted-filenames balances duration reasonably,
matching the approach already proven by the serialized route shards.

## Model Used

- Claude (Anthropic), `claude-opus-4-8`, extended thinking + tool use
(agentic coding via Paperclip).

## 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 (N/A — no UI change)
- [x] I have updated relevant documentation to reflect my changes
(inline comments explain the sharding rationale)
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green (pending this PR's run)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(pending review)
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-19 19:22:17 -07:00
Devin Foley 4518f272b2
fix(release): publish all remaining @paperclipai workspace packages from CI + guard unpublishable edges (#8365)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work, distributed primarily via the `paperclipai` npm package and its
`@paperclipai/*` workspace packages.
> - The release subsystem (`scripts/release-package-*`) decides which
workspace packages CI republishes at the unified calver version each
release, and `replaceWorkspaceDeps()` rewrites every internal
`workspace:` dependency to that calver version at publish time.
> - The gap: a package that publishes from CI can declare a `workspace:`
dependency on a package that is NOT enrolled for CI publish. The
dependency spec gets rewritten to a calver version that is never
actually published, so the dependent becomes uninstallable.
> - This shipped for real: a recent change made `@paperclipai/server`
depend on `@paperclipai/skills-catalog`, but skills-catalog was not on
the calver release train — so canary builds after that merge failed to
resolve `@paperclipai/skills-catalog@<calver>` and `npx
paperclipai@canary run` broke.
> - This PR addresses it durably by (a) putting every remaining internal
package on the CI release train so no internal dependency can dangle,
and (b) adding a fail-fast guard so this class of break can never ship
again.
> - The benefit is that canary and stable installs resolve all internal
dependencies, and any future unpublishable workspace edge fails the
release build with a clear, named error instead of producing a broken
package.

## Linked Issues or Issue Description

Refs #8327 (introduced the `server -> skills-catalog` runtime dependency
that surfaced the gap).

No public issue tracks this; describing it in-PR:

- **Problem:** After #8327, `npx paperclipai@canary run` failed for
builds past the merge because `@paperclipai/skills-catalog` was
rewritten to a calver version that was never published (the package was
not enrolled for CI publish). Versions before the merge still ran.
- **Root cause:** A `publishFromCi:true` package can declare a
`workspace:` dependency on a package that is not `publishFromCi:true`;
the release-time version rewrite then points at a non-existent published
version.

## What Changed

- Enrolled every remaining internal package on the calver release train
by setting `publishFromCi: true` in
`scripts/release-package-manifest.json`: `skills-catalog`,
`teams-catalog`, `plugin-workspace-diff`, `plugin-kubernetes`,
`plugin-novita-sandbox`. There are now zero `publishFromCi:false`
entries.
- `skills-catalog`, `teams-catalog`, `plugin-workspace-diff` already
existed on npm — CI simply republishes them at calver.
- `plugin-kubernetes` and `plugin-novita-sandbox` were not on npm; their
one-time first publish was bootstrapped so the
`check-release-package-bootstrap` gate passes.
- Added `findUnpublishableWorkspaceEdges()` to
`scripts/release-package-map.mjs`, wired into
`buildReleasePackagePlan()`. The release map build now fails fast
(surfaced by the `check` CI already runs) whenever a
`publishFromCi:true` package declares a runtime `workspace:` dependency
(`dependencies`/`optionalDependencies`/`peerDependencies`) on a
non-`publishFromCi:true` `@paperclipai/*` package, naming the offending
edge.
- Added tests covering positive/negative detection, all three dependency
sections, unknown-package edges, off-train edges, and the live manifest.

## Verification

- `node --test scripts/release-package-map.test.mjs` → 9/9 pass
(includes a test asserting the live manifest has no unpublishable
edges).
- `node scripts/check-release-package-bootstrap.mjs
scripts/release-package-manifest.json` → passes, naming all five
newly-enabled packages (all confirmed present on npm).
- Confirmed via `npm view` that all five packages resolve on the public
registry.

## Risks

- Low risk. The change only enrolls already-existing (or
freshly-bootstrapped) packages onto the existing release train and adds
a build-time validation. No runtime code paths change. The new guard can
only *fail* a release that was already going to ship a broken package.

## Model Used

Claude Opus 4.7 (claude-opus-4-7), extended thinking, with tool use /
code 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 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] If this change affects the UI, I have included before/after
screenshots (N/A — no UI changes)
- [x] I have updated relevant documentation to reflect my changes (N/A —
no doc-facing behavior change)
- [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
2026-06-19 19:11:20 -07:00
Devin Foley a2abebee07
docs: require descriptive, instance-free PR branch names (#8312)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Contributions flow through GitHub PRs against
`paperclipai/paperclip`, but most contributors author their work inside
their own private Paperclip instance
> - That tooling names a working branch after the internal issue/task —
e.g. `PAPA-42-why-did-this-break`
> - When that branch is pushed for a PR, the public PR's head branch
carries instance-local context: it's not meaningful to reviewers and
leaks instance-derived identifiers
> - We just documented the issue-reference side of this (#8292), but
said nothing about branch names
> - This pull request adds a **Branch Naming** section to
`CONTRIBUTING.md` and a matching PR-template checklist item, telling
contributors to rename branches to descriptive, change-scoped names
before pushing
> - The benefit is public PRs whose branch names describe the change and
contain no instance-local details

## Linked Issues or Issue Description

Fixes: #8311
Refs: #8292

## What Changed

- `CONTRIBUTING.md`: new **Branch Naming** subsection — rename
instance-named branches (e.g. `PAPA-42-...`) to descriptive,
change-scoped, kebab-case names before pushing, with examples and the
rename commands.
- `.github/PULL_REQUEST_TEMPLATE.md`: new checklist item asserting the
branch name describes the change and contains no internal ticket id or
instance-derived details.

## Verification

Docs-only change. Rendered Markdown locally and confirmed the new
**Branch Naming** section and the new checklist item appear as intended.
This PR's own branch (`docs/contributor-branch-naming`) follows the new
guidance. No code paths affected.

## Risks

Low risk — documentation and PR-template text only; no runtime, build,
or schema impact. Automatically renaming branches at push time in the
tooling is intentionally out of scope and tracked as separate follow-up
work.

## Model Used

Claude Opus 4.7 (claude-opus-4-7), extended thinking, agentic tool use
via Claude Code.

## 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 and contains no internal
Paperclip ticket id or instance-derived details
- [x] 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
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-19 10:14:24 -07:00
dependabot[bot] ec65aba8ec
build(deps): bump actions/upload-artifact from 4 to 7 (#7743)
Bumps
[actions/upload-artifact](https://github.com/actions/upload-artifact)
from 4 to 7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/upload-artifact/releases">actions/upload-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>v7 What's new</h2>
<h3>Direct Uploads</h3>
<p>Adds support for uploading single files directly (unzipped). Callers
can set the new <code>archive</code> parameter to <code>false</code> to
skip zipping the file during upload. Right now, we only support single
files. The action will fail if the glob passed resolves to multiple
files. The <code>name</code> parameter is also ignored with this
setting. Instead, the name of the artifact will be the name of the
uploaded file.</p>
<h3>ESM</h3>
<p>To support new versions of the <code>@actions/*</code> packages,
we've upgraded the package to ESM.</p>
<h2>What's Changed</h2>
<ul>
<li>Add proxy integration test by <a
href="https://github.com/Link"><code>@​Link</code></a>- in <a
href="https://redirect.github.com/actions/upload-artifact/pull/754">actions/upload-artifact#754</a></li>
<li>Upgrade the module to ESM and bump dependencies by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/upload-artifact/pull/762">actions/upload-artifact#762</a></li>
<li>Support direct file uploads by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/upload-artifact/pull/764">actions/upload-artifact#764</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Link"><code>@​Link</code></a>- made
their first contribution in <a
href="https://redirect.github.com/actions/upload-artifact/pull/754">actions/upload-artifact#754</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/upload-artifact/compare/v6...v7.0.0">https://github.com/actions/upload-artifact/compare/v6...v7.0.0</a></p>
<h2>v6.0.0</h2>
<h2>v6 - What's new</h2>
<blockquote>
<p>[!IMPORTANT]
actions/upload-artifact@v6 now runs on Node.js 24 (<code>runs.using:
node24</code>) and requires a minimum Actions Runner version of 2.327.1.
If you are using self-hosted runners, ensure they are updated before
upgrading.</p>
</blockquote>
<h3>Node.js 24</h3>
<p>This release updates the runtime to Node.js 24. v5 had preliminary
support for Node.js 24, however this action was by default still running
on Node.js 20. Now this action by default will run on Node.js 24.</p>
<h2>What's Changed</h2>
<ul>
<li>Upload Artifact Node 24 support by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/719">actions/upload-artifact#719</a></li>
<li>fix: update <code>@​actions/artifact</code> for Node.js 24 punycode
deprecation by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/744">actions/upload-artifact#744</a></li>
<li>prepare release v6.0.0 for Node.js 24 support by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/745">actions/upload-artifact#745</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/upload-artifact/compare/v5.0.0...v6.0.0">https://github.com/actions/upload-artifact/compare/v5.0.0...v6.0.0</a></p>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<p><strong>BREAKING CHANGE:</strong> this update supports Node
<code>v24.x</code>. This is not a breaking change per-se but we're
treating it as such.</p>
<ul>
<li>Update README.md by <a
href="https://github.com/GhadimiR"><code>@​GhadimiR</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/681">actions/upload-artifact#681</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/712">actions/upload-artifact#712</a></li>
<li>Readme: spell out the first use of GHES by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/upload-artifact/pull/727">actions/upload-artifact#727</a></li>
<li>Update GHES guidance to include reference to Node 20 version by <a
href="https://github.com/patrikpolyak"><code>@​patrikpolyak</code></a>
in <a
href="https://redirect.github.com/actions/upload-artifact/pull/725">actions/upload-artifact#725</a></li>
<li>Bump <code>@actions/artifact</code> to <code>v4.0.0</code></li>
<li>Prepare <code>v5.0.0</code> by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/upload-artifact/pull/734">actions/upload-artifact#734</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="043fb46d1a"><code>043fb46</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/upload-artifact/issues/797">#797</a>
from actions/yacaovsnc/update-dependency</li>
<li><a
href="634250c138"><code>634250c</code></a>
Include changes in typespec/ts-http-runtime 0.3.5</li>
<li><a
href="e454baaac2"><code>e454baa</code></a>
Readme: bump all the example versions to v7 (<a
href="https://redirect.github.com/actions/upload-artifact/issues/796">#796</a>)</li>
<li><a
href="74fad66b98"><code>74fad66</code></a>
Update the readme with direct upload details (<a
href="https://redirect.github.com/actions/upload-artifact/issues/795">#795</a>)</li>
<li><a
href="bbbca2ddaa"><code>bbbca2d</code></a>
Support direct file uploads (<a
href="https://redirect.github.com/actions/upload-artifact/issues/764">#764</a>)</li>
<li><a
href="589182c5a4"><code>589182c</code></a>
Upgrade the module to ESM and bump dependencies (<a
href="https://redirect.github.com/actions/upload-artifact/issues/762">#762</a>)</li>
<li><a
href="47309c993a"><code>47309c9</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/upload-artifact/issues/754">#754</a>
from actions/Link-/add-proxy-integration-tests</li>
<li><a
href="02a8460834"><code>02a8460</code></a>
Add proxy integration test</li>
<li><a
href="b7c566a772"><code>b7c566a</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/upload-artifact/issues/745">#745</a>
from actions/upload-artifact-v6-release</li>
<li><a
href="e516bc8500"><code>e516bc8</code></a>
docs: correct description of Node.js 24 support in README</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/upload-artifact/compare/v4...v7">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>
2026-06-18 15:28:39 -07:00
dependabot[bot] 3d256186d3
build(deps): bump actions/download-artifact from 4 to 8 (#7742)
Bumps
[actions/download-artifact](https://github.com/actions/download-artifact)
from 4 to 8.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/download-artifact/releases">actions/download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v8.0.0</h2>
<h2>v8 - What's new</h2>
<blockquote>
<p>[!IMPORTANT]
actions/download-artifact@v8 has been migrated to an ESM module. This
should be transparent to the caller but forks might need to make
significant changes.</p>
</blockquote>
<blockquote>
<p>[!IMPORTANT]
Hash mismatches will now error by default. Users can override this
behavior with a setting change (see below).</p>
</blockquote>
<h3>Direct downloads</h3>
<p>To support direct uploads in <code>actions/upload-artifact</code>,
the action will no longer attempt to unzip all downloaded files.
Instead, the action checks the <code>Content-Type</code> header ahead of
unzipping and skips non-zipped files. Callers wishing to download a
zipped file as-is can also set the new <code>skip-decompress</code>
parameter to <code>true</code>.</p>
<h3>Enforced checks (breaking)</h3>
<p>A previous release introduced digest checks on the download. If a
download hash didn't match the expected hash from the server, the action
would log a warning. Callers can now configure the behavior on mismatch
with the <code>digest-mismatch</code> parameter. To be secure by
default, we are now defaulting the behavior to <code>error</code> which
will fail the workflow run.</p>
<h3>ESM</h3>
<p>To support new versions of the @actions/* packages, we've upgraded
the package to ESM.</p>
<h2>What's Changed</h2>
<ul>
<li>Don't attempt to un-zip non-zipped downloads by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/download-artifact/pull/460">actions/download-artifact#460</a></li>
<li>Add a setting to specify what to do on hash mismatch and default it
to <code>error</code> by <a
href="https://github.com/danwkennedy"><code>@​danwkennedy</code></a> in
<a
href="https://redirect.github.com/actions/download-artifact/pull/461">actions/download-artifact#461</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/download-artifact/compare/v7...v8.0.0">https://github.com/actions/download-artifact/compare/v7...v8.0.0</a></p>
<h2>v7.0.0</h2>
<h2>v7 - What's new</h2>
<blockquote>
<p>[!IMPORTANT]
actions/download-artifact@v7 now runs on Node.js 24 (<code>runs.using:
node24</code>) and requires a minimum Actions Runner version of 2.327.1.
If you are using self-hosted runners, ensure they are updated before
upgrading.</p>
</blockquote>
<h3>Node.js 24</h3>
<p>This release updates the runtime to Node.js 24. v6 had preliminary
support for Node 24, however this action was by default still running on
Node.js 20. Now this action by default will run on Node.js 24.</p>
<h2>What's Changed</h2>
<ul>
<li>Update GHES guidance to include reference to Node 20 version by <a
href="https://github.com/patrikpolyak"><code>@​patrikpolyak</code></a>
in <a
href="https://redirect.github.com/actions/download-artifact/pull/440">actions/download-artifact#440</a></li>
<li>Download Artifact Node24 support by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/415">actions/download-artifact#415</a></li>
<li>fix: update <code>@​actions/artifact</code> to fix Node.js 24
punycode deprecation by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/451">actions/download-artifact#451</a></li>
<li>prepare release v7.0.0 for Node.js 24 support by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/download-artifact/pull/452">actions/download-artifact#452</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/patrikpolyak"><code>@​patrikpolyak</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/download-artifact/pull/440">actions/download-artifact#440</a></li>
<li><a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/download-artifact/pull/415">actions/download-artifact#415</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/download-artifact/compare/v6.0.0...v7.0.0">https://github.com/actions/download-artifact/compare/v6.0.0...v7.0.0</a></p>
<h2>v6.0.0</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="3e5f45b2cf"><code>3e5f45b</code></a>
Add regression tests for CJK characters (<a
href="https://redirect.github.com/actions/download-artifact/issues/471">#471</a>)</li>
<li><a
href="e6d03f6737"><code>e6d03f6</code></a>
Add a regression test for artifact name + content-type mismatches (<a
href="https://redirect.github.com/actions/download-artifact/issues/472">#472</a>)</li>
<li><a
href="70fc10c6e5"><code>70fc10c</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/461">#461</a>
from actions/danwkennedy/digest-mismatch-behavior</li>
<li><a
href="f258da9a50"><code>f258da9</code></a>
Add change docs</li>
<li><a
href="ccc058e5fb"><code>ccc058e</code></a>
Fix linting issues</li>
<li><a
href="bd7976ba57"><code>bd7976b</code></a>
Add a setting to specify what to do on hash mismatch and default it to
<code>error</code></li>
<li><a
href="ac21fcf45e"><code>ac21fcf</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/460">#460</a>
from actions/danwkennedy/download-no-unzip</li>
<li><a
href="15999bff51"><code>15999bf</code></a>
Add note about package bumps</li>
<li><a
href="974686ed50"><code>974686e</code></a>
Bump the version to <code>v8</code> and add release notes</li>
<li><a
href="fbe48b1d27"><code>fbe48b1</code></a>
Update test names to make it clearer what they do</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/download-artifact/compare/v4...v8">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=4&new-version=8)](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>
2026-06-18 15:13:33 -07:00
dependabot[bot] 0936990a58
build(deps): bump docker/setup-buildx-action from 3 to 4 (#8155)
Bumps
[docker/setup-buildx-action](https://github.com/docker/setup-buildx-action)
from 3 to 4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/docker/setup-buildx-action/releases">docker/setup-buildx-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.0</h2>
<ul>
<li>Node 24 as default runtime (requires <a
href="https://github.com/actions/runner/releases/tag/v2.327.1">Actions
Runner v2.327.1</a> or later) by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/483">docker/setup-buildx-action#483</a></li>
<li>Remove deprecated inputs/outputs by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/464">docker/setup-buildx-action#464</a></li>
<li>Switch to ESM and update config/test wiring by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/481">docker/setup-buildx-action#481</a></li>
<li>Bump <code>@​actions/core</code> from 1.11.1 to 3.0.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/475">docker/setup-buildx-action#475</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.63.0 to 0.79.0 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/482">docker/setup-buildx-action#482</a>
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/485">docker/setup-buildx-action#485</a></li>
<li>Bump js-yaml from 4.1.0 to 4.1.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/452">docker/setup-buildx-action#452</a></li>
<li>Bump lodash from 4.17.21 to 4.17.23 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/472">docker/setup-buildx-action#472</a></li>
<li>Bump minimatch from 3.1.2 to 3.1.5 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/480">docker/setup-buildx-action#480</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.12.0...v4.0.0">https://github.com/docker/setup-buildx-action/compare/v3.12.0...v4.0.0</a></p>
<h2>v3.12.0</h2>
<ul>
<li>Deprecate <code>install</code> input by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/455">docker/setup-buildx-action#455</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.62.1 to 0.63.0 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/434">docker/setup-buildx-action#434</a></li>
<li>Bump brace-expansion from 1.1.11 to 1.1.12 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/436">docker/setup-buildx-action#436</a></li>
<li>Bump form-data from 2.5.1 to 2.5.5 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/432">docker/setup-buildx-action#432</a></li>
<li>Bump undici from 5.28.4 to 5.29.0 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/435">docker/setup-buildx-action#435</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.11.1...v3.12.0">https://github.com/docker/setup-buildx-action/compare/v3.11.1...v3.12.0</a></p>
<h2>v3.11.1</h2>
<ul>
<li>Fix <code>keep-state</code> not being respected by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/429">docker/setup-buildx-action#429</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.11.0...v3.11.1">https://github.com/docker/setup-buildx-action/compare/v3.11.0...v3.11.1</a></p>
<h2>v3.11.0</h2>
<ul>
<li>Keep BuildKit state support by <a
href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/427">docker/setup-buildx-action#427</a></li>
<li>Remove aliases created when installing by default by <a
href="https://github.com/hashhar"><code>@​hashhar</code></a> in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/139">docker/setup-buildx-action#139</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.56.0 to 0.62.1 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/422">docker/setup-buildx-action#422</a>
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/425">docker/setup-buildx-action#425</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.10.0...v3.11.0">https://github.com/docker/setup-buildx-action/compare/v3.10.0...v3.11.0</a></p>
<h2>v3.10.0</h2>
<ul>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.54.0 to 0.56.0 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/408">docker/setup-buildx-action#408</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.9.0...v3.10.0">https://github.com/docker/setup-buildx-action/compare/v3.9.0...v3.10.0</a></p>
<h2>v3.9.0</h2>
<ul>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.48.0 to 0.54.0 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/402">docker/setup-buildx-action#402</a>
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/404">docker/setup-buildx-action#404</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.8.0...v3.9.0">https://github.com/docker/setup-buildx-action/compare/v3.8.0...v3.9.0</a></p>
<h2>v3.8.0</h2>
<ul>
<li>Make cloud prefix optional to download buildx if driver is cloud by
<a href="https://github.com/crazy-max"><code>@​crazy-max</code></a> in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/390">docker/setup-buildx-action#390</a></li>
<li>Bump <code>@​actions/core</code> from 1.10.1 to 1.11.1 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/370">docker/setup-buildx-action#370</a></li>
<li>Bump <code>@​docker/actions-toolkit</code> from 0.39.0 to 0.48.0 in
<a
href="https://redirect.github.com/docker/setup-buildx-action/pull/389">docker/setup-buildx-action#389</a></li>
<li>Bump cross-spawn from 7.0.3 to 7.0.6 in <a
href="https://redirect.github.com/docker/setup-buildx-action/pull/382">docker/setup-buildx-action#382</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/docker/setup-buildx-action/compare/v3.7.1...v3.8.0">https://github.com/docker/setup-buildx-action/compare/v3.7.1...v3.8.0</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d7f5e7f509"><code>d7f5e7f</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/489">#489</a>
from docker/dependabot/npm_and_yarn/docker/actions-to...</li>
<li><a
href="92bc5c9777"><code>92bc5c9</code></a>
chore: update generated content</li>
<li><a
href="da11e35abe"><code>da11e35</code></a>
build(deps): bump <code>@​docker/actions-toolkit</code> from 0.79.0 to
0.90.0</li>
<li><a
href="f021e162ef"><code>f021e16</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/492">#492</a>
from docker/dependabot/npm_and_yarn/undici-6.24.1</li>
<li><a
href="b5af94fab7"><code>b5af94f</code></a>
chore: update generated content</li>
<li><a
href="16ad9776a8"><code>16ad977</code></a>
build(deps): bump undici from 6.23.0 to 6.25.0</li>
<li><a
href="d7a12d7df8"><code>d7a12d7</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/495">#495</a>
from docker/dependabot/npm_and_yarn/glob-10.5.0</li>
<li><a
href="28ff27de4e"><code>28ff27d</code></a>
build(deps): bump glob from 10.3.12 to 13.0.6</li>
<li><a
href="daf436b50e"><code>daf436b</code></a>
Merge pull request <a
href="https://redirect.github.com/docker/setup-buildx-action/issues/496">#496</a>
from docker/dependabot/npm_and_yarn/fast-xml-parser-5...</li>
<li><a
href="9725348367"><code>9725348</code></a>
chore: update generated content</li>
<li>Additional commits viewable in <a
href="https://github.com/docker/setup-buildx-action/compare/v3...v4">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>
2026-06-18 15:03:53 -07:00
Devin Foley 8a062be94d
docs: forbid internal Paperclip issue references in PRs (#8293)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Contributions flow through GitHub PRs against
`paperclipai/paperclip`, but most contributors author their work inside
their own private Paperclip instance
> - Those instances mint instance-local issue ids and deep links
(`PAPA-123`, `/PAP/issues/...`, `agent://...`, localhost/tailnet URLs)
that only the author can open
> - When contributors paste those references into a public PR, reviewers
hit clutter and broken links and have to ask for cleanup
> - There was no written guidance telling contributors (human or agent)
to keep those references out
> - This pull request adds that guidance to `CONTRIBUTING.md` and
surfaces it as a PR-template checklist item plus an inline hint
> - The benefit is cleaner PRs that reference only public, openable
GitHub issues/PRs, with internal context restated in plain English

## Linked Issues or Issue Description

Fixes: #8292

## What Changed

- `CONTRIBUTING.md`: new **No Internal Issue References** subsection
explaining what to leave out (internal ticket ids, instance UI/deep
links, localhost/tailnet URLs) and to restate useful context in plain
English; added a cross-reference sentence from the existing "Link Issues
or Describe Them In-PR" guidance.
- `.github/PULL_REQUEST_TEMPLATE.md`: new checklist item, plus an inline
hint in the Linked Issues comment block, directing contributors to
reference only public GitHub issues/PRs.

## Verification

Docs-only change. Rendered Markdown locally and confirmed the new
`#no-internal-issue-references` anchor resolves from the cross-reference
link, and that the template checklist item appears in the rendered list.
No code paths affected.

## Risks

Low risk — documentation and PR-template text only; no runtime, build,
or schema impact. An optional automated CI gate was intentionally
deferred to a follow-up to avoid regex false positives.

## Model Used

Claude Opus 4.7 (claude-opus-4-7), extended thinking, agentic tool use
via Claude Code.

## 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] 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
- [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
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-18 14:37:21 -07:00
dependabot[bot] 83a293b161
build(deps): bump actions/checkout from 4 to 6 (#8154)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to
6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v6.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>v6-beta by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2298">actions/checkout#2298</a></li>
<li>update readme/changelog for v6 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2311">actions/checkout#2311</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v5.0.0...v6.0.0">https://github.com/actions/checkout/compare/v5.0.0...v6.0.0</a></p>
<h2>v6-beta</h2>
<h2>What's Changed</h2>
<p>Updated persist-credentials to store the credentials under
<code>$RUNNER_TEMP</code> instead of directly in the local git
config.</p>
<p>This requires a minimum Actions Runner version of <a
href="https://github.com/actions/runner/releases/tag/v2.329.0">v2.329.0</a>
to access the persisted credentials for <a
href="https://docs.github.com/en/actions/tutorials/use-containerized-services/create-a-docker-container-action">Docker
container action</a> scenarios.</p>
<h2>v5.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Port v6 cleanup to v5 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v5...v5.0.1">https://github.com/actions/checkout/compare/v5...v5.0.1</a></p>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
<li>Prepare v5.0.0 release by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2238">actions/checkout#2238</a></li>
</ul>
<h2>⚠️ Minimum Compatible Runner Version</h2>
<p><strong>v2.327.1</strong><br />
<a
href="https://github.com/actions/runner/releases/tag/v2.327.1">Release
Notes</a></p>
<p>Make sure your runner is updated to this version or newer to use this
release.</p>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4...v5.0.0">https://github.com/actions/checkout/compare/v4...v5.0.0</a></p>
<h2>v4.3.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Port v6 cleanup to v4 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2305">actions/checkout#2305</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v4...v4.3.1">https://github.com/actions/checkout/compare/v4...v4.3.1</a></p>
<h2>v4.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="df4cb1c069"><code>df4cb1c</code></a>
Update changelog for v6.0.3 (<a
href="https://redirect.github.com/actions/checkout/issues/2446">#2446</a>)</li>
<li><a
href="1cce3390c2"><code>1cce339</code></a>
Fix checkout init for SHA-256 repositories (<a
href="https://redirect.github.com/actions/checkout/issues/2439">#2439</a>)</li>
<li><a
href="900f2210b1"><code>900f221</code></a>
fix: expand merge commit SHA regex and add SHA-256 test cases (<a
href="https://redirect.github.com/actions/checkout/issues/2414">#2414</a>)</li>
<li><a
href="0c366fd6a8"><code>0c366fd</code></a>
Update changelog (<a
href="https://redirect.github.com/actions/checkout/issues/2357">#2357</a>)</li>
<li><a
href="de0fac2e45"><code>de0fac2</code></a>
Fix tag handling: preserve annotations and explicit fetch-tags (<a
href="https://redirect.github.com/actions/checkout/issues/2356">#2356</a>)</li>
<li><a
href="064fe7f331"><code>064fe7f</code></a>
Add orchestration_id to git user-agent when ACTIONS_ORCHESTRATION_ID is
set (...</li>
<li><a
href="8e8c483db8"><code>8e8c483</code></a>
Clarify v6 README (<a
href="https://redirect.github.com/actions/checkout/issues/2328">#2328</a>)</li>
<li><a
href="033fa0dc0b"><code>033fa0d</code></a>
Add worktree support for persist-credentials includeIf (<a
href="https://redirect.github.com/actions/checkout/issues/2327">#2327</a>)</li>
<li><a
href="c2d88d3ecc"><code>c2d88d3</code></a>
Update all references from v5 and v4 to v6 (<a
href="https://redirect.github.com/actions/checkout/issues/2314">#2314</a>)</li>
<li><a
href="1af3b93b68"><code>1af3b93</code></a>
update readme/changelog for v6 (<a
href="https://redirect.github.com/actions/checkout/issues/2311">#2311</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/checkout/compare/v4...v6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4&new-version=6)](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>
2026-06-18 13:59:25 -07:00
dependabot[bot] 0ec4f248af
build(deps): bump docker/login-action from 3 to 4 (#8156)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - CI/CD pipelines use GitHub Actions to automate builds and
deployments of services
> - The `agent-runtime-images` workflow uses `docker/login-action` for
authenticating with Docker registries before pushing images
> - `docker/login-action` v3 is now superseded; v4 was released with
Node 24 as the default runtime and updated internal dependencies
(`@actions/core`, AWS SDK, `@docker/actions-toolkit`)
> - This pull request bumps `docker/login-action` from v3 to v4 in the
`agent-runtime-images.yml` workflow
> - The benefit is staying on a supported runtime version and receiving
upstream security and dependency updates

## Linked Issues or Issue Description

Automated dependency bump — no upstream issue. The underlying need is
routine dependency maintenance:

- **Change type:** Dependency version bump (GitHub Actions)
- **Scope:** Single workflow file, single-line version tag change
- **Motivation:** v4 modernizes the action runtime to Node 24 and
receives updated `@actions/core` (3.x) and AWS SDK dependencies with
security patches

## What Changed

- Bumps `docker/login-action` from `v3` → `v4` in
`.github/workflows/agent-runtime-images.yml`
- v4 switches to Node 24 as the default Actions runtime (requires runner
v2.327.1+; GitHub-hosted runners satisfy this automatically)
- No changes to the action's inputs, outputs, or behavior — the API is
fully backward-compatible

## Verification

- All CI checks pass (green) on this PR
- No input/output interface changes; the login step behavior is
identical
- GitHub-hosted runners automatically meet the Node 24 runtime
requirement (runner v2.327.1+)

## Risks

Low risk. This is a one-line version bump on a widely-used, officially
maintained Docker action. The v4 release has no breaking changes to
inputs or outputs. The only new requirement (Node 24 / runner v2.327.1+)
is satisfied by GitHub-hosted runners automatically.

## Model Used

None — automated Dependabot bump. PR description updated by Claude
Sonnet 4.6 (Anthropic, 200k context, tool use enabled) to satisfy the PR
template requirement.

## 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
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [ ] I will address all Greptile and reviewer comments before
requesting merge

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-18 13:47:55 -07:00
Nicky Leach 45a8f096da
chore: add @nickyleach to CODEOWNERS (#8289)
## Summary

- Adds `@nickyleach` as a codeowner alongside `@cryppadotta` and
`@devinfoley` on all 13 existing entries
- Grants approval rights on `.github/**`, release scripts, docs,
`skills/**`, and package files

## Thinking Path

The task is to give @nickyleach the same CODEOWNERS coverage as the
existing owners. The simplest approach is to append `@nickyleach` to
every existing entry in `.github/CODEOWNERS`. No new paths are
introduced — this is a pure access grant.

## What Changed

- `.github/CODEOWNERS`: added `@nickyleach` to all 13 path patterns
alongside the existing `@cryppadotta` and `@devinfoley` owners

## Verification

- Reviewed the diff: every existing CODEOWNERS line now includes
`@nickyleach` as a third owner
- GitHub will enforce the new ownership on future PRs touching the
covered paths

## Risks

- Low risk: CODEOWNERS is additive-only; no existing owner is removed
- The change takes effect immediately on merge — future PRs touching
covered paths will require @nickyleach approval (or any of the three
owners)

## Model Used

claude-sonnet-4-6

## Test plan

- [ ] Verify GitHub picks up the new CODEOWNERS entry and shows
@nickyleach as a required reviewer on future PRs touching these paths

Closes PAP-61

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-18 13:34:55 -07:00
Jannes Stubbemann 398d746093
build(agent-runtime): harness runtime images for sandboxed execution (stage 3/3) (#7934)
> [!NOTE]
> This is **stage 3 of 3** of the staged Kubernetes contribution: stage
1 is the kubernetes sandbox-provider plugin (#5790), stage 2 is the
provider backend/hardening refresh filed separately, and this stage
ships the runtime images those sandboxes run.

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Sandboxed agent execution (Refs #248) runs each agent turn in an
isolated environment; the kubernetes sandbox provider (stage 1, #5790)
schedules those runs as hardened pods
> - A sandbox pod needs a runtime image with the harness CLI
preinstalled: installing CLIs at run start is slow, flaky, and needs
network egress the sandbox should not have
> - There is no first-party image family for this, so every deployer
would have to hand-roll Ubuntu + Node + CLI images per harness and solve
signal handling, non-root, and image chaining themselves
> - This PR ships the agent-runtime image family: a hardened base
(non-root uid 1000, tini, git, the agent shim) plus one derived image
per harness, a buildx bake file that chains them, and a publish workflow
with cosign keyless signing
> - The benefit is that any sandbox infrastructure, the kubernetes
provider or otherwise, gets ready-made, signed, security-hardened
per-harness runtime images that are verified in production across five
harnesses

## Linked Issues or Issue Description

Refs #248 (sandboxed agent execution proposal) and #5790 (the kubernetes
sandbox provider, stage 1 of this contribution, which consumes these
images as per-run runtime images via its adapter defaults).

No issue covers the image gap itself, described in-PR: sandbox providers
reference `ghcr.io/paperclipai/agent-runtime-*` images, but the
repository contains neither the Dockerfiles nor the workflow that builds
and publishes them. Without this, self-deployers cannot reproduce or
audit the images their agent runs execute in.

## What Changed

- `docker/agent-runtime/Dockerfile.base`: foundation image. Ubuntu 22.04
+ Node 22 + git + tini (PID 1, signal propagation) + non-root
`paperclip` user (uid/gid 1000) + the agent shim compiled in a Go build
stage. `WORKDIR /workspace`, entrypoint `tini -- paperclip-agent-shim`.
- One derived Dockerfile per harness: `opencode` (opencode-ai), `pi`
(@mariozechner/pi-coding-agent), `codex` (@openai/codex), `gemini`
(@google/gemini-cli, plus headless auth-mode settings), `claude`
(@anthropic-ai/claude-code, symlinked as `claude-code`). Each installs
the CLI as root, returns to uid 1000, and asserts the binary is on PATH
at build time.
- `acpx` and `hermes` Dockerfiles are included in the bake group but are
not in the default publish scope (hermes is a stub until a CLI package
exists).
- `docker/agent-runtime/buildx-bake.hcl`: builds the whole family in one
pass. Derived targets chain off the `base` target through bake
`contexts` (the literal registry in each `FROM` is overridden to
`target:base` at build time, so no intermediate push is needed).
`REGISTRY` (default `ghcr.io/paperclipai`) and `VERSION` are overridable
variables.
- `tools/agent-shim/`: a small Go shim that runs as the container
command. It reads `/run/paperclip/runtime-command.json` (`{ "command",
"args" }`), resolves the harness CLI on PATH, and `syscall.Exec`s it so
SIGTERM from the kubelet reaches the harness directly. Harness-agnostic,
with unit tests.
- `.github/workflows/agent-runtime-images.yml`: builds and pushes the
default scope (base, opencode, pi, codex, gemini, claude) for
linux/amd64 on `workflow_dispatch` (explicit version tag) or pushes to
`master` touching these paths, then signs every digest with cosign
keyless OIDC. Uses only `GITHUB_TOKEN`; no extra secrets.
- `docker/agent-runtime/README.md`: image lineup, base contents, local
build instructions, the runtime-command contract, and the security
model.

Additive only: nothing in the product loads these images. Deployments
opt in via their sandbox provider configuration (for example the
kubernetes plugin's image settings).

## Verification

- `cd tools/agent-shim && go build ./... && go test ./... && go vet
./...`: all passing.
- `docker buildx bake -f docker/agent-runtime/buildx-bake.hcl --print
base opencode pi codex gemini claude`: resolves cleanly; every tag and
build context lands on `ghcr.io/paperclipai/agent-runtime-*` and derived
targets map the base ref to `target:base`.
- Workflow YAML validated (parses, single job, no org-specific secrets).
- This exact image family (built from these Dockerfiles, bake file, and
workflow) is what runs agent execution in production on paperclip.inc,
verified end-to-end across five harnesses (opencode, pi, codex, gemini,
claude): each as a full loop from assigned issue to per-run runtime
image in a sandboxed pod to completed run.

## Risks

- Low risk: purely additive, nothing in paperclip-server or the UI
references these files. The workflow only triggers on its own paths.
- Derived images install harness CLIs `@latest` at build time; a broken
upstream CLI release would surface at image build, not at run time, and
the PATH assertion fails the build rather than shipping a broken image.
- The hermes image is an explicit stub (documented in its Dockerfile)
until a hermes CLI package exists; it is outside the default publish
scope.
- cosign signing is keyless OIDC with the workflow identity; no
long-lived signing keys are introduced.

## Model Used

Claude Opus 4.8 (claude-opus-4-8, 1M context, extended thinking, tool
use via Claude Code).

## 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 (no UI changes)
- [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: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 21:10:23 -07:00
Devin Foley 47bd02647c
fix(commitperclip): stop security gate from hanging the review check (#7847)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The commitperclip review workflow runs a security gate as part of CI
on every PR
> - The security script's header promises it always exits 0 and stays
silent/informational, but PRs that triggered a flag were failing with a
5-minute timeout
> - Two compounding bugs: `findExistingDraftAdvisory` paginated without
an upper bound, and the workflow step did not have `continue-on-error:
true`, so any hang inside the script turned into a hard `review` check
failure that blocked merge
> - This pull request caps the advisory pagination at 20 pages and adds
`continue-on-error: true` to the workflow step, aligning runtime
behavior with the script's documented "always exit 0" contract
> - The benefit is that future PRs flagged by the security gate no
longer block merge on a 5-minute timeout, and the gate stays
silent/informational as intended

## Linked Issues or Issue Description

Fixes: #7849

## What Changed

- `.github/workflows/commitperclip-review.yml`: added
`continue-on-error: true` to the `Run security gates` step so a hang or
non-zero exit cannot fail the `review` check (matches the script's
documented "always exit 0" contract).
- `.github/scripts/check-pr-security.mjs`: capped
`findExistingDraftAdvisory` pagination at 20 pages (= 2000 advisories)
and short-circuited with a `console.warn` when the cap is hit; if no
match is found within the cap, callers will simply create a new draft
instead of hanging forever.
- `.github/scripts/tests/check-pr-security.test.mjs`: added a test
asserting the pagination cap is enforced.

## Verification

- `node .github/scripts/tests/check-pr-security.test.mjs` — 31/31 pass,
including the new cap test.
- Step-level guarantee: `continue-on-error: true` makes the `Run
security gates` step non-blocking for the job, so even an unexpected
hang/timeout in this step can no longer fail the `review` check.

## Risks

- Low risk. Pagination cap is a defensive bound; the worst case is a
duplicate draft advisory (acceptable — the workflow continues).
`continue-on-error: true` is exactly what the script header already
promised; the workflow now matches its stated contract.

## Model Used

- Claude (claude-opus-4-7), extended thinking, 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 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>
2026-06-09 15:29:25 -07:00
Devin Foley f85f606c5a
fix(ci): guard canary lockfile commit when regen matches HEAD (#7692)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The PR pipeline runs a "Canary Dry Run" step that validates
dependency PRs against a regenerated `pnpm-lock.yaml` before merge
> - When a dependabot (or other) PR's regenerated lockfile is
byte-identical to `HEAD`, `git commit` exits non-zero with "nothing to
commit, working tree clean"
> - The surrounding `bash -e` step propagates the non-zero exit, failing
the Canary Dry Run for PRs that should be allowed through
> - This pull request guards the commit with `git diff --cached --quiet`
so the step only commits when there is a real staged change
> - The benefit is that dependabot PRs (#7571 storybook bump, #7572) and
any future PR where regen happens to match HEAD stop getting spuriously
blocked by the canary step

## Linked Issues or Issue Description

Refs #7571
Refs #7572

PR #7571 (dependabot: storybook 10.3.5 → 10.4.2) and PR #7572 both fail
on the exact same line of the `Canary Dry Run` step:

```
+ git -c user.email=ci@paperclip.local -c user.name=CI commit --no-verify -m 'ci(canary): stage regenerated lockfile'
On branch master
nothing to commit, working tree clean
Error: Process completed with exit code 1.
```

The step regenerates `pnpm-lock.yaml`, stages it, and unconditionally
commits. When the regenerated lockfile matches `HEAD` exactly (which
happens for some dependabot bumps where the lockfile resolution did not
actually change), `git commit` exits 1 and `bash -e` fails the entire
step.

## What Changed

- `.github/workflows/pr.yml`: Wrap the `git commit` inside the Canary
Dry Run step in `if ! git diff --cached --quiet; then ... fi`, so the
commit is skipped when there is no staged diff.

## Verification

- Reproduced the failure on PR #7571 and PR #7572 (identical stack trace
at the `git commit` line of the Canary Dry Run step).
- Local sanity check: `git diff --cached --quiet` returns 0 (no diff)
when the regen is a no-op and non-zero when there is a real change,
which matches the intended branching.
- Once merged, dependabot PRs that previously stalled on this step
should re-run the Canary Dry Run cleanly.

## Risks

- Low risk: the change only adds a guard before an existing `git
commit`. The `else` branch (`git checkout -- pnpm-lock.yaml` when no
artifact lockfile was used) is unchanged. No behavior change when there
*is* a regen diff.

## Model Used

- Claude (Anthropic) — `claude-opus-4-7`, extended thinking off, 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 run tests locally and they pass (workflow YAML change;
verified via shell sanity check of the guard condition)
- [ ] I have added or updated tests where applicable (no test harness
for workflow YAML)
- [x] If this change affects the UI, I have included before/after
screenshots (n/a — CI workflow only)
- [x] I have updated relevant documentation to reflect my changes (n/a)
- [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
2026-06-06 23:06:05 -07:00
Dotta f09d4231e3
[codex] Add create-issue-interaction-ui maintainer skill (#7659)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Issue-thread interactions are one of the core ways agents pause for
structured board or user decisions.
> - Adding a new interaction kind currently requires coordinated changes
across shared contracts, server behavior, UI cards, fixtures,
CLI/MCP/plugin SDK helpers, and agent guidance.
> - The checkbox-confirmation rollout established a good end-to-end
pattern, but contributors needed a durable maintainer checklist for
repeating that work.
> - This pull request adds a developer/maintainer skill that captures
that workflow inside the repo under `.agents/skills`.
> - The benefit is a reusable implementation guide for future
interaction-card work without installing that guidance on runtime
Paperclip agents.

## Linked Issues or Issue Description

Paperclip issue: [PAP-10457](/PAP/issues/PAP-10457)

This PR documents the process for adding a new issue-thread interaction
family end-to-end. There is no GitHub issue for this Paperclip-internal
skill addition.

## What Changed

- Added `.agents/skills/create-issue-interaction-ui/SKILL.md` as a
developer/maintainer skill.
- Covered shared contract, server route/service behavior, UI card
wiring, fixtures/Storybook, CLI/MCP/plugin SDK helpers, agent guidance,
invariants, and focused verification.
- Referenced the checkbox-confirmation rollout (`4d5322c82`, PR `#7649`)
as the canonical worked example.

## Verification

- `git diff --check origin/master..HEAD`
- `NODE_ENV=test pnpm exec vitest run
server/src/__tests__/paperclip-skill-utils.test.ts`
- Reviewed the added skill markdown for scope, location, and workflow
completeness.

## Risks

Low risk. This is a documentation/skill-only change under
`.agents/skills`; it does not change runtime code, database schema, API
behavior, or installed production-agent guidance.

> 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 shell and GitHub CLI tool
access. Exact hosted model variant and context-window size were 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 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-06 10:47:34 -05:00
Devin Foley a4fa0eaf5e
chore(github): expand issue forms (#7628)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies, and
`github.com/paperclipai/paperclip` is the public intake for bugs and
feature work
> - PR #7575 (just merged) shipped a first cut of
`.github/ISSUE_TEMPLATE/`: bug / feature / adapter forms plus a chooser
config that disables blank issues — enough to stop greeting filers with
an empty textarea
> - Reviewing [PR
#4189](https://github.com/paperclipai/paperclip/pull/4189) surfaced
additional, complementary items worth landing now rather than later: PII
handling (logs and config paste fields routinely contain agent
transcripts, encrypted-secrets paths, and tokens), richer environment
capture for bugs (install method, adapters, DB mode, access context),
and a subsystem picker on feature/enhancement so the queue can be
filtered by area
> - Items 7–10 from #4189 (CONTRIBUTING.md change, AGENTS.md §11,
`require-issue-link.yml`, GitHub Discussions contact link) are
intentionally deferred — each is its own decision and belongs in a
separate, focused PR
> - The auto-label workflow that earlier revisions of this branch
included was dropped per reviewer feedback — labeling on issue open is a
separate concern from the template content and should land (if at all)
in its own PR
> - This pull request extends the merged templates with PII warnings + a
mandatory privacy checkbox on `bug_report.yml`, additional optional env
fields, a required subsystem dropdown on `feature_request.yml`, and two
net-new templates (`enhancement.yml`, `docs_issue.yml`)
> - The benefit is that newly filed issues land with enough environment
context and subsystem hint to triage on first read, and paste-field PII
is gated by an explicit reviewer-readable checkbox

## Linked Issues or Issue Description

Refs #7575

PAPA-521 (follow-up). This is the second half of the issue-templates
work — PR #7575 shipped the baseline, this PR adopts items 1, 2, 3, 4,
and 6 from PR #4189 on top. Item 5 (auto-label workflow) was dropped per
reviewer feedback.

## What Changed

- `bug_report.yml` — added PII privacy notice with redaction guidance
and anonymizer links; pre-submission preflight checkboxes; optional
fields for install method, adapter checkbox list (Claude Code / Codex /
Cursor / Droid / Hermes / external plugin / core), database mode (PGlite
/ external Postgres), and access context (board / agent); inline PII
warnings on the logs and config paste fields; mandatory privacy
checklist at submission time
- `feature_request.yml` — added a required subsystem dropdown (`server/`
· `ui/` · `packages/db` · `packages/shared` · `packages/adapters` ·
`packages/plugins` · cross-cutting · unsure)
- `enhancement.yml` — new template for improvements to existing
behaviour, with current-vs-proposed-behaviour fields and a required
breaking-changes field
- `docs_issue.yml` — new lightweight doc-issue form (type / location /
description / suggestion)

No workflow changes in this PR.

## Verification

- All 4 changed YAML files round-trip through `js-yaml` cleanly
- Diff vs. master: 4 files changed, +254/-3 (`.github/ISSUE_TEMPLATE/`
only)
- Post-merge reviewer steps:
1. Visit `github.com/paperclipai/paperclip/issues/new/choose` — expect
five template cards (bug, feature, enhancement, adapter, docs) and the
existing Discord/Roadmap contact links; no "Open a blank issue" option
2. Open each template in turn — required fields should block submission
when empty (in particular: privacy checklist on the bug form, subsystem
dropdown on feature/enhancement, breaking-changes field on enhancement)

## Risks

- Low risk overall. Files are `.github/ISSUE_TEMPLATE/` config only — no
runtime effect on the server, UI, CLI, or any package, and no workflows
touched
- If a YAML form has a schema quirk that `js-yaml` accepts but GitHub's
form renderer rejects, GitHub silently falls back to a blank issue for
that template. The reviewer render check above is the mitigation

> 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 Opus 4.7 — provider Anthropic, exact model ID `claude-opus-4-7`,
extended-thinking + tool use, running inside the Paperclip Claude Code
harness.

## 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 (refs #7575, #4189)
- [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 (n/a —
`.github/ISSUE_TEMPLATE/` content only; `js-yaml` parse check run
instead)
- [ ] I have added or updated tests where applicable (n/a — repo has no
test coverage for `.github/` content)
- [ ] If this change affects the UI, I have included before/after
screenshots (n/a — only the GitHub.com "New issue" page is affected;
render check happens post-merge on github.com)
- [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 (will verify after open)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
(greploop will run after open)
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-06-05 22:27:12 -07:00
Devin Foley d5889919a9
feat(commitperclip): widen linked-issue gate, add dedup-search check (#7632)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Contributor onboarding leans on a small set of CI gates
("commitperclip") that read PR metadata and enforce the rules in
CONTRIBUTING.md
> - We recently landed two new contributor rules: every PR must either
link an existing issue or inline an issue-template-shaped description,
and the author must affirm they searched for duplicate PRs first
> - The existing `check-pr-linked-issue` gate only accepted
`Fixes/Closes/Resolves #N`, and there was no gate at all for the
dedup-search affirmation, so the new rules were unenforced
> - This pull request widens the linked-issue gate (accept `Refs #N`,
accept inline template-shaped descriptions) and adds a new dedup-search
gate wired into `run-quality-gates`
> - The benefit is that the rules we ask contributors to follow are now
mechanically enforced, lowering review noise without raising contributor
friction

## Linked Issues or Issue Description

Refs #4260 — the PR cited in the original rule discussion, whose body is
the canonical example of the inline-issue-description shape this gate
now accepts.

**Problem or motivation**

The repo recently adopted two contributor rules: (1) link the issue your
PR fixes or inline a description in the issue-template shape, and (2)
confirm you searched for duplicate PRs before opening one. Neither rule
was enforced — the existing linked-issue check only matched
`Fixes/Closes/Resolves #N`, and nothing looked for the dedup-search
affirmation. Reviewers had to remember and re-state the rules by hand on
every PR.

**Proposed solution**

Widen `check-pr-linked-issue.mjs` and add a new
`check-pr-dedup-search.mjs` so commitperclip enforces the rules already
documented in CONTRIBUTING.md and the PR template:

- Accept `Refs #N` as a valid link verb alongside `Fixes`, `Closes`,
`Resolves`.
- Accept a PR body with an inline issue-template-shaped description (≥3
fields matched against the bug, feature, or adapter templates) as a
valid alternative to a linked issue.
- New `check-pr-dedup-search.mjs` looks for a checked checkbox affirming
the author searched for similar/duplicate/prior PRs, wired into
`run-quality-gates.mjs` with the same skip/override semantics as the
other gates.

**Alternatives considered**

- A single regex over the whole PR body looking for issue-template field
names — rejected, too brittle and gave no useful error message when it
failed. The per-field counter lets us tell the author exactly how many
template fields we matched and which template they're closest to.
- Making the dedup-search check live inside `check-pr-linked-issue` —
rejected, the two rules are orthogonal and a separate gate gives a
cleaner error message and respects `[skip-quality-gates]` independently.

**Roadmap alignment**

This is contributor-workflow plumbing for rules that already landed on
`master`. It is not a roadmap feature and does not overlap with planned
core work.

## What Changed

- `check-pr-linked-issue.mjs`: accept `Refs #N`; add
`hasInlineIssueDescription` (per-template field counter, ≥3 fields) so a
fully inlined description satisfies the gate.
- `check-pr-dedup-search.mjs`: new gate, looks for a checked
dedup-search checkbox in the PR body, with clear failure guidance.
- `run-quality-gates.mjs`: wire the new gate in alongside the existing
checks.
- `CONTRIBUTING.md`: "Before You Start: Search First" callout pointing
at the PR-template checkbox the gate enforces.
- Tests: unit tests for `Refs #N`, the inline-description threshold
(bolded labels, plain labels, headings), and the dedup-search gate
across checked/unchecked/missing/skip-prefix paths.

## Verification

- `node --test .github/scripts/tests/check-pr-linked-issue.test.mjs` →
all pass
- `node --test .github/scripts/tests/check-pr-dedup-search.test.mjs` →
all pass
- Full repo test matrix: 116/116 pass locally

For the gate itself, this PR exercises both new code paths: the body
inlines a feature-template-shaped description with ≥3 matched fields,
and the dedup-search checkbox below is checked.

## Risks

Low risk. The change is contributor-CI plumbing — no runtime or
migration impact. The widened linked-issue gate is strictly more
permissive (it can only flip prior FAILs to PASS), and the new
dedup-search gate honors the existing `[skip-quality-gates]` prefix, so
an author can always bypass it the same way as the other gates if
needed.

## Model Used

Claude Opus 4.7 (`claude-opus-4-7`), extended-thinking enabled, tool use
for filesystem + shell.

## 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
- [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>
2026-06-05 22:10:52 -07:00
Devin Foley 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
2026-06-05 21:11:32 -07:00