Commit Graph
3293 Commits
Author SHA1 Message Date
DottaandPaperclip ade8761ae3 fix(cli): ignore update cache in managed install doctor
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 5b61cf1f63 test(installer): make fixture logging atomic
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip c7d8e0fe59 test(cli): cover final installer hardening
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip b9df8bf4f5 fix(installer): pin npm registry trust boundary
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 94b68d2437 fix(cli): allow cached managed reinstalls
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip dc06b610b9 feat(cli): add managed GitHub ref installs
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip a491790319 chore: retrigger PR policy checks
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 66d9c9860a fix(cli): avoid guessed restart versions
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip eeaec78627 feat(cli): add managed update and rollback
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip e64d383b6f fix(cli): preserve installs when service state is unknown
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 06e8d2f387 fix(installer): harden dry runs and unit escaping
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 7a22677471 fix(cli): fail closed on install locks
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip c15a35fb8f fix(cli): serialize managed uninstall
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 6eda77574e fix(cli): harden managed install store
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 0a4651232c fix(installer): verify third-party bootstrap scripts
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 9f0aa2ac75 fix(cli): make bootstrap options explicit
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 49503ddba4 fix(cli): harden service lifecycle edge cases
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 247ed753b2 fix(cli): align installer flags and restart health
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip d38ac01af5 chore: retrigger PR policy checks
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip a45ba82d94 chore(cli): clean installer smoke script whitespace
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip c858e7364c fix(cli): harden managed install filesystem writes
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 8354cecede fix(cli): harden install integration checks
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:13 +00:00
DottaandPaperclip 1c5b6c1caf feat(cli): integrate managed install workflows
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:12 +00:00
DottaandPaperclip 3bfeba5835 feat(cli): add managed npm install store
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:12 +00:00
DottaandPaperclip 3c1666e318 docs: document installer raw fallback
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:12 +00:00
DottaandPaperclip b4b596503d feat(cli): add managed service lifecycle
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:12 +00:00
DottaandPaperclip 189da8bb95 feat(cli): add curl bootstrap installer
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-27 15:32:12 +00:00
DottaandPaperclip aed4478c81 fix(pr-gardening): scope runs to instance-authored PRs (#10323)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies
> - Maintainers use the pr-gardening skill to keep referenced pull
requests reviewable and moving toward merge
> - The skill previously treated every recently referenced repository PR
as owned work, including community PRs and stale references
> - That oversized scope caused noisy reports, capped-search failures,
and follow-up actions aimed at PRs this Paperclip instance should not
manage
> - The workflow also stopped at reminders instead of dispatching the
repository's standard PR-preparation process
> - This pull request scopes gardening to the authenticated instance
identity by default and makes exclusions explicit and inspectable
> - The benefit is a smaller, ownership-correct queue that automatically
routes actionable PRs through the established preparation workflow

## Linked Issues or Issue Description

No public issue exists for this maintenance fix, so the bug report is
included inline.

### Pre-submission checklist

- [x] I searched existing open and closed issues and found no duplicate.
- [x] The behavior reproduces on the current `master` branch.
- [x] The behavior originates in Paperclip's repository skill, not an
adapter, provider, or local configuration.

### What happened?

The `pr-gardening` skill included community-authored and stale pull
requests in its actionable candidate set, aborted when issue-to-PR
extraction hit its cap, and only notified assignees rather than
dispatching the standard PR-preparation workflow.

### Expected behavior

By default, gardening should act only on PRs authored by the current
GitHub identity, report excluded community and stale PRs explicitly,
tolerate capped match sets, and dispatch actionable PRs through
`/prepare-paperclip-pr`. Operators should retain explicit overrides for
broader author scopes.

### Steps to reproduce

1. Run Stage A against issue history containing recently referenced PRs
from both the authenticated operator and community contributors.
2. Include an issue whose PR-reference extraction reaches the configured
match cap and an open PR with no activity inside the configured window.
3. Observe that the prior workflow admits non-owned and stale PRs,
aborts on the capped extract, and leaves Stage C at assignee reminders.

### Paperclip version or commit

Reproduced on upstream `master` at
`2568bdecc4577c60d76d58a45c5eaf3dc58f7e13`.

### Deployment mode

Local repository skill execution.

### Installation method

Built from source.

### Agent adapter(s) involved

Not adapter-specific; this is a repository maintenance skill.

### Database mode

Not database-related.

### Access context

Agent execution using the repository's authenticated GitHub CLI
identity.

### Node.js version

Current repository development environment.

### Operating system

Linux.

### Relevant logs or output

Live verification before the fix showed 264 community PRs entering
discovery scope. The corrected discovery retained 54 candidates, all
authored by `cryppadotta`.

### Relevant config

Default author resolution via `gh api user --jq .login`; no secret or
user-specific configuration is included.

### Additional context

The fix retains `--authors` and `--include-community` overrides for
intentionally broader maintenance runs.

### Privacy checklist

- [x] I reviewed all included output and configuration details for
secrets and PII.

## What Changed

- Resolve the default author allowlist from the authenticated `gh`
login, with `--authors` and `--include-community` overrides.
- Default the activity window to 14 days and record community-authored
and stale PRs in explicit dropped lists.
- Preserve capped issue-extract match sets with warnings instead of
aborting discovery.
- Add PR author and a one-line purpose summary to readiness data and
rendered reports.
- Rewrite Stage C to dispatch `/prepare-paperclip-pr` for PRs that need
gardening.
- Expand the focused Node test suite to cover the new scoping,
stale-drop, cap, summary, reporting, and guardrail behavior.

## Verification

- `node --test
.agents/skills/pr-gardening/scripts/pr-gardening.test.mjs` — 15/15
passing, including contributor-controlled Markdown escaping.
- `git diff --check origin/master...HEAD` — clean.
- Live discovery verification excluded 264 community PRs and retained 54
candidates, all authored by `cryppadotta`.

## Risks

- Low-to-moderate behavioral risk: default candidate scope is
intentionally narrower; operators who want community PRs must opt in
with `--include-community` or provide `--authors`.
- The authenticated `gh` login must be available unless an explicit
author override is supplied.
- No database, API, UI, migration, workflow, or dependency-lock changes.

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

## Model Used

- OpenAI Codex using GPT-5.4 with reasoning, repository tool use, shell
execution, GitHub CLI access, and focused test execution. The original
implementation commit also records Claude Fable 5 assistance.

## 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>
canary/v2026.727.0-canary.0
2026-07-27 09:24:11 -05:00
DottaandPaperclip 2568bdecc4 fix(adapter-utils): keep sandbox proxy sockets within Linux path limit (#10221)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents for work
> - Local process adapters can enforce network allowlists through a
Unix-socket proxy inside the Linux sandbox
> - The proxy socket was created under `os.tmpdir()`, which can be a
deeply nested run-specific directory
> - Linux Unix-domain socket paths are limited to 107 usable bytes, so
deep temporary paths can be silently truncated during bind
> - A truncated proxy socket resets every confined outbound connection,
including the model provider API, before the agent can do work
> - This pull request creates proxy sockets under the short `/tmp` path
when possible and validates the path length before bind
> - The benefit is reliable sandboxed egress under deep `TMPDIR` values
and an explicit error instead of an opaque connection-reset storm

## Linked Issues or Issue Description

### Pre-submission checklist

- [x] I searched existing open and closed issues and this is not a
duplicate.
- [x] I can reproduce this on upstream `master`.
- [x] I confirmed the error originates in Paperclip's local-process
sandbox proxy.

### What happened?

Sandboxed local-process agents using `networkScope: "allowlist"` could
lose all proxied egress when `TMPDIR` was deeply nested because
`proxy.sock` exceeded Linux's Unix socket path limit. The truncated bind
surfaced as repeated connection resets, including for provider API
traffic.

### Expected behavior

Proxy creation should use a Linux-safe short path and fail explicitly if
no safe socket path can be created.

### Steps to reproduce

1. Set `TMPDIR` to a path long enough that
`<TMPDIR>/paperclip-network-sandbox-XXXXXX/proxy.sock` exceeds 107
bytes.
2. Build or run a local-process sandbox with `networkScope:
"allowlist"`.
3. Make an HTTP or HTTPS request through the generated sandbox proxy.
4. Observe connection resets from the overlong Unix socket path on
affected code.

### Paperclip version or commit

Upstream `master` before this change.

### Deployment mode

Other — Linux local-process adapters using Bubblewrap network
allowlisting.

### Installation method

Built from source.

### Agent adapter(s) involved

Codex and any other local-process adapter using the shared sandbox
utility.

### Operating system

Linux.

### Additional context

GitHub search found no duplicate public issue or pull request for this
defect.

## What Changed

- Add a Linux Unix-socket byte-length guard that reports the unsafe path
before binding.
- Create network proxy temporary directories under `/tmp` first, with
`os.tmpdir()` as a validated fallback.
- Use the safe temporary-directory helper at both allowlist proxy
creation sites while preserving trusted URL handling.
- Add regression coverage that sets a deliberately deep `TMPDIR` and
verifies the working socket remains within 107 bytes under `/tmp`.

## Verification

- `node
/srv/paperclip/home/paperclipai/paperclip/node_modules/vitest/vitest.mjs
run packages/adapter-utils/src/local-process-sandbox.test.ts` — 8
passed, 4 environment-gated tests skipped.
- `git diff --check origin/master...HEAD` — passed.
- Greptile Review — passed after reviewing 2 files with 0 comments and
no unresolved threads; this repository integration did not emit a
separate numeric confidence score.
- Full GitHub CI matrix — passed after one rerun of an unrelated ACPX
`ENOTEMPTY` cleanup flake.
- Package typecheck was attempted, but the existing shared install
cannot resolve `acpx/runtime`; the failure is outside the changed files
and is expected to be covered by CI's clean dependency install.

## Risks

- Low risk: the change is limited to Linux sandbox proxy
temporary-directory selection and validation.
- Systems without a writable `/tmp` fall back to `os.tmpdir()` only when
the resulting socket path is safe; otherwise startup now fails loudly
instead of producing connection resets.
- No schema, API, UI, migration, or documentation behavior changes.

> 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 managed
reasoning and code execution; context-window size is not exposed by the
runtime.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.726.0-canary.0
2026-07-26 10:52:16 -05:00
Devin FoleyandPaperclip 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>
canary/v2026.725.0-canary.3
2026-07-25 10:06:28 -07:00
DottaandPaperclip 4c55f0d8da fix(inbox): hide external object summaries (#10020)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The inbox helps operators scan and act on tasks that need attention
> - Inbox task rows currently include external-object summary markers
alongside the core task information
> - Those markers add a column of visual noise that is not needed for
inbox triage
> - External-object data must remain available to the inbox filters even
when the row marker is removed
> - This pull request stops passing external-object summaries into inbox
rows and adds regression coverage
> - The benefit is a cleaner inbox while preserving external-object
filtering behavior

## Linked Issues or Issue Description

- Refs #4556
- **Problem:** Inbox task rows display external-object summary markers
that operators do not need for triage.
- **Expected behavior:** Inbox rows omit the external-object marker,
while filters that depend on external-object summaries continue to work.

## What Changed

- Removed the external-object summary prop from inbox task rows.
- Added a regression test that provides external-object summary data and
confirms the inbox row does not render its marker.
- Kept external-object summary loading intact for inbox filtering.

## Verification

- `pnpm exec vitest run ui/src/pages/Inbox.test.tsx` — 18 tests passed.
- `pnpm check:token-gates` — reproduces five pre-existing `#9627`
color-literal violations; this PR adds no token values or new gate
violations.

## Risks

- Low risk: the change removes one optional presentation prop from the
inbox row call site and leaves filtering data flow unchanged.
- Regression coverage verifies summary data no longer produces the
removed inbox marker.

> 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.4, tool-enabled coding agent with shell and code
execution; reasoning enabled; context-window size not exposed by the
runtime.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.725.0-canary.2
2026-07-25 08:59:44 -05:00
DottaandPaperclip c481be44e3 fix(task-watchdogs): deduplicate unchanged stopped-state wakes (#10207)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Task watchdogs review issue subtrees when no run or queued wake
keeps work live
> - Pending human interactions and approvals are valid stopped states
that still need one watchdog review
> - The existing fingerprint included volatile activity timestamps, so
unchanged stopped trees could wake repeatedly after comments, documents,
work products, or sibling completions
> - This pull request fingerprints only review-material leaf and wait
state, persists the reviewed snapshot, and suppresses shrink-only
repeats
> - The benefit is one review per materially new stopped state without
weakening liveness classification or hiding human waits

## Linked Issues or Issue Description

### What happened?

Task-watchdog stop fingerprints changed for metadata-only activity and
completed siblings, producing duplicate wakes after an unchanged stop
had already been reviewed.

### Expected behavior

Pending interactions and approvals remain classified as stopped, but a
reviewed stopped state only wakes again when waits, non-terminal leaves,
status, assignment, or blockers gain material changes.

### Steps to reproduce

1. Review a stopped watched subtree with a pending human wait or
multiple non-terminal stopped leaves.
2. Add only comment/document/work-product activity, or complete one
stopped sibling without changing the wait set.
3. Observe a duplicate wake from the timestamp-heavy fingerprint.

Related public work: Refs #9452 for overlapping task-watchdog service
edits and #10043 for related no-op fingerprint suppression.

## What Changed

- Added fingerprint v2 over non-terminal material leaves plus
subtree-wide pending wait ids, excluding volatile timestamps while
retaining them in wake context.
- Added nullable observed/reviewed JSONB stop snapshots and shrink-only
reviewed-state suppression with legacy exact-fingerprint fallback.
- Added pending interaction kinds and approval ids to watchdog wake
context, review comments, and comment metadata.
- Added classifier and scheduler coverage for waiting-leaf liveness,
metadata stability, sibling shrink suppression, material changes,
snapshot promotion, legacy rows, and unchanged idempotency keys.

## Verification

- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/task-watchdogs-classifier.test.ts
src/__tests__/task-watchdogs-scheduler.test.ts` — 2 files, 36 tests
passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `git diff --check origin/master...HEAD` — passed.

## Risks

- Fingerprint version 2 intentionally re-fingerprints every currently
stopped watched tree once after deployment, causing a one-time wake
burst before the new reviewed snapshots are established.
- Migration `0191_task_watchdog_stop_snapshots.sql` only adds two
nullable JSONB columns with no backfill; legacy rows continue
exact-fingerprint behavior until a post-deploy review promotes a
snapshot.
- PR #9452 edits the same service file; whichever lands second may need
a trivial rebase.

> 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 tool use and code execution. The runtime did not expose a
context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR 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>
canary/v2026.725.0-canary.1
2026-07-25 08:34:41 -05:00
DottaandPaperclip 4e00818574 fix(runtime): support in-place workspace realization (#10230)
## Thinking Path

> - Paperclip is the control plane people use to coordinate AI agents
and their execution environments.
> - Environment realization decides where an agent runs and which
filesystem and toolchain are authoritative.
> - Copy-based realization is unsafe for container-anchored tasks
because absolute paths such as `/app` can point outside the synchronized
tree and task-specific binaries may be absent.
> - That mismatch can let an agent successfully verify work in a phantom
writable path while sync-back silently discards the result.
> - Existing task environments already provide the authoritative
filesystem and toolchain, so they should be executed in place rather
than copied.
> - Copy mode still needs explicit confinement rules so aliases target
the synchronized workspace and unsynchronized writable paths fail
visibly.
> - This pull request adds typed realization metadata, propagates the
authoritative root through orchestration, and teaches Codex to honor it.
> - The benefit is that container-anchored tasks operate on
verifier-visible state with the intended tools, while copy mode remains
safe and backward compatible.

## Linked Issues or Issue Description

No public GitHub issue exists for this defect.

GitHub duplicate searches for in-place execution, workspace realization,
and authoritative workspace roots found no related pull request to link.

### What happened?

Environment-backed agent runs were always realized through a copied
workspace. Tasks anchored to absolute container paths could therefore
write outside the synchronized tree, and task-provided toolchains were
unavailable in the copy. A run could report success even though
sync-back discarded its output.

### Expected behavior

Existing task environments should run against their real authoritative
root and toolchain. Copy-mode runs should map declared absolute aliases
into the synchronized tree and reject writable paths that cannot be
restored.

### Steps to reproduce

1. Run a Codex task environment whose required files live under `/app`
or `/workspace` and whose required binary exists only in the task
container.
2. Observe that copy realization changes the effective
filesystem/toolchain or permits writes outside the synchronized root.
3. Complete and verify the task inside the agent sandbox.
4. Observe that the verifier cannot see out-of-tree artifacts or that
task-specific commands were unavailable.

### Reproduction context

- Paperclip commit: `3a16b91217483d2c233926de5b7f7bc3a1077924`
- Deployment: built from source in a task-container execution
environment
- Adapter: Codex local
- Database: not database-related
- Access context: agent execution

## What Changed

- Added typed `copy | in_place` workspace-realization metadata,
authoritative roots, confined aliases, and outbound restore paths to
shared execution-target contracts.
- Selected in-place realization for existing task environments and
skipped archive prepare/restore when the authoritative environment is
used directly.
- Propagated the authoritative root into adapter context so Codex uses
it for cwd and `PAPERCLIP_WORKSPACE_*` semantics, including ACP
execution.
- Bound copy-mode aliases such as `/app` to the synchronized workspace
and rejected writable out-of-tree paths without explicit restore
mappings.
- Added focused regression coverage while preserving existing copy-mode
archive restore behavior.

## Verification

- `pnpm --filter @paperclipai/shared typecheck` — passed.
- `pnpm exec vitest run
packages/adapter-utils/src/local-process-sandbox.test.ts
packages/adapters/codex-local/src/server/acp.test.ts
packages/adapters/codex-local/src/server/execute.remote.test.ts
server/src/__tests__/environment-run-orchestrator.test.ts` — 48 passed,
4 skipped.
- `pnpm -r typecheck` — passed.
- `env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u
AWS_SESSION_TOKEN pnpm test:run` — passed across all general and
serialized Vitest shards.
- `pnpm build` — passed.
- Codex `k=1` acceptance run completed July 24, 2026 at 23:54:30 UTC
with 4 completed, 0 exceptions, and mean reward 1.0: `build-cython-ext`,
`openssl-selfsigned-cert`, `prove-plus-comm`, and `sqlite-db-truncate`
each received terminal grade 1.0 against real task-environment paths and
toolchains.

## Risks

- In-place mode deliberately exposes the authoritative task root to the
adapter; incorrect environment metadata could point execution at the
wrong root. Typed metadata and focused orchestration tests cover
selection and propagation.
- Copy-mode writable-path validation is stricter and may reject
previously accepted unsafe configurations. The rejection is intentional
and produces a visible error instead of silently losing output.
- The acceptance run is focused on four Codex task-environment
workloads, not a broad cross-adapter benchmark. Existing copy-mode
archive tests and the full repository suite remain green.

> 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 CLI coding agent; exact model ID and context-window size
were not exposed to this runtime. Capabilities used: extended reasoning,
repository editing, shell execution, test/build execution, Git, GitHub
CLI, and Paperclip API 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
- [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>
canary/v2026.725.0-canary.0
2026-07-25 08:29:26 -05:00
cca2806e57 test(tool-gateway): make idle-down slot test deterministic via injected clock (#10226)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The server has a gateway layer that coordinates tool execution and
runtime slots
> - The idle-down test for the local stdio fixture slot was relying on
real wall-clock timing
> - On slower runners, that made the test nondeterministic because the
slot could be reaped before the presence assertion ran
> - This pull request switches the test to use the existing injectable
clock seam so time only advances when the test says it should
> - The benefit is that the idle-down behavior stays covered while the
test becomes deterministic and no longer flakes under load

## Linked Issues or Issue Description

This PR fixes a flaky gateway test in the server test suite. The
`tool-gateway` idle-down scenario was asserting slot presence while also
depending on a very short real-time idle TTL and a later sleep-based
reap. On loaded runners, the intervening work could exceed the TTL,
which caused the slot to disappear early and the assertion to see an
empty list.

The fix keeps the production code path unchanged and drives the test
from the supervisor's existing injectable clock. The test now holds time
steady through the presence check, then advances the clock past the idle
deadline to trigger the reap deterministically. The original behavioral
assertions stay intact: slot reuse, counter increments, metadata, and
stop status still get verified.

## What Changed

- Replaced the real-time idle-down wait in the `tool-gateway` test with
the runtime supervisor's injectable clock seam.
- Kept the existing assertions for slot reuse, slot identity, counters,
metadata, and stop behavior.
- Removed the test's dependency on wall-clock timing so the idle-down
path is deterministic under load.

## Verification

- Targeted server typecheck passed with `tsc --noEmit`.
- `tool-gateway.test.ts` passed in full: 49/49.
- The targeted idle-down scenario passed 50/50 in a tight loop with 0
failures after the clock injection change.

## Risks

- Low risk: this is a test-only change and does not modify production
gateway logic.
- The test now exercises the idle-down logic through a controlled clock
rather than real elapsed time, which is the point of the fix but does
slightly reduce wall-clock realism in the test itself.

## Model Used

OpenAI Codex (GPT-5), tool-using coding agent; context window not
surfaced in the 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: Harold Kim <harold@paperclip.ing>
Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.724.0-canary.17
2026-07-24 16:29:47 -07:00
DottaandPaperclip 30ff3d7c58 feat(routines): expose activity gate API (#9438)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Scheduled routines provide recurring control-plane work without
manual intervention
> - The new activity gate can suppress scheduled runs when no external
work occurred
> - The core scheduler and database support landed without a public
create/update contract
> - Agents, operators, and managed plugins need validated fields plus
discoverable semantics to opt in safely
> - This pull request exposes the activity gate through routine APIs,
revisions, plugin contracts, tests, and skill documentation
> - The benefit is backward-compatible control over idle scheduled work
without losing activity-triggered follow-up

## Linked Issues or Issue Description

- Refs #8534

## What Changed

- Added shared activity-gate policy and scope enums with create/PATCH
validation.
- Persisted activity-gate fields through routine creation, updates,
revision snapshots, pipeline snapshots, and revision restores.
- Defaulted legacy revision snapshots during restore and added
regression coverage for pre-field snapshots.
- Extended managed-plugin routine declarations, production
reconciliation, and the SDK test harness to preserve non-default gate
settings.
- Added end-to-end API coverage for create/PATCH/list/detail
round-trips, defaults, and invalid enum rejection.
- Documented schedule-only semantics, activity windows,
own-run/read-action exclusions, scopes, and an hourly quiet-night
watcher example.

## Verification

- `pnpm exec vitest run packages/shared/src/validators/routine.test.ts
server/src/__tests__/routines-service.test.ts
server/src/__tests__/routines-e2e.test.ts`
- `pnpm exec vitest run packages/shared/src/validators/plugin.test.ts
packages/plugins/sdk/tests/testing-actions.test.ts
server/src/__tests__/plugin-managed-routines.test.ts
server/src/__tests__/routines-service.test.ts -t 'activity
gate|preserves declared activity gate settings|resolves routine agent
and project refs'`
- `pnpm exec vitest run ui/src/lib/workspace-routines.test.ts
ui/src/pages/Routines.test.tsx`
- `pnpm --filter @paperclipai/shared typecheck`
- `pnpm --filter @paperclipai/plugin-sdk typecheck`
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm check:token-gates`
- GitHub CI: all final-head checks green; Storybook visual regression
skipped by path rules.
- Greptile: 5/5 with no unresolved review threads.

## Risks

- Low risk: defaults remain `always` and `company`, preserving existing
routine behavior and old revision snapshots.
- Managed plugin manifests can now declare the same validated gate
settings as the public routine API; omitted values retain core defaults.
- Revision snapshots now include the new fields so policy changes are
not lost or treated as no-ops during restore.

> For core feature work, checked `ROADMAP.md`: this extends the existing
Scheduled Routines roadmap item and does not duplicate a separate
planned capability.

## Model Used

- OpenAI GPT-5.5 via Codex CLI, with repository tool use and code
execution; context-window size was not exposed by the runtime.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [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>
canary/v2026.724.0-canary.16
2026-07-24 16:47:24 -05:00
DottaandPaperclip 8f08ec5ce6 feat(status-cards): join summary-mentioned issues to watched set (#10205)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Status cards summarize changing company work and watch issues so
later changes can produce useful deltas
> - A summary can explicitly reference issues that are important to the
update even when those issues do not match the card's configured queries
> - Previously, those referenced issues were not retained in the watched
set, so their later status, assignee, or comment changes could be missed
> - The watched snapshot must avoid artificial additions or removals
caused only by a summary changing which issues it references
> - This pull request resolves issue references when a summary is
written, persists them, and joins them to the watched snapshot with
stable delta semantics
> - The benefit is that status cards continue tracking the exact issues
their latest update called out while keeping follow-up updates relevant
and non-duplicative

## Linked Issues or Issue Description

### Pre-submission checklist

- [x] I have searched existing open and closed issues and this is not a
duplicate.
- [x] I am on the latest released version of Paperclip (or can reproduce
on `master`).
- [x] I have confirmed the error originates in Paperclip itself — not in
my agent adapter, API provider, or local configuration.

### What happened?

When a status-card summary explicitly referenced an issue by identifier
or `/issues/<uuid>` URL, that issue was not automatically retained in
the card's watched set unless it independently matched a configured
query. Later status, assignee, or comment changes to an issue
highlighted by the latest update could therefore be omitted.

### Expected behavior

References in the latest summary should resolve only within the card's
company, appear in dry runs and the watched-issues UI, count and
fingerprint like query matches, and enter or leave the watched set
without artificial added/removed deltas already represented by the
summary change.

### Steps to reproduce

1. Create a status card whose query does not match a second issue in the
same company.
2. Write a summary that references the second issue by identifier or
issue URL.
3. Inspect the card's watched count or Watched issues tab.
4. Change the referenced issue's status, assignee, or comments and run
the next update.
5. Before this change, the referenced issue is absent from the watched
snapshot and its later change does not produce the expected delta.

### Paperclip version or commit

- Reproduced on `master` before this PR (base commit `762ce5b4ef`).

### Deployment mode

- Local dev (`pnpm dev`), built from source.

### Agent adapter(s) involved

- Not adapter-specific (core bug).

### Database mode

- Embedded Postgres test environment; the schema change uses standard
PostgreSQL JSONB.

### Access context

- Board (human operator).

## What Changed

- Added migration `0191` and schema support for persisted
`status_cards.mentioned_issue_ids`.
- Resolved summary references by issue identifier or `/issues/<uuid>`
URL within the status card's company when summaries are written.
- Joined mentioned issues into watched counts and fingerprints so later
status, assignee, and comment changes generate normal update deltas.
- Suppressed artificial added/removed deltas when the latest summary
starts or stops mentioning an issue.
- Added `mentionedIssues` to dry-run responses and a “Mentioned in the
latest update” group in the Watched issues tab.
- Updated the summarizer prompt to explain that referenced issues
automatically join the watched set.
- Added focused server and UI coverage for reference resolution,
snapshot behavior, deltas, API responses, and rendering.

## Verification

- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/status-cards.test.ts
src/__tests__/status-card-update-engine.test.ts` — 31 tests passed.
- `pnpm --filter @paperclipai/ui exec vitest run
src/pages/StatusCards/StatusCardTile.test.tsx` — 11 tests passed.
- Earlier implementation verification also passed database/shared/server
typechecks, UI `tsc -b`, the broader StatusCards UI test set, and
embedded-Postgres migration application.

### Visual Verification

- Greptile T-Rex ran Playwright browser checks successfully and captured
the Status Card drawer Watched tab showing the new “Mentioned in the
latest update” grouping:
https://app.greptile.com/trex/runs/15796101/artifacts

## Risks

- The migration adds a nullable JSONB column and is backward-compatible;
existing cards have no mentioned issues until their next summary write.
- Reference extraction is company-scoped to prevent cross-company issue
association.
- Watched counts and future fingerprints change for cards whose latest
summaries reference issues; tests cover additions, removals, and
suppression of spurious deltas.
- This targeted status-card fix does not introduce a new roadmap
subsystem or external integration.

## Model Used

- Anthropic Claude Fable 5 (Paperclip model alias; exact underlying
provider model ID and context window were not recorded in the
implementation task metadata), with extended reasoning, tool use, and
code execution.
- OpenAI Codex coding agent (runtime model identifier and context window
not exposed to this task) prepared the PR, rebased the branch, and ran
focused verification with terminal 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)
- [ ] 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-24 16:44:56 -05:00
DottaandPaperclip 665408c6d0 fix(codex): classify mid-turn harness crashes structurally as retriable infra (#10210)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents and their work
> - Heartbeat execution relies on adapters distinguishing agent failures
from failures in the harness running beneath the agent
> - Codex MCP transport crashes can kill the CLI after the JSONL
protocol has started but before it emits a protocol-terminal event
> - Those interrupted streams were left unclassified, so the control
plane terminalized the heartbeat as `heartbeat_failed` / `agent_failure`
with no continuation
> - Agent-level failure is already expressible through the JSONL
protocol via an `error` event, `turn.failed`, or `turn.completed`, so an
interrupted nonzero exit can be classified structurally without
inspecting unstable error strings
> - This pull request reports that shape as `codex_harness_crash` in the
`transient_upstream` family and routes it through Paperclip's existing
bounded retry and recovery-continuation paths
> - The benefit is that transient Codex harness failures recover safely
without misclassifying quoted agent output or depending on
transport-specific wording

## Linked Issues or Issue Description

- **What happened:** Codex MCP transport failures, including rmcp worker
death, could terminate the CLI mid-turn after protocol output began but
before any terminal JSONL event. The run then became an unclassified
terminal heartbeat failure with `continuationCount: 0`; this occurred in
3 of 44 L3 Codex-lane trials during the associated benchmark
investigation.
- **Expected behavior:** a nonzero Codex exit after the protocol starts
but before an `error`, `turn.failed`, or `turn.completed` event should
be treated as a harness/infrastructure crash and enter the existing
bounded retry policy.
- **Why structural classification:** transport error strings vary, and
stdout may quote agent output that merely discusses network failures.
The protocol boundary identifies whether the agent itself produced a
terminal result without regex matching.
- **Recovery behavior:** `codex_harness_crash` maps to `errorFamily:
transient_upstream`, using the existing `same_session` →
`safer_invocation` → `fresh_session` ladder plus the
recovery-continuation transient-infrastructure path.
- Supersedes the regex-based approach in #10150, which is closed.

## What Changed

- Added protocol-state tracking that identifies a nonzero exit after
protocol start and before any protocol-terminal event as
`codex_harness_crash`.
- Propagated the structural classification as `transient_upstream`
through the Codex adapter.
- Added parse unit coverage, including a faithful crash-shaped stream,
without matching stderr transport strings.
- Added adapter execution coverage using a fake Codex process that emits
a protocol prefix and then dies with the observed rmcp stderr line.
- Added heartbeat bounded-retry coverage, including the `errorCode`-only
fallback, and recovery-continuation classification coverage.

## Verification

- `parse.test.ts` — 16 passed.
- `codex-local-execute.test.ts` — 16 passed.
- `heartbeat-retry-scheduling.test.ts` — 30 passed.
- `service.pause-durability.test.ts` — 6 passed.
- Server and Codex adapter TypeScript checks passed.
- The branch commit is unchanged from the tested and pushed `88f5464d40`
handoff.

## Risks

- Low risk: the classification requires a nonzero exit after protocol
start and before any protocol-terminal event, so normal agent-declared
failures and completed turns keep their existing behavior.
- The change intentionally broadens recovery for structurally
interrupted Codex runs; bounded retry limits still prevent indefinite
continuation loops.
- No schema, migration, public API, UI, lockfile, or workflow changes.

> 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. The exact runtime model ID and
context-window size were not exposed by the execution environment;
capabilities used for the implementation included repository analysis,
reasoning, code editing, and terminal-based test 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
— the pre-existing, already-pushed branch name was explicitly prescribed
for this replacement PR
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [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-24 16:40:47 -05:00
DottaandClaude Fable 5 b996b71a38 Deduplicate wake-payload issue descriptions and compact resume deltas (#10216)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Heartbeat wake payloads and the task-context markdown are the two
channels that deliver an issue's brief into an agent's prompt
> - #10151 fixed wake-prompt-only adapter lanes waking without the issue
description by adding it to the structured wake payload
> - That left the description delivered twice per prompt on lanes that
also inject the task-context markdown, and re-delivered in full on every
resume wake, permanently bloating persistent-session context
> - This pull request makes the task markdown the single description
carrier on lanes that use it, and omits the description from
non-assignment resume deltas on all lanes while keeping it for
assignment-shaped and recovery wakes
> - The benefit is that every lane receives the brief exactly once when
it needs it, and long-lived sessions stop re-paying the full brief in
tokens on every wake

## Linked Issues or Issue Description

Refs #10151

Related prior work: #2883, #8402 (earlier description-delivery attempts
referenced by #10151). I searched the PR list for open work on
wake-payload description handling and found none besides the merged
#10151.

**Bug:** After #10151, adapters that inject the `Paperclip task context`
markdown (ACPX engine lanes, claude-local CLI, hermes server and
gateway) receive the issue description twice in a single prompt — once
in the wake prompt's `Issue description:` block and once in the task
markdown. Separately, resume deltas re-send the full description (up to
12k characters) on every wake even though the persistent session already
received it.

**Expected behavior:** The description appears exactly once per prompt
on every lane, and resume deltas only carry it when the resuming session
may not have seen the brief (assignment-shaped or recovery wakes),
leaving an explicit fetch breadcrumb otherwise.

**Reproduction:** Wake a claude-local or ACPX agent on an issue with a
description and inspect the assembled prompt: the description text
appears in both the wake-payload block and the task-context block. Wake
the same session again via a comment: the full description is present
again in the resume delta.

**Affected version:** Current `master` (with #10151 merged).

**Deployment mode:** Adapter-backed heartbeat execution, local and
sandboxed lanes.

## What Changed

- `renderPaperclipWakePrompt` accepts `suppressIssueDescription`; the
four task-markdown lanes pass it so the task markdown stays the single,
uncapped description carrier there.
- Non-assignment resume deltas omit the description and emit `- issue
description: omitted from this resume delta; fetch the issue if you need
the latest brief`. Assignment-shaped reasons (`issue_assigned`,
`issue_reopened_via_comment`, `issue_recovery_action_restored`,
`issue_tree_restored`) and recovery wakes still deliver the full brief.
- `buildPaperclipTaskMarkdown` gains `includeDescription`; the server
now also publishes `context.paperclipTaskMarkdownCompact` (description
stripped, directives and wake comment kept), and the new
`selectPaperclipTaskMarkdown` helper picks the right variant under the
same resume rules, falling back to the full markdown when no compact
variant exists (version skew safety).
- The wake prompt's description block now carries the same user-authored
trust framing the task markdown already had.

## Verification

- `npx vitest run packages/adapter-utils/src/server-utils.test.ts
packages/adapters/claude-local/src/server/acp.test.ts
packages/adapters/codex-local/src/server/acp.test.ts
server/src/__tests__/heartbeat-context-summary.test.ts` — 137 tests
passed, including new coverage for suppression, resume omission plus
breadcrumb, assignment-shaped resume inclusion, compact-variant
building, variant selection, and an end-to-end ACPX prompt-assembly test
asserting the description appears exactly once on fresh wakes and not at
all on comment resumes.
- `npx vitest run` in `packages/adapters/hermes` — 59 tests passed,
including a gateway execute-level test asserting the brief is sent
exactly once on fresh runs and not re-sent on stable-session resumes.
- `tsc --noEmit` in `packages/adapter-utils`,
`packages/adapters/claude-local`, `packages/adapters/hermes` — clean;
`server` matches the `master` baseline exactly (pre-existing plugin-sdk
resolution errors only, none in touched files).
- Pre-existing failures confirmed identical on clean `master`:
claude-local `execute.remote.test.ts` / `test.probe.test.ts`,
adapter-utils `mcp-isolation.integration.test.ts` (requires a newer
local Claude CLI).

## Risks

- Behavioral shift, prompt-only: a resumed session woken by a comment on
an issue it never handled (rare — assignment wakes normally precede
comment wakes) would not get the inline description; the breadcrumb plus
the standard issue-fetch path covers it.
- Additive context key (`paperclipTaskMarkdownCompact`); older adapters
ignore it and newer adapters fall back to the full markdown when it is
absent, so mixed-version deployments degrade to current behavior.
- No schema, migration, or API changes; the structured wake-payload JSON
shape is unchanged.
- Known follow-up deliberately out of scope: openclaw embeds the raw
wake-payload JSON (which still contains the description) in prompt text
for machine parsing. The hermes-gateway lane is handled: it detects
stable-session resumes (issue/agent session-key strategy plus a stored
prior session id), compacts the task markdown, and omits the description
from its prompt-embedded JSON copy.

> This is a focused correctness/efficiency fix to existing wake plumbing
and does not overlap with planned roadmap feature work.

## Model Used

- Anthropic Claude Fable 5 (`claude-fable-5`), extended thinking
enabled, with repository tool use, shell execution, and local test
execution 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)
- [ ] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
(execution-workspace branch, same convention as merged #10202)
- [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
(code-level docs; no user-facing docs affected)
- [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

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
canary/v2026.724.0-canary.15
2026-07-24 16:35:07 -05:00
DottaandPaperclip d3c004d1b8 Fix issue descriptions in structured wake payloads (#10151)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Heartbeat wake payloads provide the scoped task context an agent
needs before it can act safely
> - Assignment wakes already loaded the issue description for task
markdown, but the structured wake-payload builder dropped it
> - Agents reading `PAPERCLIP_WAKE_PAYLOAD_JSON` could therefore see a
missing brief while also being told no fallback fetch was needed
> - Long descriptions also need a bounded representation so wake
environments and prompts remain safe
> - This pull request carries the description through the server and
adapter contract, and marks truncated descriptions as requiring fallback
fetch
> - The benefit is that agents receive the actual brief instead of
inventing requirements from the title

## Linked Issues or Issue Description

Fixes: #5844
Fixes: #2882

Related prior attempts: #2883 and #8402. This change adds focused
regression coverage and enforces the missing long-description fallback
invariant.

**Bug:** Issue-assignment wake payloads omitted the issue description
from the structured payload even when the issue had a populated
description.

**Expected behavior:** The structured wake payload includes the issue
description. If the description must be truncated for payload size,
`fallbackFetchNeeded` is `true`.

**Reproduction:** Assign an issue with a description to an agent and
inspect `PAPERCLIP_WAKE_PAYLOAD_JSON`; before this change,
`issue.description` was absent while `fallbackFetchNeeded` could remain
`false`.

**Affected version:** Reproduced on current `master` before this patch.

**Deployment mode:** Adapter-backed heartbeat execution, including local
Codex agents.

## What Changed

- Include `issues.description` in the server wake-payload query and
supplied issue summaries.
- Bound inline descriptions at 12,000 characters and force fallback
fetch when truncation occurs.
- Preserve and render description metadata through shared adapter
normalization and prompt rendering.
- Add focused tests for long-description fallback and exact brief-string
rendering.

## Verification

- `pnpm exec vitest run
server/src/__tests__/heartbeat-agent-session-message.test.ts
packages/adapter-utils/src/server-utils.test.ts` — 81 tests passed.
- `pnpm --filter @paperclipai/adapter-utils typecheck` — passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `git diff --check` — passed.

## Risks

- Low risk: the payload shape is additive.
- Very long descriptions are truncated at 12,000 characters; the payload
explicitly requests a fallback fetch for the full brief.
- Prompt size increases by the issue-description length for scoped
wakes, bounded by the same limit.

> This is a focused correctness fix and does not overlap with planned
roadmap feature work.

## Model Used

- OpenAI GPT-5.4 via Codex CLI, with reasoning, repository tool use,
shell execution, and test execution. The runtime did not expose a
context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR 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>
canary/v2026.724.0-canary.14
2026-07-24 15:40:39 -05:00
DottaandPaperclip b3b07ae44e fix(codex): preserve silent active builds (#10153)
## Thinking Path

> - Paperclip is the open source control plane people use to coordinate
AI agents and their work.
> - Local adapters are responsible for observing agent subprocesses and
terminating runs that are genuinely stuck.
> - The Codex local adapter currently treats output bytes as its only
liveness signal for the 30-minute inactivity monitor.
> - Healthy compile and test loops can consume CPU and perform disk I/O
for longer than that without producing terminal output.
> - Terminating those runs loses valid work, while removing the monitor
entirely would allow truly wedged processes to run indefinitely.
> - This pull request adds a Linux process-group activity probe that
recognizes meaningful CPU, disk I/O, and child-process churn while
retaining the existing timeout for idle processes.
> - The benefit is that long silent builds can finish without weakening
the adapter's hung-run safety net.

## Linked Issues or Issue Description

No public GitHub issue was found in the duplicate/related search.

**What happened**

A healthy Codex local run executing a long compile/test loop could be
terminated at the default 30-minute output-inactivity threshold when the
child process emitted no stdout or stderr.

**Expected behavior**

The inactivity monitor should keep a silent run alive while its process
group is doing meaningful work, but should still terminate a process
group that is alive and idle.

**Steps to reproduce**

1. Run Codex local with the default `outputInactivityTimeoutMs`.
2. Have the agent start a compile or test command that consumes CPU or
disk I/O without terminal output for longer than the threshold.
3. Observe the adapter terminate the otherwise healthy process group as
output-inactive.

**Affected version / deployment mode**

Observed on a local-process Paperclip deployment using the Codex local
adapter with the 30-minute default inactivity monitor.

## What Changed

- Added a Linux `/proc` process-group sampler that tracks meaningful CPU
tick growth, disk I/O growth, and child-process membership changes.
- Reset the existing Codex inactivity timer when that sampler observes
real process work, while leaving remote and non-Linux behavior
unchanged.
- Added diagnostics for the number of process-activity resets and
documented the expanded liveness semantics.
- Added unit coverage for process-activity timer resets and subprocess
regressions for both a long silent CPU build and a genuinely wedged
child.

## Verification

- `pnpm --filter @paperclipai/adapter-codex-local typecheck`
- `pnpm exec vitest run
packages/adapters/codex-local/src/server/process-activity-monitor.test.ts
packages/adapters/codex-local/src/server/output-inactivity-monitor.test.ts
packages/adapters/codex-local/src/server/output-inactivity-monitor.integration.test.ts`
- Focused result: 23 tests passed, including a silent CPU-bound
subprocess that runs four times beyond the simulated inactivity window
and an idle subprocess that is still terminated.

## Risks

- Low risk and Linux-scoped: the new probe reads `/proc` every 15
seconds only while a monitored local Codex child is running.
- The CPU threshold requires sustained work rather than any single
scheduler tick, reducing the risk that a nearly idle event loop is
treated as productive.
- If `/proc` sampling is unavailable or fails, the adapter falls back to
the existing output-only 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 with model `gpt-5.6-sol`, high reasoning effort,
terminal/tool execution, code editing, and test execution. The runtime
did not expose a context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR 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>
canary/v2026.724.0-canary.13
2026-07-24 15:27:24 -05:00
DottaandPaperclip e4662b1f9d fix: preserve control plane access in Codex sandbox (#10152)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents for work
> - Local coding adapters can be confined with filesystem and network
sandbox policies
> - Codex confinement proxied only user-allowlisted hosts, so it denied
Paperclip's own run API and managed MCP endpoints
> - The same proxy returned untyped plaintext denials, which MCP clients
could treat as a fatal unexpected content type
> - Host-only `PAPERCLIPAI_CMD` values could also leak into agents even
when the referenced checkout module did not exist
> - This pull request gives the sandbox an explicit trusted-URL channel
for Paperclip endpoints, returns structured JSON errors, and removes the
inherited host CLI pointer
> - The benefit is confined Codex agents retain control-plane access
without broadening the operator's external network allowlist or crashing
on policy denials

## Linked Issues or Issue Description

Refs #3802

Related foundation: #9504

### What happened?

A `codex_local` agent configured with `networkScope: "allowlist"` and an
external-only allowlist could not reach its own Paperclip API or
Paperclip-managed MCP endpoints. The sandbox proxy returned a `403`
plaintext response without `Content-Type`, and an inherited
`PAPERCLIPAI_CMD` could point at a missing checkout-local CLI module.

### Expected behavior

Paperclip's run-scoped API and managed MCP endpoints remain reachable
regardless of the user external allowlist. Policy denials are valid
structured JSON responses with an explicit media type, and host-only CLI
pointers are not inherited by agent processes.

### Steps to reproduce

1. Configure a `codex_local` agent with `networkScope: "allowlist"` and
`networkAllowlist: ["api.openai.com"]`.
2. Run the agent and request its Paperclip issue API or a
Paperclip-managed MCP endpoint.
3. Observe the sandbox proxy deny the request with an untyped plaintext
`403` response.

### Environment

- Paperclip commit: `f49a3f99` originally exhibited the defect; fix is
based on current `master`.
- Deployment: local source build on Linux.
- Adapter: Codex.
- Database: not database-related.
- Access context: agent bearer/run-scoped credentials.

## What Changed

- Added internal trusted URL rules to the local network allowlist proxy
and supplied the Codex run API plus managed MCP endpoints.
- Returned JSON error envelopes with `Content-Type` and `Content-Length`
for HTTP and CONNECT policy denials.
- Removed inherited `PAPERCLIPAI_CMD` from child process environments
while preserving explicitly constructed runtime variables.
- Added focused proxy and environment sanitizer regression tests.

## Verification

- `pnpm exec vitest run
packages/adapter-utils/src/local-process-sandbox.test.ts
packages/adapter-utils/src/server-utils-env.test.ts --reporter=verbose`
- 2 test files passed; 8 tests passed; 4 platform-dependent tests
skipped.
- `git diff --check`
- Package typecheck was attempted; it reaches unrelated current-`master`
type drift in untouched files (`spawnCwd` in `adapter-utils`, and
staged-runtime ACP types in `codex-local`).

## Risks

- Low risk: trusted access is restricted to exact HTTP(S) hostname and
port pairs derived from Paperclip-provided URLs.
- Invalid or non-HTTP trusted URL values are ignored rather than
broadening access.
- Denial response bodies change from plaintext to structured JSON;
status codes remain unchanged.

> 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 (exact model ID and context window are not
exposed to this runtime), reasoning and terminal/tool execution enabled.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.724.0-canary.12
2026-07-24 15:25:59 -05:00
762ce5b4ef feat(acpx): per-step timing observability for sandbox run-startup (#10204)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Sandbox-backed runs need observable startup behavior so operators
can see where time is spent before an adapter is invoked
> - The current startup path only surfaced aggregate timing, which makes
it hard to identify the slow boundary in the bring-up sequence
> - That gap matters because sandbox startup latency is often dominated
by one specific step, and aggregate timing hides the bottleneck
> - This pull request adds per-step startup timing events for the named
sandbox bring-up boundaries
> - The benefit is more precise observability with no control-flow
change and no schema migration

## Linked Issues or Issue Description

### Subsystem affected
Cross-cutting (multiple of the above)

### Problem or motivation
Sandbox run startup only exposed aggregate timing. That makes it hard to
identify which bring-up boundary is responsible for slow starts,
especially in remote or sandboxed execution where the bottleneck can
move between workspace setup, skill reconciliation, bridge setup, and
adapter handshake.

### Proposed solution
Emit a structured timing event for each named startup boundary before
the adapter is invoked, so the existing run-event stream carries
per-step duration data. This keeps the event path additive and lets
operators see which step dominates startup latency without changing
control flow or introducing a schema migration.

### Alternatives considered
- Keep only the aggregate startup duration: simpler, but it hides the
bottleneck and makes regression analysis much harder.
- Add a new telemetry sink or schema field: rejected because the
existing run-event payload already carries structured event data and
does not need a new storage path.
- Log unstructured text for each step: rejected because it is harder to
query and aggregate than a structured `step` + `durationMs` event.

### Roadmap alignment
This fits the roadmap direction around cloud / sandbox agents and
enforced outcomes by improving observability for sandboxed execution
without changing the control plane model. The roadmap section is broad,
but it does not call out this specific startup-timing work as a planned
duplicate.

### Additional context
This PR is intentionally additive. It records timing for the named
startup boundaries in the existing event stream and leaves the bridge,
database shape, and adapter invocation order unchanged.

## What Changed

- Added a `measureStartupStep` helper that times a startup step, emits
one structured `run.startup.step` event, and rethrows failures after
recording duration
- Wrapped the seven sandbox bring-up boundaries in `execute.ts` so the
structured timing covers each named step before adapter invocation
- Added unit coverage for the helper and integration coverage for the
startup-step events in the adapter-utils execute path
- Kept the event path additive, with no bridge change and no database
migration

## Verification

- `tsc --noEmit` for `@paperclip/adapter-utils`
- `pnpm test` in `packages/adapter-utils` equivalent suite coverage: 292
passed, 4 skipped
- Adjacent server event/log-store suites: `run-log-store.test.ts` and
`heartbeat-run-log.test.ts` passed (11 total)
- Git validation: fetched `origin/feat/sandbox-startup-step-timing`,
confirmed it matches the authorized submit SHA, and confirmed
`origin/master..origin/feat/sandbox-startup-step-timing` contains the
expected single commit
- Searched GitHub for duplicate or related open PRs/issues and found no
overlapping open items
- Checked `ROADMAP.md`; the roadmap covers sandboxed environments
generally, but does not call out this specific startup-timing
observability work as a planned duplicate

## Risks

- Low risk: the change is additive and only emits additional structured
events
- If downstream consumers assume startup events are aggregate-only, they
may need to ignore or account for the new `run.startup.step` entries
- Timing is measured via the injected clock and event emission happens
in a `finally`, so failures still report duration before rethrowing

## Model Used

OpenAI GPT-5, tool-using coding 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
- [ ] 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: Harold Kim <harold@paperclip.ing>
Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.724.0-canary.11
2026-07-24 12:50:37 -07:00
7014e46e5b fix(recovery): wake ambiguous successful runs on normal model (#10184)
## Thinking Path

> - Paperclip is the open source control plane people use to coordinate
AI agents and their work.
> - The heartbeat recovery subsystem detects successful runs that leave
assigned issues `in_progress` without a durable disposition or
continuation path.
> - The existing corrective wake used a cheap, status-only model
profile, so the assignee could not perform missing verification or
deliverable work before choosing the issue disposition.
> - The existing wake prompt also omitted the original issue context and
the agent's own final report, making an honest finish/blocked/continue
decision harder.
> - This pull request keeps the structural handoff guards and
one-attempt loop bound, but wakes the assignee on its normal model lane
with context-rich instructions.
> - The benefit is that Paperclip asks the responsible agent to inspect
its own evidence, perform the smallest missing verification when needed,
and then record a real disposition without server-side prose
classification.

## Linked Issues or Issue Description

Related prior approach: #10154 (closed; this PR intentionally does not
reuse its regex classifier or route-level gate).

**Problem**

A succeeded agent run can leave its issue `in_progress` with no valid
disposition. Paperclip already detects this structurally and queues a
corrective handoff, but that wake currently runs as cheap/status-only
recovery and receives little context. The assignee may be unable to
create deliverables or verify the work, and the prompt does not quote
the report that caused the ambiguity.

**Expected behavior**

The corrective wake should use the assignee's normal model and adapter
settings, include the issue identifier/title/description, quote the
agent's own final report, include any recorded next action, preserve the
four disposition options, and explicitly require concrete verification
before marking the issue done.

**Scope**

This change does not classify run prose, add a route-level disposition
gate, alter run-liveness classification, or change the one-attempt
handoff loop bound.

## What Changed

- Switched successful-run corrective handoff payloads and context
snapshots from `status_only` to `normal_model`, removing cheap-model and
status-only guard hints.
- Added issue description, final-report, next-action, and
detected-progress fallback context to the handoff decision and
instruction builder.
- Reworked the instruction into clear "supposed to do / what happened /
options / what to do" sections with bounded description/report excerpts
and verbatim blockquotes.
- Added unit and heartbeat integration coverage for normal-lane
payloads, context plumbing, evidence quoting, fallback behavior, and
truncation while preserving structural skip tests.

## Verification

- `cd server && pnpm exec vitest run
src/services/recovery/successful-run-handoff.test.ts` — 24 tests passed.
- `cd server && pnpm exec vitest run
src/__tests__/heartbeat-process-recovery.test.ts -t "queues one
finish-handoff wake when a successful run leaves in-progress work
without a next action"` — 1 passed, 90 skipped.
- `pnpm --dir server typecheck` — passed.
- `git diff --check` — passed.

## Risks

- Low-to-moderate behavioral risk: an ambiguous successful run now
consumes the assignee's normal model rather than a cheap profile and may
perform verification or finish work before disposition.
- Prompt excerpts are bounded to approximately 1,200 description
characters and 2,000 report characters; very long context is
intentionally ellipsized.
- The existing structural skip guards, idempotency key, and single
corrective attempt remain unchanged to prevent loops.

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

## Model Used

- OpenAI Codex using `gpt-5.6-sol`, high reasoning effort, with
repository/tool execution. Context-window size was not exposed by the
runtime configuration.

## 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>
canary/v2026.724.0-canary.10
2026-07-24 14:32:26 -05:00
c9881223e4 fix(routines): show routines grouped by folder name (#10201)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Routines page is part of the operator UI for scheduled routine
management
> - The grouped-by-folder view was not presenting folder sections inline
in the main pane
> - That made the folder grouping mode harder to scan and hid the
separation between custom folders, Unfiled routines, and built-in
routines
> - This pull request updates the Routines page rendering so folder
groups appear as inline sections and built-in routines still split into
their own section afterward
> - The benefit is that grouped routines stay readable and the page
matches the intended folder organization

## Linked Issues or Issue Description

No corresponding public GitHub issue exists, so the problem is described
directly below following the bug template.

### What happened

On the Routines page, selecting Group → Folder flattened the grouped
list into a single "All routines" section with only the separate
built-in routines section below it.

### Expected behavior

Group → Folder should render one inline section per folder, keep
routines with no folder in an Unfiled section, and preserve the separate
built-in routines section after the custom folder groups.

### Steps to reproduce

1. Open the Routines page.
2. Change grouping to Folder.
3. Observe the main pane.
4. The routine list is flattened instead of grouped into folder-labeled
inline sections.

### Paperclip version / commit

Current PR head: `a8e384c838e362de3437c7a88bc7aa38b10fd9c0` on
`fix/routine-folder-grouping`.

### Deployment mode

Local development workspace for the Paperclip app UI.

## What Changed

- Updated the Routines page rendering so grouped folders render as
inline sections instead of flattening into a single list.
- Kept routines without a folder grouped under Unfiled.
- Preserved the built-in routines section after custom folder groups.
- Added and updated tests for the folder-grouped rendering behavior.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/pages/Routines.test.tsx`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm check:token-gates`

## Risks

- Low risk: the change is localized to the Routines page rendering and
its test coverage.
- The main behavioral risk is accidental grouping regressions if future
routine-grouping logic changes without updating the tests.

## Model Used

OpenAI Codex, GPT-5, tool-use enabled, 256k-context class model.

## 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
- [ ] 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: Harold Kim <harold@paperclip.ing>
Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.724.0-canary.9
2026-07-24 12:20:35 -07:00
DottaandClaude Fable 5 3a16b91217 feat(status-cards): single-message setup drives query and update prompt (#10202)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies and their ongoing work.
> - Status cards turn a standing question into recurring,
agent-generated summaries on the board.
> - The existing setup split intent across a watch prompt and separate
update instructions, which made creation and later behavior harder to
understand.
> - A status card should have one durable source of truth for both
deciding what to watch and telling the summarizer what each update must
contain.
> - This pull request makes the card prompt that source of truth,
simplifies creation to one step, and lets operators choose the running
agent immediately.
> - The benefit is a smaller mental model, fewer configuration modes,
and consistent update instructions throughout the card lifecycle.

## Linked Issues or Issue Description

Status cards currently require operators to express the same intent in
two places: the watch prompt and optional update instructions with
append/replace/none modes. This feature simplifies the experimental
status-card workflow so a single prompt defines both the watch query and
every generated update. The create flow must also support selecting the
responsible agent without a second setup step.

Related prior status-card work: #10101.

## What Changed

- Use the status card's single prompt to compile the watch query and
directly instruct every summary update.
- Add migration `0190_status_card_single_prompt` to remove
`status_cards.instructions_mode` and `status_cards.instructions`.
- Add `agentId` to `createStatusCardSchema`, validate company
membership, and default new cards to the built-in Summarizer.
- Replace the two-step create flow with one prompt-and-agent dialog and
extract a shared `SummarizerAgentSelect` for create/settings surfaces.
- Remove the extra-instructions settings section, reset incremental
history when the prompt changes, and rename the board page to "Status".
- Update the bundled `status-card-query` skill and board-operator
documentation, then regenerate the skills catalog manifest.

## Verification

- Server status-card suites: 29/29 passing.
- UI `StatusCards` suites: 22/22 passing.
- Skills catalog suite: 20/20 passing.
- `tsc -b` passes for server, UI, shared, and database packages.
- `pnpm check:migrations` passes.
- Light and dark mode screenshots cover the new create dialog and
settings tab.

## Risks

- Migration `0190` intentionally drops existing separate instruction
text. Existing card prompts remain and become the update instructions
under the new model; status cards are experimental and feature-flagged.
- Prompt edits now reset the incremental summary chain and trigger a
full rebuild, which is intentional because the prompt is also the update
contract.
- Agent selection is company-scoped; invalid agent ids return a
validation error rather than creating a misrouted card.

> 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

- Implementation: Anthropic Claude via the `claude_local` adapter, agent
label "Claude Fable 5"; extended reasoning, tool use, and code
execution. The exact provider model id and context-window value were not
retained in the task metadata.
- PR preparation: OpenAI GPT-5.4 through Codex CLI, with reasoning,
repository inspection, GitHub CLI, and Paperclip API 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)
- [ ] 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 Fable 5 <noreply@anthropic.com>
canary/v2026.724.0-canary.8
2026-07-24 14:06:14 -05:00
LeonSGPandAndrew Aymeloglu b083b173ea fix(db): use calendar month retention for backups (#3718)
## Thinking Path

> - Paperclip includes built-in database backup and retention behavior
as part of its operational reliability surface.
> - The retention implementation lives in
`packages/db/src/backup-lib.ts`.
> - Monthly pruning is intended to keep the newest backup per retained
calendar month.
> - The current cutoff uses a fixed 30-day approximation, which deletes
January backups too early when the current month has 31 days.
> - This pull request switches the monthly cutoff to calendar-month
boundaries instead of a fixed day multiplier.
> - The benefit is that monthly retention now matches the documented
calendar-month behavior and does not prune valid backups prematurely.

## Linked Issues or Issue Description

Fixes #3713

Two other pull requests implemented the same fix and have already been
closed as duplicates of this one:

- #3798 — same author's later take. Anchors the cutoff to the 1st
correctly, but mutates the date in local time and leaves `monthKey` on
local time, and unit-tests the helper in isolation rather than end to
end.
- #4031 — decrements the month without anchoring to the 1st, so
partial-month drift and a `setMonth` day-overflow edge case remain. No
tests.

## What Changed

- Replaced the fixed `30 * 24h` monthly retention cutoff with a
calendar-month cutoff anchored to the first day of the earliest retained
month.
- Added a regression test that freezes `Date.now()` at March 31 and
proves the newest January backup is retained when `monthlyMonths=2`.
- Kept the rest of the pruning behavior unchanged: daily and weekly
tiers still use their existing windows and bucket selection rules.

## Verification

- `pnpm --filter @paperclipai/db exec vitest run src/backup-lib.test.ts`
- `pnpm --filter @paperclipai/db exec tsc --noEmit`
- Note: `pnpm --filter @paperclipai/db typecheck` hits an
environment-specific `check:migrations` runtime failure on this host
(`Cannot find module ./cjs/index.cjs from ` via Bun), so I used plain
`tsc --noEmit` to validate the code changes themselves.

## Risks

- Low risk. This only changes the monthly retention cutoff calculation.
- The pruning buckets are still selected the same way; the fix only
widens the retained month window to align with calendar-month semantics.

## Model Used

- OpenAI Codex GPT-5 coding agent with terminal 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 searched GitHub for duplicate or related PRs and linked
them above
- [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

---

<sub>Edited by commitperclip during triage: added the **Linked Issues**
section (`Fixes #3713`) and the duplicate-PR search line the PR template
requires. The duplicate search was performed by the triage pipeline,
which grouped this PR with #3798 and #4031 and selected this one as the
canonical fix. Everything else is the author's original
description.</sub>

---------

Co-authored-by: Andrew Aymeloglu <aaymeloglu@gmail.com>
canary/v2026.724.0-canary.7
2026-07-24 13:12:43 -05:00
7e40ed8c43 feat(status-cards): add experimental status card update view (#10101)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies.
> - Operators need a board-level way to monitor a changing slice of
company work without repeatedly rebuilding filters or reading raw task
threads.
> - Existing summaries are useful snapshots, but they do not provide a
dedicated query-backed card with refresh policy, change tracking, update
history, and per-update cost visibility.
> - The capability needs to be safe to evaluate before it becomes part
of the default product surface.
> - This pull request adds end-to-end experimental Status Cards, from
schema and query compilation through update orchestration and operator
UI.
> - The entire feature is gated behind the `enableStatusCards`
experimental toggle, including its route and sidebar entry.
> - The benefit is a governed, inspectable way to keep focused
operational rollups current while preserving explicit controls over
refresh frequency and spend.

## Linked Issues or Issue Description

### Subsystem affected

Cross-cutting (`packages/db`, `packages/shared`, `server/`, `ui/`, and
bundled skills/docs).

### Problem or motivation

Operators cannot currently define a reusable natural-language view of
company work, compile it into an inspectable query, and keep its summary
current as matching issues change. Rebuilding filters and rereading task
threads makes board-level monitoring repetitive and hides the
relationship between source changes, refresh cost, and the resulting
summary.

### Proposed solution

Add experimental Status Cards that compile operator intent into a query,
summarize matched work, record each update, expose
manual/interval/reactive refresh policies and costs, and preserve the
last good result across stale, updating, paused, and error states. The
capability is off by default and fully gated behind `enableStatusCards`,
including its route and navigation entry.

### Alternatives considered

- Extend existing one-off summaries: rejected because status cards
require persistent query provenance, refresh policy, update history, and
card-specific cost controls.
- Add a dashboard-only filter widget: rejected because it would not
provide governed background refresh, an update ledger, or an inspectable
compile pipeline.
- Ship the surface by default: rejected in favor of an experimental
toggle while behavior and operator value are evaluated.

### Roadmap alignment

This advances Paperclip’s board-level execution visibility and
output-first product goals. `ROADMAP.md` was checked and no duplicate
status-card initiative was found.

### Additional context

No related open PR was found in the public GitHub search for status
cards. The PR-only design wireframes were removed from the repository
after review; the published prototype remains external to the production
source tree.
## What Changed

- Added company-scoped status-card schema, CRUD APIs, compile
provenance, update ledger, shared contracts, validators, and OpenAPI
coverage.
- Added the text-to-query compile pipeline, bundled `status-card-query`
agent skill, query versioning, and authorized write-back flow.
- Added the experimental board, create flow, lifecycle tiles,
detail/settings/debug drawers, archived view, routing, navigation, and
instance setting.
- Added a change-gated update engine with manual, interval, and reactive
refresh policies, trigger selection, active hours, and daily token caps.
- Added per-update token/cost recording, today and lifetime rollups, and
policy-derived cost previews.
- Added operator documentation and agent-authoring hardening for compile
and update behavior.
- Added PR-prep integration coverage for settings/startup wiring and
replaced raw UI values with design-system tokens.
- Removed the PR-only `design/pap-15023-status-cards` wireframe
artifacts so the repository contains only production feature assets.

## Verification

- `pnpm -r typecheck` — passes on the PR head; includes `ui` `tsc -b`
passing. The UI compile gate was also independently recorded as passing
at `6d7f3cf96b` on July 23, 2026.
- `pnpm build` — passes.
- `pnpm check:token-gates` — passes with all three gates clean.
- `pnpm test:run` — 2,880 tests passed and 1 skipped; the sole failure
was an unrelated 10-second `afterAll` database-cleanup timeout in
`execution-workspaces-service.test.ts`.
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/execution-workspaces-service.test.ts` — passes on
immediate focused rerun (25/25).
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/instance-settings-service.test.ts
src/__tests__/server-startup-feedback-export.test.ts` — passes (31/31).
- `pnpm --filter @paperclipai/ui exec vitest run
src/pages/StatusCards/StatusCardSettingsForm.test.tsx
src/pages/StatusCards/StatusCardTile.test.tsx
src/pages/StatusCards/format.test.ts src/lib/status-card-state.test.ts`
— passes (26/26).
- Recorded pre-PR QA: compile-pipeline e2e PASS; full lifecycle and cost
QA PASS; security re-review PASS after write-back hardening; UX
approved.
- `pnpm exec vitest run packages/db/src/status-card-migrations.test.ts`
— passes; reapplies migrations `0185`–`0189` against an already-migrated
embedded Postgres database.
- `pnpm --filter /db check:migrations` — passes migration numbering and
safety checks.
- `pnpm --filter /db typecheck` — passes.
- Merged current `origin/master` on July 24, 2026 with no conflicts;
migrations `0185`–`0189` remain unclaimed on master.

## Risks

- The feature introduces five database migrations and a new background
update path; all new DDL is repeat-safe after partial application,
migration numbering/safety checks pass, and update execution is
company-scoped and change-gated.
- Natural-language compilation can produce invalid or overly broad
queries; compile provenance, query validation, debug visibility, and
version history make failures inspectable and recoverable.
- Reactive or interval refresh could increase spend; active hours, max
refresh frequency, daily token caps, per-update cost records, and
budget-paused states bound and expose that risk.
- The branch name contains an internal execution identifier because it
is a fixed handoff branch; it was intentionally not renamed or rebased
per the release handoff instructions.
- Overall rollout risk is limited because the route, navigation,
services, and UI are disabled by default behind `enableStatusCards`.

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

## Model Used

- OpenAI Codex using GPT-5.5 with reasoning, repository tool use, shell
execution, GitHub CLI, and test/build execution. The runtime did not
expose a context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR 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; the fixed execution-workspace
identifier is documented as an authorized handoff exception
- [x] I have run tests locally and they pass, with the one cleanup
timeout passing on focused rerun
- [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 Fable 5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-24 12:26:43 -05:00
Nicky Leach 2002c4fff3 refactor: remove redundant archived project filters (#10177) canary/v2026.724.0-canary.6 2026-07-24 08:34:30 -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
DottaandPaperclip ee3ed0117e fix(opencode): register configured model in runtime config (#10178)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents for work
> - Agent runs depend on adapters translating Paperclip configuration
into each agent runtime's native configuration
> - The OpenCode local adapter passes configured models through the
`--model provider/model` argument
> - OpenCode only resolves that argument when the model id exists in the
provider's runtime `models` map
> - Valid provider-served model ids missing from OpenCode's bundled
catalog therefore fail locally with `Model not found`
> - This pull request registers the configured model in the injected
runtime configuration without overwriting explicit provider definitions
> - The benefit is that uncataloged routing variants and newly released
models resolve while cataloged models retain their metadata

## Linked Issues or Issue Description

### Pre-submission checklist

- [x] I have searched existing open and closed issues and this is not a
duplicate.
- [x] I can reproduce this on current `master`.
- [x] I have confirmed the error originates in Paperclip's OpenCode
adapter rather than the provider or local configuration.

### What happened?

OpenCode local runs failed with `Model not found` when a configured
`provider/model` id was valid at the provider but absent from OpenCode's
bundled model catalog. OpenRouter routing variants such as model ids
ending in `:nitro` are one example.

### Expected behavior

Any configured provider-served model id should resolve when Paperclip
starts OpenCode, including ids not yet present in the bundled catalog.

### Steps to reproduce

1. Configure the OpenCode local adapter with a valid provider/model id
that is absent from OpenCode's bundled catalog.
2. Start an agent run.
3. Observe that OpenCode rejects the `--model` value with `Model not
found` before the session starts.

### Paperclip version or commit

Current `master` before this change.

### Deployment mode

Local dev using the OpenCode local adapter and an existing provider API
key.

### Installation method

Built from source.

### Agent adapter(s) involved

OpenCode local.

### Database mode

Not database-related.

### Relevant logs or output

`Model not found`

### Additional context

Reproduced with OpenCode 1.15.5. No duplicate or related public GitHub
issues or pull requests were found.

### Privacy checklist

- [x] I have reviewed all pasted output for sensitive information and no
secrets or PII are included.

## What Changed

- Register the configured `provider/model` id as an empty custom model
entry in the injected `opencode.json` provider configuration.
- Preserve explicit model definitions from user configuration and
`PAPERCLIP_OPENCODE_PROVIDERS`.
- Skip registration for model strings that do not use the
`provider/model` form.
- Add focused coverage for uncataloged models, explicit definitions, and
invalid model strings.

## Verification

- `cd packages/adapters/opencode-local && pnpm exec vitest run
src/server/runtime-config.test.ts` — 14 tests passed.
- `cd packages/adapters/opencode-local && pnpm exec tsc --noEmit` —
passed.
- Manual reproduction with OpenCode 1.15.5: the uncataloged OpenRouter
routing variant fails without the injected model entry and resolves with
it.

## Risks

- Low risk: the empty entry deep-merges with catalog metadata for known
models, and existing explicit model definitions take precedence.
- The behavior is limited to syntactically valid `provider/model`
configuration values in the OpenCode local adapter.

> 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 runtime model `gpt-5.6-sol` (context-window size
not exposed by the runtime), with reasoning, tool use, terminal
execution, and code-editing capabilities.

## 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>
canary/v2026.724.0-canary.5
2026-07-24 10:22:07 -05:00