Commit Graph

41 Commits

Author SHA1 Message Date
Devin Foley 664052f8ea
feat(release): draft stable notes at beta publish, read them from master at promotion (#11567)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release channel system promotes builds canary → nightly → beta →
stable, and stable releases publish a GitHub Release from
`releases/vYYYY.MDD.P.md`
> - The stable lane requires that notes file to exist inside the
promoted source commit, but the file is named for the promotion date,
which is unknown when the source commit is created
> - A promoted beta can therefore never pass the notes check: every
happy-path stable is forced through the candidate-branch fix path, with
a soak-gate justification, for a notes-only change
> - This pull request drafts the notes automatically when the beta is
published and lets the stable promotion read them from `master`
> - The benefit is a walkable stable happy path: the soak gate stays
exact, notes get a real review window during the soak, and the
justification path returns to its real purpose (cherry-picked fixes)

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The stable promotion path in the release channel system (`release.yml`,
`scripts/release.sh`).

**Current behavior**

`release.sh stable` requires `releases/vYYYY.MDD.P.md` in the
checked-out source tree, and `publish_stable` checks out the exact
promoted SHA. The soak gate requires a `beta/v*` tag to point at that
same SHA. No commit can satisfy both for a promoted beta, so a stable
promotion must cut a candidate branch with a notes-only commit and
bypass the soak gate with a written justification. Release notes are
also written at promotion time, under time pressure, with no review
window.

**Proposed behavior**

When a beta publishes, a `draft_stable_notes` job generates a grouped
notes skeleton at `releases/beta/v<beta-version>.md` and pushes it to a
machine-owned branch; a human opens the PR and edits it during the 3-day
soak. The stable preflight resolves notes before the `npm-stable`
approval gate: source-tree notes first (the candidate fix path,
unchanged), then the merged beta-keyed file on `master`; it fails early
with the missing path named when neither exists. After the stable ships,
a canonicalization job pushes a branch that moves the file to
`releases/vYYYY.MDD.P.md`.

Related (not duplicates): #11006 and #11008 introduced the nightly and
beta lanes this builds on; older changelog PRs (for example #10669)
authored notes manually at promotion time, which is the flow this
replaces.

**Reason and benefit**

The happy path becomes: promote the exact soaked SHA, no justification,
notes reviewed during the soak instead of written at the gate. The
`releases/vYYYY.MDD.P.md` invariant still holds durably via the
canonicalization PR.

## What Changed

- `scripts/release.sh`: new `--notes-file PATH` (stable only) overrides
where the pre-publish notes check looks, so notes can live outside the
source checkout without dirtying the worktree.
- `scripts/create-github-release.sh`: same `--notes-file` override for
the GitHub Release body.
- `scripts/draft-stable-notes.sh` (new): deterministic skeleton
generator — commit subjects from the newest stable tag (falling back to
the previous beta, then full history) to the beta's source commit,
grouped into Features / Fixes / Other.
- `.github/workflows/release.yml`:
- `draft_stable_notes` job after `publish_beta`: runs the generator and
force-pushes `release-notes/v<beta-version>`; the job summary links the
compare page. It recreates the beta tag locally if the tag push was
rejected (the known workflows-permission case), so drafting is not
blocked on manual tag recovery.
- `preflight_stable`: computes the target stable version (`release.sh
stable --print-version`) and resolves the notes source (`source_tree` →
`master_beta` → fail early / warn on dry run); new outputs.
- `publish_stable`: materializes `master`-side notes into `RUNNER_TEMP`
and passes `--notes-file` to both scripts; outputs the published stable
version.
- `canonicalize_stable_notes` job: pushes the `git mv` branch after a
stable that used `master`-side notes.
- `doc/RELEASING.md`, `doc/RELEASE-CHECKLIST.md`: document the
drafted-notes flow, the preflight resolution order, and the
canonicalization step; the LLM changelog flow now targets the draft
branch during the soak.
- `.agents/skills/release-changelog/SKILL.md`,
`.agents/skills/release-changelog-discord-message/SKILL.md`: the
notes-authoring skills now describe this flow — range ends at the beta
source commit (not `HEAD`), the file is beta-keyed on the
`release-notes/v<beta-version>` branch (seeded with
`scripts/draft-stable-notes.sh` for betas that predate the automation),
and the canonicalization link caveat is called out for announcements.

## Verification

- `node --test scripts/draft-stable-notes.test.mjs` — 6 tests, temp
git-repo fixtures: grouping, stable-tag range, previous-beta and
full-history fallbacks, default output path, malformed version, missing
tag.
- `node --test scripts/release-lib.test.mjs` — unchanged suite still
green.
- `bash -n` on both changed shell scripts; `release.yml` re-parsed as
YAML.
- `./scripts/release.sh stable --print-version` unchanged (prints the
next stable version); `--notes-file` on a non-stable channel fails with
a clear error.
- Not exercised end-to-end: the new workflow jobs need a real beta
publish to run. The first beta after merge is the live test; the draft
job is additive and cannot affect the publish result (it runs after
`publish_beta` completes).

## Risks

- Low risk to publishing itself: `--notes-file` defaults preserve
today's behavior everywhere; the draft and canonicalization jobs are
additive and run after the publishes succeed.
- The preflight now fails a real stable run when no notes are found.
That is the intended fail-early behavior (it previously failed later,
inside `publish_stable`, after the `npm-stable` approval).
- `draft_stable_notes` force-pushes only the machine-owned
`release-notes/v<beta-version>` branch; a beta re-cut regenerates it
cleanly.
- The stable version computed at preflight could differ from the
published one if a run crosses UTC midnight between the two jobs; the
materialized notes are passed by path, so the publish still succeeds,
and the canonicalization job uses the actually-published version.

## Model Used

Claude Fable 5 (Claude Code)



## Pre-submission 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
2026-08-17 20:47:23 -07:00
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 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 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
Dotta fc5a30805e
feat(cli): add managed install, update, and service lifecycle (#10045)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies
> - Operators need a predictable installation path that survives beyond
an ephemeral `npx` process
> - A durable installation needs an owned per-user payload store, stable
command shim, safe shell integration, and supported service lifecycle
> - Updates must preserve recoverability by backing up data, installing
side-by-side, verifying the new payload, and retaining rollback state
> - Bootstrap scripts and privileged service operations must fail closed
across download, filesystem, ownership, and consent boundaries
> - This pull request integrates managed install, update, rollback,
service, uninstall, doctor, bootstrap-installer, and runtime-serving
support into one workflow
> - The benefit is a recoverable, inspectable, and documented
installation lifecycle with explicit safety boundaries across Linux,
macOS, containers, WSL, npm, npx, and source checkouts

## Linked Issues or Issue Description

### Problem

Paperclip lacks a first-class durable installation and lifecycle
workflow. Operators currently have to assemble npm/npx installation,
PATH setup, background-service management, updates, rollback,
diagnostics, and uninstall behavior themselves. That makes upgrades
harder to recover, creates inconsistent behavior across platforms, and
leaves shell/download/service trust boundaries without one documented
implementation.

### Proposed Solution

Add a managed per-user install store and stable shim, a verified shell
bootstrap installer, service lifecycle commands, install-mode-aware
update/rollback behavior, doctor checks, and documentation. Managed
updates back up the database, install and smoke-test a side-by-side
payload, atomically switch `current`, and retain prior payloads. The
shell installer pins registry/download trust boundaries and requires
explicit consent for non-interactive privileged actions.

### Alternatives Considered

- Keep recommending `npx`: simple for evaluation, but ephemeral and
unsuitable for stable services, atomic updates, or rollback.
- Require global npm installation only: familiar, but cannot provide the
owned side-by-side payload store and retained rollback semantics.
- Split the capability across multiple PRs: rejected because install,
update, service, uninstall, bootstrap, and serving behavior share
contracts and security boundaries that need review together.

### Related Pull Requests

- Supersedes #10042 and #10044 with one integrated final diff.
- Incorporates and replaces the closed preparatory work in #10032 and
#10034.

## What Changed

- Added `paperclipai install`, `update`/`upgrade`, rollback, uninstall,
service lifecycle, onboarding integration, and managed-install doctor
checks.
- Added a private managed payload store, verified manifest/marker
ownership, exclusive mutation locks, atomic manifest/current/shim
writes, retained previous payloads, and provenance validation.
- Added npm and GitHub-ref install sources with exact target resolution,
registry isolation, database backup, side-by-side verification, atomic
activation, service restart coordination, and failure rollback.
- Made managed-update backups report actionable service-start and
`--no-backup` recovery guidance for unreachable databases, while clean
never-onboarded instances skip an empty backup.
- Added systemd user and launchd service definitions, status/health/log
commands, single-instance coordination, stale-port recovery, and
explicit sudo/lingering consent handling.
- Added the `scripts/install.sh` bootstrap path with checked two-stage
downloads, pinned public npm registry usage, platform checks,
dry-run/non-interactive controls, and Docker fixtures.
- Added embedded Postgres/native bootstrap integration,
hot-restart/systemd-notify serving support, passive update notices,
configuration contracts, README/CLI/install documentation, and focused
regression tests.
- Security re-review should explicitly re-verify: (1)
`addManagedPathBlock`/`removeManagedPathBlock` reject symlinked or
non-regular rc files, assert current-user ownership, preserve
restrictive modes, and replace atomically; (2) managed shim replacement
rejects unsafe parents, foreign-owned or multiply linked files, and uses
checked atomic replacement; (3) the shell installer and sudo path
preserve explicit consent and checked downloads; and (4) installed
service/runtime serving remains bound to the validated managed shim and
instance configuration.

## Verification

- `bash -n scripts/install.sh scripts/clean-install-git.sh
scripts/clean-install-npm.sh scripts/test-install-sh-docker.sh`
- `pnpm exec vitest run cli/src/__tests__/install-store.test.ts
cli/src/__tests__/install-command.test.ts
cli/src/__tests__/managed-install-check.test.ts
cli/src/__tests__/onboard-service.test.ts
cli/src/__tests__/service-health-check.test.ts
cli/src/__tests__/service-manager.test.ts
cli/src/__tests__/update-command.test.ts
cli/src/__tests__/update-notice.test.ts
packages/db/src/embedded-postgres-native.test.ts` — 9 files, 66 tests
passed
- `pnpm --dir cli typecheck`
- `pnpm --dir cli build`
- Follow-up verification: `pnpm exec vitest run
cli/src/__tests__/update-command.test.ts` (14/14), `pnpm --dir cli
typecheck`, `pnpm --dir cli build`, and `pnpm --filter
@paperclipai/server typecheck`.
- `pnpm -r typecheck`
- `pnpm build`
- Full `pnpm test:run` exercised all suites; an injected static AWS
credential changed one unrelated doctor expectation, which passed when
those credentials were removed. A second run cleared that case and
exposed stale pre-existing adapter-utils `dist` output; rebuilding
`@paperclipai/adapter-utils` made the isolated test pass. The updated PR
CI is the authoritative clean-workspace full-suite run.

## Risks

- Installer/update code writes executable shims, symlinks, shell rc
blocks, service definitions, and managed payloads; ownership,
regular-file, symlink, hard-link, marker, and path-containment checks
fail closed before destructive changes.
- The bootstrap installer executes downloaded tooling; downloads are
staged and checked before execution, npm traffic is pinned to the public
registry, and non-interactive privileged behavior requires explicit
consent.
- Linux lingering may invoke `sudo`; the command is surfaced and
confirmed before execution, and unsupported service managers fall back
to foreground-run guidance.
- Database migrations remain forward-only; payload rollback does not
reverse migrations, so managed updates create a backup before activation
unless explicitly disabled.
- Service restart and runtime serving touch process/port ownership;
lifecycle locks, health/version checks, and stable-shim service
definitions reduce split-brain and stale-process risk.

> 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 agents using GPT-5.5 and GPT-5.6-sol, with
reasoning, repository/API access, shell execution, and test tooling. The
runtime did not expose a reliable 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>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 18:52:23 -07:00
Dotta 47c38777d8
fix(release): use trusted publishing npm for bundled packages (#10030)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip publishes canary and stable packages through a shared
release script
> - GitHub Actions authenticates those publishes through npm trusted
publishing and an OIDC identity token
> - Bundled-dependency packages recently moved from pnpm publish to a
pinned npm CLI to preserve their bundled files
> - That pin selected npm 10, which cannot use trusted publishing, so
the first bundled package failed with `ENEEDAUTH`
> - This pull request keeps bundled-package packing on npm 10 while
routing actual publishing through the trusted-publishing-capable npm 11
version
> - The benefit is bundled packages keep their required npm packaging
behavior while canary and stable releases authenticate successfully

## Linked Issues or Issue Description

**What happened**

The canary release job failed while publishing
`@paperclipai/adapter-utils` with `ENEEDAUTH`. The package has bundled
dependencies, so the release helper selected pinned `npm@10.9.7`; the
workflow provides OIDC trusted publishing rather than an npm token, and
npm 10 cannot use that authentication path. Because this is the first
package attempted, the release exited before trying the remaining
packages.

**Expected behavior**

Bundled-dependency packages should publish with an npm CLI that both
preserves bundled dependencies and supports GitHub Actions trusted
publishing.

**Steps to reproduce**

Run the canary release workflow from master after PR #9980. The
`publish_canary` job reaches `@paperclipai/adapter-utils`, invokes `npx
npm@10.9.7 publish`, and fails with `ENEEDAUTH`.

**Deployment mode**

GitHub Actions canary and stable npm release workflows.

Refs #9980.

## What Changed

- Kept bundled-package dry-run packing on npm `10.9.7`, which
successfully produces the staged tarball.
- Routed bundled-package publishing through npm `11.16.0`, which
supports GitHub Actions trusted publishing.
- Split the pack and publish helpers so future npm changes cannot
silently couple the two compatibility requirements.
- Updated focused release and ACPX packaging tests to enforce both
versions and call paths.

## Verification

- `pnpm test:release-registry` — 67 passed locally.
- Initial all-npm-11 PR head: Canary Dry Run reproduced an npm-internal
crash during bundled `pack`.
- Current head `5b3961ed13dd26ed2d6b1096ea23fd91b32e4353`: Canary Dry
Run passed with split npm pack/publish helpers.
- All PR checks passed, including build, typecheck + release registry,
server/workspace suites, both e2e shards, security gates, and Greptile.
- Greptile reviewed the current head at 5/5 confidence with no blocking
issues.

## Risks

- Low risk: the change only separates the npm CLI used for
bundled-package packing from the CLI used for publishing.
- The versions remain explicitly pinned because npm 11.16.0 currently
crashes on the bundled pack payload, while npm 10.9.7 cannot perform
trusted publishing.
- Focused tests assert both pins and both helper call paths, and the
full Canary Dry Run passes on the current head.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, exact model ID `gpt-5.6-sol`, high reasoning mode, with
repository, shell, GitHub CLI, and code-execution tools.

## 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 13:19:15 -05:00
Dotta d31a28828b
fix(acpx): support Windows agent spawning (#9980)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Local Claude, Codex, Gemini, and custom ACP adapters run through the
shared embedded ACPX engine
> - That engine wrapped every local agent command in a generated Bash
script to inject environment variables and filter child stderr
> - Windows cannot directly spawn that Bash wrapper, and npm/pnpm ACP
binaries are exposed through `.cmd` shims there
> - ACPX 0.12 already supports per-session child environment variables,
so the wrapper is unnecessary
> - This pull request registers agent commands directly, injects env
through ACPX session options, captures child stderr in-process, and adds
a real Node ACP spawn smoke on Ubuntu and Windows
> - The benefit is one cross-platform spawn path with a reusable smoke
test instead of parallel shell-wrapper implementations

## Linked Issues or Issue Description

Fixes #9941.
Refs #9428 and #9771.

**What happened**

ACPX-backed local agents failed to start on Windows because Paperclip
registered a generated POSIX `.sh` wrapper as the agent command. Windows
also needs the `.cmd` npm/pnpm shim when resolving built-in ACP
binaries, and symlink creation can fail with `EPERM` for seeded
auth/skill files.

**Expected behavior**

The same ACPX engine path should spawn a real ACP agent on Windows and
Linux, forward Paperclip/runtime env without mutating `process.env`,
preserve filtered/unfiltered child stderr behavior, and fall back to
copies where Windows symlinks are unavailable.

**Steps to reproduce**

Run a local ACPX adapter on Windows with the prior wrapper path. ACPX
attempts to spawn the generated `.sh` file and the agent never
initializes.

**Deployment mode**

Local Paperclip adapters using
`packages/adapter-utils/src/acpx-engine/`.

## What Changed

- Removed generated Bash agent/env wrappers and registered local
commands directly with ACPX.
- Passed the resolved child environment through ACPX
`sessionOptions.env`, including resume retry paths.
- Added a minimal `acpx@0.12.0` package patch exposing child stderr
callbacks and allowing documented uppercase env-map keys in persisted
session options.
- Moved stderr tee/filter behavior in-process: raw stderr remains in the
per-run file while benign `nes/close` noise is omitted from live stderr.
- Preferred `.cmd` ancestor binaries on Windows and added `EPERM` copy
fallbacks for Codex auth seeding and Gemini skill materialization.
- Added a real Node ACP echo-agent spawn smoke that can run directly on
any supported platform.

## Verification

- `pnpm exec vitest run
packages/adapter-utils/src/acpx-engine/execute.test.ts
packages/adapter-utils/src/acpx-engine/spawn-smoke.test.ts` — 57 passed.
- `pnpm --filter @paperclipai/adapter-utils typecheck` — passed.
- `node --test scripts/acpx-patch-packaging.test.mjs
scripts/release-lib.test.mjs` — 10 passed.
- Full canary release dry run under Node 24.18.0 / npm 11.16.0 — passed
in an isolated scratch clone.
- `git diff --check` — passed during implementation verification.
- One-time GitHub Actions proof: [Ubuntu ACPX spawn
smoke](https://github.com/paperclipai/paperclip/actions/runs/29924348927/job/88937774579),
[Windows ACPX spawn
smoke](https://github.com/paperclipai/paperclip/actions/runs/29924348927/job/88937774558),
and [Canary Dry
Run](https://github.com/paperclipai/paperclip/actions/runs/29924348927/job/88937774497)
passed on head `f345ac69f2`; the dedicated smoke jobs are intentionally
not retained in the recurring PR workflow.

## Risks

- The ACPX stderr callback and env persistence exemption are carried as
a pnpm dependency patch until ACPX exposes/fixes those behaviors
upstream.
- Child stderr is synchronously appended to preserve ordering and
failure diagnostics; unusually high-volume agent stderr could briefly
block the Node event loop.
- The Windows-specific `.cmd` resolution and symlink `EPERM` branches
are proven by the standalone smoke test and the linked one-time
`windows-latest` run rather than a permanent CI gate.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI GPT-5.4 via Codex CLI, medium reasoning, repository/tool
execution enabled; context-window size is not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-22 10:22:29 -05:00
Dotta 6a36ae47fe
Fix stable release dry-run notes gate (#9334)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The release subsystem uses GitHub Actions dry-run previews so
maintainers can validate stable and canary release behavior before
publishing.
> - Stable release publishing needs a release notes gate so real
`latest` publishes never happen without authored notes.
> - The same gate was also blocking stable dry-run previews, which made
release QA fail before publish-sensitive work could be previewed.
> - This pull request narrows the notes requirement to real non-dry-run
stable publishes.
> - The benefit is that stable dry-run dispatches can preview the
release without same-day notes, while real stable publishes remain
protected.

## Linked Issues or Issue Description

No public GitHub issue exists for this release-QA blocker, so the bug is
described inline below.

### What happened?

Stable dry-run release previews fail when the same-day release notes
file is absent. The release script runs the stable notes-file gate
before release preview work even when `--dry-run` is set.

### Expected behavior

`./scripts/release.sh stable --dry-run` should preview the stable
release without requiring `releases/vYYYY.MDD.P.md`. Real non-dry-run
stable publishes must still fail before build/publish work starts when
the notes file is missing.

### Steps to reproduce

1. Check out current `master` before this fix.
2. Ensure the computed same-day stable release notes file does not exist
under `releases/`.
3. Run `./scripts/release.sh stable --skip-verify --dry-run`.
4. Observe that the script exits with `stable release notes file is
required` instead of reaching the release preview plan.

### Paperclip version or commit

Reproduced on `master` at `9a1d4b7983dfd50e8eb40ee9770e44999d405f60`.

### Deployment mode

Built from source / GitHub Actions release workflow.

## What Changed

- Narrowed the stable release notes gate to `channel=stable` and
`dry_run=false`.
- Updated the release script usage note to say the notes file is
required for non-dry-run stable releases.
- Added a targeted Node test covering dry-run allowed behavior and
non-dry-run blocked behavior.
- Stubbed release fixture registry-version checks so the test isolates
the notes gate without hitting npm.

## Verification

- `node --test scripts/__tests__/release-dry-run-notes.test.mjs` passed
with 2/2 subtests.
- `bash -n scripts/release.sh` exited 0.

## Risks

Low risk. The behavior change only relaxes the notes-file gate for
stable dry-runs. The new test verifies real non-dry-run stable publish
still fails before build/publish work starts when notes are missing.

## Model Used

OpenAI Codex, GPT-5-based coding agent, with shell/tool execution in a
local repository workspace.

## 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-13 21:11:07 -05:00
Devin Foley e68ee09809
perf(release): batch npm registry version queries (#9202)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The release subsystem publishes the public workspace packages and
also powers release-related CI validation.
> - The release flow currently asks npm for package versions one package
at a time in multiple places.
> - That serial registry latency slows the PR Canary Dry Run path and
real release invocations even though the checks are independent.
> - This pull request batches npm registry version lookups with bounded
concurrency and reuses the result for version calculation.
> - The benefit is shorter non-build release-script time while
preserving the fresh target-version existence check before publishing.

## Linked Issues or Issue Description

- No public GitHub issue exists for this release-script performance
cleanup.

### Problem or motivation

Release validation spends avoidable time on repeated serial `npm view`
calls across the public package set. The slow path affects PR release
validation and real release invocations because version discovery waits
on independent registry reads one at a time.

### Proposed solution

Fetch package version maps concurrently with bounded parallelism, reuse
that map for stable/canary version calculation, and keep a fresh
parallel absence check for the target publish version.

### Alternatives considered

Keeping the existing serial shell loop is simpler, but it preserves the
CI latency cost. Caching the final target-version existence check was
rejected because release publish safety should still query npm freshly
before publishing.

### Roadmap alignment

This is a small release-tooling performance improvement. It does not
duplicate any planned core product work found in `ROADMAP.md`.

## What Changed

- Added `scripts/release-registry-versions.mjs` to fetch npm package
version maps and assert target-version absence with bounded parallelism.
- Updated `scripts/release.sh` to prefetch package versions once and to
batch the final target-version absence check.
- Updated `next_stable_version` and `next_canary_version` to use the
prefetched version map when present, with the existing per-package npm
fallback preserved.
- Added release-registry helper coverage and included it in `pnpm run
test:release-registry`.
- Hardened the release publish helper tests so their fake `pnpm`/`npm`
fixture PATH is preserved under non-login shell execution.

## Verification

- `node --test scripts/release-registry-versions.test.mjs`
- `pnpm run test:release-registry`
- `bash -n scripts/release.sh scripts/release-lib.sh`
- `git diff --check`
- Safety scan before push: searched changed files for common
key/token/password patterns and PII markers; only benign script-name
text matched (`secrets:migrate-inline-env`).
- Remote PR checks on the latest head passed, including `Typecheck +
Release Registry`, `Canary Dry Run`, build, tests, e2e, policy, security
scans, and commitperclip review.
- Greptile reviewed the latest head with Confidence Score 5/5 and no
blocking issues.

## Risks

- Low risk. The release version helpers keep their original npm fallback
when no prefetched version map is supplied.
- The existence check remains fresh and uncached before publish, but now
reports all matching package/version pairs from a parallel check.
- If npm has transient failures during the prefetch step, missing or
failed packages still map to an empty version list, matching the old
helper behavior.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex coding agent using GPT-5, with shell/tool execution in
the local repository.

## 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: Claude <noreply@paperclip.ing>
2026-07-08 08:04:39 -07:00
Dotta ce7b49e4f1
[codex] Recover duplicate npm provenance canary publishes (#7839)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The release workflow publishes canary npm packages on every push to
`master`
> - The failing canary job built successfully and published several
packages before npm failed on `@paperclipai/mcp-server`
> - The concrete failure was npm trusted-publishing provenance returning
`TLOG_CREATE_ENTRY_ERROR` because an equivalent Sigstore
transparency-log entry already existed
> - The package version was not visible on npm afterward, so the release
script could not safely treat that error as success by itself
> - This pull request adds a narrow recovery path for that npm
provenance failure and keeps the existing registry verification as the
final source of truth
> - The benefit is that transient duplicate transparency-log failures do
not break canary publication when a package can be republished without
provenance or is already visible on npm

## Linked Issues or Issue Description

Bug fix, no public GitHub issue found in duplicate search.

- What happened: the Release workflow canary publish failed in
`publish_canary` after npm returned `TLOG_CREATE_ENTRY_ERROR` while
publishing `@paperclipai/mcp-server@2026.609.0-canary.2`.
- Expected behavior: canary publishing should either recover from npm's
duplicate transparency-log failure when the package can still be
published, or fail later in registry verification if the package never
appears.
- Steps to reproduce: inspect
https://github.com/paperclipai/paperclip/actions/runs/27230012891/job/80411422155
from push `05cb18cf28074a6d1074c7575c5a44133146e368`.
- Deployment mode: GitHub Actions Release workflow, npm trusted
publishing.
- Duplicate search: no open PRs or issues found for `canary publish TLOG
provenance release` or the failing run/job IDs.

## What Changed

- Added `publish_package_to_npm` in `scripts/release-lib.sh` to wrap
canary/stable package publishing.
- Detects npm's duplicate Sigstore transparency-log error and checks
whether the package version is already visible on npm.
- Retries that exact package once with `--provenance=false` when npm hit
the duplicate tlog error but the version is not visible yet.
- Keeps unrelated publish failures as hard failures.
- Added shell-helper tests with fake `pnpm` and `npm` commands, and
included them in `pnpm test:release-registry`.

## Verification

- `node --test scripts/release-lib.test.mjs`
- `pnpm test:release-registry`
- Confirmed `pnpm publish --dry-run --no-git-checks --tag canary
--access public --provenance=false` is accepted by pnpm 9.15.4.

## Risks

- Low risk: the recovery only triggers when npm output contains both
`TLOG_CREATE_ENTRY_ERROR` and the duplicate transparency-log message.
- Publishing without provenance is a fallback for canary continuity; if
npm still does not expose the package, the existing registry
verification step still fails the release.
- The same helper is used by stable publishing too, but only for this
exact npm provenance failure path.

> 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`.

This is a release reliability bug fix. I checked `ROADMAP.md`; it does
not duplicate planned core product work.

## Model Used

OpenAI Codex coding agent, GPT-5-class model, tool-enabled local shell
and GitHub CLI workflow, medium reasoning mode.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have 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
- [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-09 15:35:07 -05:00
Devin Foley 81d18f2d77
ci: speed up PR verify workflow (#6137)
## Thinking Path

> - Paperclip orchestrates AI agents through a control-plane repo that
relies on GitHub Actions as part of its release and verification safety
net.
> - The PR workflow in `.github/workflows/pr.yml` is the core CI path
protecting pull requests before merge.
> - Baseline measurement work in [PAPA-335](/PAPA/issues/PAPA-335)
showed the old single `verify` job was the critical-path bottleneck,
with general tests and build serialized together.
> - Follow-up implementation in [PAPA-338](/PAPA/issues/PAPA-338) and
[PAPA-339](/PAPA/issues/PAPA-339) split that work into parallel lanes
and removed redundant clean-runner prebuild work.
> - [PAPA-340](/PAPA/issues/PAPA-340) now needs real post-change PR
workflow evidence, not local inference, to compare against the May 15,
2026 baseline and decide whether phase-2 work is still justified.
> - This pull request publishes the already-implemented CI speedup
branch so GitHub can run the actual `PR` workflow against it.
> - The benefit is that CI timing decisions are based on measured runs
from the exact workflow shape we intend to ship.

## What Changed

- Split the PR workflow so `policy` fans out into separate `Typecheck +
Release Registry`, grouped `General tests`, and `Build` jobs.
- Kept the serialized server matrix, canary dry run, and e2e jobs intact
while removing the old monolithic `verify` bottleneck.
- Reworked grouped general-test execution in
`scripts/run-vitest-stable.mjs` so the workflow can run balanced
non-serialized lanes.
- Replaced redundant clean-runner prebuild gates with the idempotent
`ensure-build-deps` path used by the relevant CI entrypoints.

## Verification

- `ruby -e "require 'yaml'; YAML.load_file('.github/workflows/pr.yml');
puts 'yaml-ok'"`
- `node scripts/run-vitest-stable.mjs --mode general --dry-run`
- `node scripts/run-vitest-stable.mjs --mode general --group
general-server --dry-run`
- `node scripts/run-vitest-stable.mjs --mode general --group
general-workspaces-a --dry-run`
- `node scripts/run-vitest-stable.mjs --mode general --group
general-workspaces-b --dry-run`
- `pnpm test:run:general -- --group general-workspaces-b`
- `pnpm test:run:general -- --group general-workspaces-a`
- `pnpm test:run:general -- --group general-server`
- `pnpm run typecheck:build-gaps`
- `pnpm --filter @paperclipai/plugin-hello-world-example typecheck`

## Risks

- Required-check and branch-protection settings may still reference the
old single `verify` job name.
- Parallel CI lanes can expose hidden ordering assumptions or
clean-runner bootstrap gaps that local grouped dry-runs did not surface.
- Because the branch is behind current `master`, merge conflicts or
unrelated upstream drift could affect the measured runtime until the
branch is rebased.

> Checked `ROADMAP.md`; this work is CI throughput maintenance for the
existing PR verification path, not duplicate feature work.

## Model Used

- OpenAI Codex via Paperclip `codex_local`, GPT-5-class coding agent
with repository read/write, shell execution, and GitHub CLI/tool use.
The runtime does not expose a more specific backend model ID in-session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [ ] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-16 11:28:25 -07:00
Devin Foley a72731f118
fix: harden release registry verification against npm lag (#4816)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - Its release automation publishes canary packages to npm and then
validates the published registry state before considering the release
healthy
> - The failing canary run `25139465018` showed that npm can expose a
newly published version through version-specific endpoints before the
root package document has fully converged
> - That made a successful canary publish look like a failed release
because the verifier trusted stale root metadata too early
> - This pull request hardens the registry verification path by
preferring version-specific manifest checks, retrying
convergence-sensitive failures, and distinguishing permanent failures
from propagation lag
> - While validating that change in CI, a separate teardown race in
`heartbeat-stale-queue-invalidation.test.ts` surfaced and was hardened
so the PR could pass reliably
> - The benefit is that transient npm propagation lag no longer fails a
successful canary publish, while genuine registry-state and
dependency-integrity failures still stop the release flow promptly

## What Changed

- Hardened `scripts/verify-release-registry-state.mjs` so it prefers
version-specific manifest resolution over stale root metadata, adds
bounded registry-fetch timeouts, and classifies failures as retriable vs
non-retriable.
- Updated `scripts/release-lib.sh` and `scripts/release.sh` so
post-publish registry verification retries only convergence-sensitive
failures and reports immediate permanent failures clearly.
- Expanded `scripts/verify-release-registry-state.test.mjs` with
regression coverage for stale root metadata, fetch timeout behavior,
peer dependency range handling, non-retriable canary-latest cases, and
related verifier edge cases.
- Hardened
`server/src/__tests__/heartbeat-stale-queue-invalidation.test.ts`
teardown to tolerate the late-comment foreign-key race that CI exposed
while validating this branch.

## Verification

- `pnpm run test:release-registry`
- `node --check scripts/verify-release-registry-state.mjs`
- `bash -n scripts/release.sh && bash -n scripts/release-lib.sh`
- PR checks passed on head `5c422600fc12acac61f6b7c267a4dc915df622b1`:
`policy`, `verify`, `e2e`, `security/snyk`, and `Greptile Review`

## Risks

- Low risk. The main behavioral changes are limited to release
automation and verifier retry semantics, plus a test-only teardown
hardening for a CI race.

> I checked [`ROADMAP.md`](ROADMAP.md). This is a narrow release bugfix
and does not overlap planned core feature work.

## Model Used

- OpenAI Codex via Paperclip `codex_local` with tool use and local code
execution enabled. This agent session runs on a GPT-5-class coding
model; the exact backend model ID/context window is not exposed by the
local adapter runtime.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] 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 have addressed all Greptile and reviewer comments before
requesting merge
2026-05-09 22:18:12 -07:00
Devin Foley f784d8d90e
Retry canary registry verification (#5579)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies, and the
release pipeline is part of keeping that control plane shippable.
> - The relevant subsystem here is the release automation in
`scripts/release.sh`, which publishes canary builds and then verifies
npm registry state.
> - The failing CI run showed a successful publish followed by an
immediate registry-state verification failure while npm dist-tag
metadata was still propagating.
> - That made the canary job flaky even when the publish itself had
succeeded, which is the wrong failure mode for release automation.
> - This pull request adds bounded retries around the post-publish
registry-state verification step instead of failing on the first stale
read.
> - The benefit is that canary releases tolerate transient npm
propagation lag while still failing clearly if registry metadata never
converges.

## What Changed

- Wrapped the post-publish `verify-release-registry-state.mjs` call in a
bounded retry loop inside `scripts/release.sh`.
- Reused the existing publish verification retry defaults and added
optional overrides via `NPM_REGISTRY_STATE_VERIFY_ATTEMPTS` and
`NPM_REGISTRY_STATE_VERIFY_DELAY_SECONDS` for dist-tag-specific tuning.

## Verification

- `bash -n scripts/release.sh`
- CI will also exercise the release path via the existing `Canary Dry
Run` workflow job in `.github/workflows/pr.yml`.

## Risks

- Low risk. The main behavioral change is that a genuinely broken
registry-state verification can now wait through the configured retry
window before failing.

> 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 local agent, GPT-5-based Codex runtime in Paperclip with
tool use and shell execution. The exact backend model ID/context window
is not surfaced in this local heartbeat 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 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
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-05-09 11:40:02 -07:00
Devin Foley a0f5cbffd7
Harden release flow with registry verification and dist-tag checks (#4800)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - Paperclip is distributed as npm packages, including plugins like
`plugin-e2b`
> - The release process publishes canary and stable builds via npm
dist-tags
> - But there was no automated verification that published packages
actually landed with the correct dist-tags, and broken canary publishes
could silently ship to users
> - This PR adds a registry verification script that checks published
packages match their expected dist-tags, and wires it into PR CI so
regressions are caught before merge
> - The benefit is release integrity is verified automatically, and
broken dist-tag states are caught early

## What Changed

- Added `scripts/verify-release-registry-state.mjs` — verifies that
published npm packages have correct dist-tag assignments and detects
orphaned or mispointed tags
- Added `scripts/verify-release-registry-state.test.mjs` — test coverage
for the verification logic
- Updated `scripts/release.sh` to include canary dist-tag safety checks
before publishing
- Updated `.github/workflows/pr.yml` to run registry verification as a
CI step
- Updated `doc/PUBLISHING.md` and `doc/RELEASING.md` with the new
verification workflow

## Verification

- `pnpm test` — all tests pass including new verification script tests
- `node scripts/verify-release-registry-state.mjs` — runs against the
live npm registry and reports current state
- CI: the new PR workflow step runs on every PR push

## Risks

- Low risk. This is additive CI and tooling — no runtime code changes.
The registry verification is read-only (queries npm, does not publish).
The release script changes add safety checks that abort before
publishing if state is unexpected.

## Model Used

Codex GPT 5.4 high 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 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
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-04-29 15:56:20 -07:00
Devin Foley 40782f703d
Fix release packaging for standalone public packages (#4494)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies, and the
sandbox-provider work just moved E2B into a standalone publishable
plugin package.
> - That plugin is intentionally excluded from the root pnpm workspace
so it can model third-party install behavior without forcing lockfile
churn in the main repo.
> - The merged architecture change exposed a follow-up release problem:
the canary publish workflow tried to publish `@paperclipai/plugin-e2b`,
but the tarball had no `dist/` payload because standalone public
packages were not being built in the release path.
> - That means the release pipeline needed a packaging fix in core
release tooling, not another architectural change in the sandbox
provider itself.
> - This pull request adds a generic release step for public packages
that live outside the pnpm workspace, instead of hardcoding E2B-specific
behavior into the release script.
> - The benefit is that standalone publishable packages can be built and
packed correctly during release, including future sandbox-provider
plugins that follow the same pattern.

## What Changed

- Added `scripts/build-standalone-public-packages.mjs` to discover
public packages outside the pnpm workspace, run a clean package-local
install, and build them before publish.
- Updated `scripts/release.sh` to invoke that helper immediately after
the normal workspace build step.
- Kept the behavior generic by driving off the existing public package
map and pnpm workspace patterns rather than special-casing
`@paperclipai/plugin-e2b`.

## Verification

- `rm -rf packages/plugins/sandbox-providers/e2b/dist`
- `node ./scripts/build-standalone-public-packages.mjs`
- `cd packages/plugins/sandbox-providers/e2b && npm pack --dry-run`
- Confirm the tarball now includes the rebuilt `dist/` files instead of
only `README.md` / `package.json`

## Risks

- Low risk: this only changes the release build path for public packages
outside the pnpm workspace.
- The helper performs a clean package-local install for each standalone
public package, so release time may increase slightly as more such
packages are added.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex via `codex_local`
- Model ID: `gpt-5.4`
- Reasoning effort: `high`
- Context window observed in runtime session metadata: `258400` tokens
- Capabilities used: terminal tool execution, git, GitHub CLI, and local
build/test 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 run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-04-25 12:16:23 -07:00
dotta 3e0e15394a chore: switch release calver to mdd patch 2026-03-18 07:57:36 -05:00
dotta 21f7adbe45 fix: advance canary after partial publish 2026-03-17 16:31:38 -05:00
repro 9176218d16 fix: validate canary release path in CI 2026-03-17 15:35:59 -05:00
Dotta 48326da83f fix: restore release script executable bit 2026-03-17 14:09:16 -05:00
Dotta 21c1235277 chore: automate canary and stable releases 2026-03-17 14:08:55 -05:00
Dotta 964e04369a fixes verification 2026-03-12 12:55:26 -05:00
Dotta 873535fbf0 verify the packages actually make it to npm 2026-03-12 12:42:00 -05:00
Dotta 469bfe3953 chore: add release train workflow 2026-03-09 13:55:30 -05:00
Dotta 422f57b160 chore: use public-gh for manual release flow 2026-03-09 10:33:56 -05:00
Dotta 31c947bf7f fix: publish canaries in changesets pre mode 2026-03-09 10:23:04 -05:00
Dotta f5bf743745 fix: support older git in release cleanup 2026-03-09 10:11:46 -05:00
Dotta df94c98494 chore: add release preflight workflow 2026-03-09 09:06:45 -05:00
Dotta a7cfd9f24b chore: formalize release workflow 2026-03-09 08:49:42 -05:00
Dotta 77e04407b9 fix(publish): always bundle ui-dist into server package 2026-03-09 07:21:33 -05:00
Dotta 048e2b1bfe Remove legacy OpenClaw adapter and keep gateway-only flow 2026-03-07 18:50:25 -06:00
Dotta e693e3d466 feat(release): auto-create GitHub Release on publish
Add create_github_release helper to release script that creates a
GitHub Release via gh CLI after tagging, using release notes from
releases/vX.Y.Z.md if available or auto-generated notes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 16:50:25 -06:00
Dotta 35e4897256
Merge pull request #141 from aaaaron/integrate-opencode-pr62
Integrate opencode pr62 & pr104
2026-03-06 11:32:03 -06:00
Dotta 7c07b16f80 feat(release): add --canary and --promote flags to release.sh
Support two-phase canary release flow:
- --canary: publishes packages under @canary npm tag, skips git commit/tag
- --promote <version>: moves canary packages to @latest, then commits and tags

Both flags work with --dry-run. Existing behavior unchanged when neither flag is passed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:03:49 -06:00
Konan69 6a101e0da1 Add OpenCode provider integration and strict model selection 2026-03-05 15:24:20 +01:00
Dotta a4da932d8d fix: remove stale server/ui-dist from git add in release.sh
The release script cleaned up temporary build artifacts (ui-dist, skills)
before staging files for the commit, then tried to git add server/ui-dist
which no longer existed.  Remove it from the git add list since these
artifacts should never be committed — they're only needed during publish.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:14:28 -06:00
Dotta f4a5b00116 fix: bundle skills directory into npm packages for runtime discovery
The claude-local, codex-local adapters and the server all resolve a
skills/ directory using __dirname-relative paths that only work inside
the monorepo.  When installed from npm the paths point outside the
package and cause ENOENT on readdir/readFile.

- Update both adapter execute.ts files to try a published-path
  candidate (../../skills from dist/) before falling back to the
  monorepo dev path (../../../../../skills from src/).
- Update server readSkillMarkdown() to try the published path first.
- Add "skills" to the files array in server, claude-local, and
  codex-local package.json so npm includes them.
- Update release.sh to copy the repo-root skills/ into each package
  before publish, and clean up after.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 16:06:12 -06:00
Dotta 09d2ef1a37 fix: restore docs deleted in v0.2.3 release, add Paperclip branding
- Restored docs/ directory that was accidentally deleted by `git add -A`
  in the v0.2.3 release script
- Replaced generic "P" favicon with actual paperclip icon using brand
  primary color (#2563EB)
- Added light/dark logo SVGs for Mintlify navbar (paperclip icon + wordmark)
- Updated docs.json with logo configuration for dark/light mode
- Fixed release.sh to stage only release-related files instead of `git add -A`
  to prevent sweeping unrelated changes into release commits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:49:43 -06:00
Dotta d18312d6de fix: bundle UI dist into server package for npm publishing
The server's static-ui mode resolves the UI dist path relative to its
own directory. In the monorepo it finds ../../ui/dist, but when published
to npm the UI package isn't available.

- server/src/app.ts: try ../ui-dist (published) then ../../ui/dist (dev),
  gracefully degrade to API-only if neither exists
- server/package.json: include ui-dist/ in published files
- scripts/release.sh: build UI and copy dist to server/ui-dist before
  publishing, clean up in restore step

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:45:45 -06:00
Dotta c11d2d3eda fix: copy repo README to CLI for npm publishing
build-npm.sh now copies the root README.md into cli/ so the npm package
page shows the same README as the GitHub repo. release.sh cleans up the
copy after publishing during the restore step.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:05:41 -06:00
Dotta 24b393b08f fix: release script grep -P macOS compat and CLI typecheck actor errors
- Replace grep -P (Perl regex, unavailable on macOS) with sed for
  extracting the CLI version string in release.sh
- Add triple-slash reference to server/src/types/express.d.ts in
  server/src/index.ts so CLI's tsc picks up the Express Request
  augmentation when following workspace links

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 14:58:55 -06:00
Dotta defccdd4d9 feat: integrate Changesets for multi-package npm publishing
Migrate from single-bundle CLI publishing to publishing all @paperclipai/*
packages individually via Changesets. This fixes the "Cannot find package
@paperclipai/server" error when installing from npm.

Changes:
- Add @changesets/cli with fixed versioning (all packages share version)
- Make 7 packages publishable (shared, adapter-utils, db, 3 adapters, server)
- Add build scripts, publishConfig, and files fields to all packages
- Mark @paperclipai/server as external in CLI esbuild config
- Simplify CLI importServerEntry() to use string-literal dynamic import
- Add generate-npm-package-json support for external workspace packages
- Create scripts/release.sh for one-command releases
- Remove old bump-and-publish.sh and version-bump.sh
- All packages start at version 0.2.0

Usage: ./scripts/release.sh patch|minor|major [--dry-run]

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 14:46:16 -06:00