Commit Graph
100 Commits
Author SHA1 Message Date
DottaandPaperclip a388ea1cac Render workspace-ready comments as compact system notices (#10636)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server posts a workspace-ready comment after it prepares an
execution workspace or runtime service.
> - The full Markdown card uses too much space in the task thread.
> - The existing system-notice presentation can show the same comment as
a compact row.
> - The server must keep the original body for API clients and expanded
details.
> - This pull request adds structured presentation data at both
workspace-ready call sites.
> - The benefit is a quieter thread with no data loss and no migration.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The server posts the workspace-ready task comment after workspace
provisioning and adapter-managed runtime startup.

**Current behavior**

The task thread shows a full Markdown comment with strategy, branch,
working directory, services, and warnings. Long branch names can make
this card dominate the thread.

**Proposed behavior**

Show the comment as a compact system-notice row. Expand the row in place
to show the original Markdown body and structured workspace, service,
and warning details. Use a warning tone and open the details by default
when warnings exist.

**Reason and benefit**

The same workspace data is available in the task properties. The compact
row keeps the thread easy to scan while it preserves the full comment
for API consumers and expanded inspection.

**Breaking changes**

None. The comment body stays unchanged. Existing comments without
presentation data keep their current rendering.

## What Changed

- Added workspace-ready presentation and metadata builders.
- Added structured workspace, service, reuse, and warning details.
- Wired both workspace-ready comment paths to send presentation and
metadata options.
- Added focused unit and heartbeat-level tests.

Collapsed notice:

![Collapsed Workspace Ready compact
notice](https://pages.paperclip.ing/pap-16051-workspace-ready-notice-20260801/collapsed.png)

Expanded notice:

![Expanded Workspace Ready compact
notice](https://pages.paperclip.ing/pap-16051-workspace-ready-notice-20260801/expanded.png)

## Verification

- `pnpm exec vitest run
server/src/services/workspace-runtime-ready-comment.test.ts
server/src/__tests__/heartbeat-workspace-ready-comment.test.ts` — 8
tests passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `pnpm -r typecheck` — passed.
- `pnpm check:token-gates` — passed.
- `pnpm build` — passed.
- `pnpm test:run` — 300 server files and 405 UI files passed. One
unrelated CLI AWS doctor test detected static credentials from the
runner environment. The same test passed with `AWS_ACCESS_KEY_ID` and
`AWS_SECRET_ACCESS_KEY` removed.
- Built the existing system-notice Storybook story and captured both
compact and expanded states.
- GitHub CI — all latest-head gates passed. One signoff-policy e2e shard
hit a transient checkout-state race and passed on its single rerun.

## Risks

Low risk. This change only adds optional comment presentation data in
two server paths. The body, database schema, API contract, and old
comments remain unchanged. Incorrect metadata would affect only expanded
structured details; focused tests cover the shape and both warning
states.

> 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 GPT-5 (`gpt-5`, the exact snapshot and context-window
size are not exposed by this runtime). The agent used reasoning,
repository tools, code execution, and visual inspection.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-01 16:04:43 -05:00
DottaandPaperclip ee851fc364 feat(heartbeat): expose cache-adjusted run cost (#10349)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The heartbeat service is the control plane that runs agents through
adapters and records each run's usage and cost in the finance/cost
ledger
> - Adapters report a provider cost (`costUsd`), but there is no way to
represent the provider-billed cost *after* prompt-cache discounts, so
cache-heavy runs are priced wrong and some paid runs end up exported
with a zero/null cost
> - A benchmark comparing Paperclip-orchestrated runs against direct
harness invocation of the same tasks measured 1.5–3.1× higher apparent
USD per pair, largely because cache-discounted billing was not
represented in the exported cost data
> - This pull request adds an optional `cacheAdjustedCostUsd` field to
`AdapterExecutionResult` and a `resolveCacheAdjustedCostUsd` helper in
the heartbeat service that prefers the explicit cache-adjusted figure
and falls back to the reported `costUsd`, persisting it into the run's
usage/ledger JSON
> - The benefit is that paid runs are no longer exported as zero/null
cost and cache-heavy runs can be priced correctly, so operators
comparing orchestrated vs. direct costs see real numbers

## Linked Issues or Issue Description

No single existing public issue covers this exactly; closely related
cost-reporting issues:

- Refs #8947 — hermes adapter never reports usage/cost to Paperclip, so
budget limits never trigger
- Refs #6716 — hermes_local cost/usage capture returns zero
- Refs #3320 — expose per-run token counts in activity log and dashboard

**Problem (feature-request form):** Adapters can only report a single
`costUsd`. Providers with prompt caching bill less than the nominal
token cost, and the heartbeat cost accounting has no field for the
cache-adjusted billed amount. As a result, cache-heavy paid runs are
either priced at the undiscounted figure or, when the adapter withholds
the ambiguous number, exported as zero/null. **Proposed solution:** an
explicit optional `cacheAdjustedCostUsd` on the adapter execution
result, resolved server-side with a safe fallback to `costUsd`.
**Alternatives considered:** recomputing cache discounts server-side
from token counts (rejected: provider pricing tables drift and cache
billing rules are provider-specific; the adapter is the source of
truth).

## What Changed

- `packages/adapter-utils/src/types.ts`: added optional
`cacheAdjustedCostUsd?: number | null` to `AdapterExecutionResult`, with
a doc comment on adapter expectations
- `server/src/services/heartbeat.ts`: added exported
`resolveCacheAdjustedCostUsd()` (explicit cache-adjusted value wins when
a finite non-negative number; otherwise falls back to a finite
non-negative `costUsd`; otherwise `null`), and consistently uses the
resolved billed value for ledger cents, cost status, and run usage JSON
- `server/src/__tests__/heartbeat-cost-accounting.test.ts`: added unit
coverage for explicit precedence, fallback, invalid values,
adjusted-only pricing, and discounted ledger billing

## Verification

- `pnpm exec vitest run
server/src/__tests__/heartbeat-cost-accounting.test.ts` — 1 file, 7
tests passed
- `pnpm --filter @paperclipai/adapter-utils typecheck` — passed
- `pnpm --filter @paperclipai/server typecheck` — passed
- GitHub Actions on head `dc9c3830bf694b9afb3b27c5c8c36bff38e7fdcb` —
all 26 checks clean/skipped; one unrelated E2E checkout-contention flake
passed on its single failed-job rerun
- Greptile review on the same head — 5/5 with zero unresolved threads

## Risks

- Low risk: the field is optional and additive; when absent, behavior
falls back to the existing `costUsd` path
- Ledger/usage JSON gains a new optional `cacheAdjustedCostUsd` key —
consumers that strictly validate keys would need to tolerate it (usage
JSON is already open-shaped)
- No migrations, no API-breaking 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

- Implementation: Anthropic Claude Fable 5, model ID `claude-fable-5`,
standard context window, agentic coding mode with shell/file tool use
- PR preparation and verification: OpenAI Codex on GPT-5 (the runtime
did not expose a more specific serving snapshot or context-window
value), reasoning mode with shell and GitHub 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 (doc
comment on the new field; 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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-01 07:15:52 -07:00
DottaandPaperclip 92c3d9f0d9 fix(server): stop requiring PAPERCLIP_DECISION_SIGNING_SECRET at startup (#10594)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The server signs decision specifications with an HMAC
> - PR #10010 made `PAPERCLIP_DECISION_SIGNING_SECRET` a hard startup
requirement
> - Existing installs do not have this new environment variable
> - Those installs now stop during startup
> - This pull request uses a secure persisted instance key when the
override is absent
> - The benefit is that existing installs start without new
configuration and decision signing remains fail-closed

## Linked Issues or Issue Description

**What happened?**

After #10010, `startServer()` throws when
`PAPERCLIP_DECISION_SIGNING_SECRET` is unset or shorter than 32
characters. Existing installs without the new environment variable stop
at startup.

**Expected behavior**

The server starts without manual configuration. A new optional feature
must not add a required environment variable for existing installs.

**Steps to reproduce**

1. Check out `master` at 9c1f8e7887.
2. Unset `PAPERCLIP_DECISION_SIGNING_SECRET`.
3. Start the server.
4. Observe that startup stops with a missing-secret error.

**Paperclip version or commit**

`master` at 9c1f8e7887.

**Deployment mode**

All deployment modes are affected when the environment variable is
absent.

## What Changed

- Treat `PAPERCLIP_DECISION_SIGNING_SECRET` as an optional override.
- Generate a random per-instance key at
`<instance>/secrets/decision-signing.key` when the override is absent.
- Publish a complete first-time key with an atomic no-overwrite link so
concurrent server starts use one key.
- Repair permissive modes on process-owned secrets directories and
regular key files, reject planted symlinks or foreign-owned paths, and
fail startup if `0700`/`0600` cannot be enforced.
- Keep an explicitly configured secret shorter than 32 characters as a
startup error.
- Add startup, permission, planted-symlink, fail-closed verification,
and generated-key round-trip tests.

## Verification

- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/decisions-service.test.ts
src/__tests__/server-startup-feedback-export.test.ts` — 45 tests passed.
- `pnpm --filter @paperclipai/server exec tsc --noEmit` — passed.
- Eight simultaneous resolver processes returned the same persisted key.
The secrets directory/key modes were `0700`/`0600`.
- `git diff --check` — passed.

## Risks

- Existing configured secrets remain unchanged.
- Removing a configured secret after a proposal makes the prior
signature fail verification. Restoring the secret restores verification.
- A restored secrets directory or key with unsafe permissions now fails
startup when the server cannot repair it to `0700`/`0600`; symlinks and
paths owned by another local user are rejected rather than trusted.
- The generated key uses an atomic hard link in the instance secrets
directory. An unsupported file system fails startup instead of replacing
an existing key.
- Existing installs that failed at startup did not sign decisions with a
missing key.

> 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

- Anthropic Claude Fable 5, model ID `claude-fable-5`, produced the
initial implementation with extended reasoning and tool use.
- OpenAI Codex, model ID `gpt-5`, addressed review findings and prepared
the PR with reasoning, repository editing, code execution, and GitHub
tooling. The runtime did not expose the context-window size.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 22:48:32 -07:00
DottaandPaperclip b163c6c473 fix(server): preserve hot restart intent across path upgrade (#10593)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server can preserve eligible agent runs during a controlled hot
restart.
> - A path change moved restart state from the Paperclip home root to
the instance root.
> - A staged update can therefore make the old server and the new server
read different intent files.
> - The old server then drains live runs, while the new server can start
without a shutdown snapshot.
> - This pull request adds a correlated compatibility handoff and
records the live preflight set.
> - It also verifies the target process instance on Linux, macOS, and
Windows.
> - The benefit is complete and safe run classification across the path
upgrade.

## Linked Issues or Issue Description

No public GitHub issue covers this defect.

**What happened?**

A staged hot restart can run an older server that reads
`hot-restart-intent.json` from the Paperclip home root and a new server
that writes the file under the instance root. The old server misses the
request and uses graceful drain. The new server later finds its marker
without a shutdown snapshot. Before this change, that state could
produce an empty loss list even when live runs existed before restart.

**Expected behavior**

The old server must receive the PID-targeted restart request at its
legacy path. The new server must correlate the legacy shutdown snapshot
with its instance-scoped request. Every run that was live during
preflight must appear as adopted, finalized while down, or lost. A
reused PID must not let a stale marker claim a different process
instance.

**Steps to reproduce**

1. Start a server version from before the instance-root marker change.
2. Keep one or more local-agent heartbeat runs active.
3. Stage a current build and request a hot restart from that build.
4. Observe that the old server reads only the home-root path while the
staged build writes only the instance-root path.
5. Observe graceful drain and a new-server intent that has no shutdown
snapshot.

**Paperclip version or commit**

The path transition entered `master` in #10045. The hot-restart adoption
flow came from #9647. This fix targets current `master` and
compatibility with the immediately preceding home-root behavior.

**Deployment mode**

Self-hosted server built from source with controlled service hot
restarts.

Related work: #9628 is the original broader hot-restart feature PR.
#10556 addresses embedded PostgreSQL lifecycle behavior and does not
address marker-path compatibility.

## What Changed

- Write an authoritative instance-scoped intent and a correlated legacy
home-root handoff marker.
- Merge a legacy shutdown snapshot only when immutable request identity
fields match.
- Prevent a non-default instance from consuming an uncorrelated
legacy-only marker.
- Record preflight running heartbeat IDs and reconcile snapshot
omissions from current database state.
- Serialize marker claims, snapshot writes, stale recovery, and matching
cleanup with recoverable per-path filesystem leases.
- Read process start identity on Linux, macOS, and Windows to
distinguish a reused PID from the original server.
- Require identity for new restart requests and fail closed when a
supported platform cannot provide it.
- Classify older markers by comparing the replacement server boot time
or operating-system process start time with the request time.
- Close the preflight database client explicitly and use a root-safe SQL
query.
- Add focused unit, platform-branch, database-backed, and CI regression
coverage.
- Document the compatibility handoff, process identity probes, and
instance-scoped report path.

## Verification

- `pnpm exec vitest run server/src/services/hot-restart.test.ts
server/src/__tests__/heartbeat-process-recovery.test.ts -t
"hot-restart|old-server legacy|preflight live|preflight run|spawn
identity before hot restart"` — 24 tests passed and 90 tests were
skipped across 2 files.
- `pnpm exec vitest run server/src/services/hot-restart.test.ts` — 17
tests passed.
- `pnpm exec vitest run
server/src/__tests__/issue-watchdogs-routes.test.ts -t "restarts a
stalled claimed run"` — 1 test passed and 10 tests were skipped.
- `pnpm exec vitest run
server/src/__tests__/agent-action-audit-routes.test.ts -t "allows an
agent with issue:delegate"` — 1 test passed and 7 tests were skipped.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `git diff --check` — passed.
- GitHub Actions — 26 of 26 checks passed at
`55a79cb029be8b1dc89926d9d89ccd2181266d5c`.
- Greptile — 5/5 at the same head with no unresolved current-head review
threads.

## Risks

- The legacy handoff path is shared across instances. Exclusive claims
and per-path leases prevent overwrite and match-before-delete races.
- Process identity uses platform commands as a fallback when the health
endpoint has no identity. Linux reads `/proc`, macOS and BSD use `ps`,
and Windows uses PowerShell.
- A supported-platform identity probe failure aborts the restart. This
fails closed instead of replacing an unknown live process.
- Older intent files do not contain process identity. The server
compares the replacement boot or process start time with the request
time when those values are available.
- A preflight database read can fail before the marker is written. The
command fails closed instead of claiming a restart whose live-run set is
unknown.

> 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 GPT-5. The exact deployment model ID and
context-window size were not exposed by this runtime. Reasoning,
repository editing, shell execution, test execution, GitHub CLI, and
Paperclip API capabilities were enabled.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 21:55:59 -07:00
9c1f8e7887 feat(decisions): add first-class propose mode (#10010)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents can currently perform many mutations directly, while humans
often need a durable review point before cross-issue or destructive
actions occur
> - Existing approvals and issue-thread interactions do not provide a
standalone, reusable object for presenting options, collecting typed
inputs, detecting stale targets, and auditing effect execution
> - The control plane therefore needs a first-class propose mode that
separates an agent's recommendation from the governed mutation it may
cause
> - This pull request adds Decisions v1 across the database, shared
contracts, server execution and telemetry, agent skill guidance, and
operator UI
> - The benefit is that agents can propose multi-option actions safely
while operators get explicit provenance, fail-closed execution,
per-effect results, and a focused attention workflow

## Linked Issues or Issue Description

### Subsystem affected

Cross-cutting: `packages/db`, `packages/shared`, `server`, and `ui`.

### Problem or motivation

Agents need a governed way to propose consequential work without
immediately mutating issues, especially when one choice can affect
several issue trees. Existing approvals and issue-thread interactions do
not provide a standalone object with typed options, target snapshots,
effect-level authorization, expiration, execution outcomes, and reusable
attention-feed presentation.

### Proposed solution

Add first-class Decisions that store options and typed inputs, surface
open proposals in the operator attention feed, validate target freshness
and the origin-agent/operator authorization intersection at decision
time, execute a bounded set of auditable effects, and retain terminal
outcomes. Decisions v1 supports comments, status and assignee changes,
follow-up issue creation, blocker resolution, and issue-tree
cancellation, plus bundle grouping, expiration/dismissal, rule-key
telemetry, and agent-facing API guidance.

### Alternatives considered

- Extend approvals with arbitrary effects: rejected because approvals
represent governed yes/no actions and would become an unsafe generic
mutation envelope.
- Model every proposal as an issue-thread interaction: rejected because
decisions can span several targets and need independent lifecycle,
telemetry, idempotency, and effect results.
- Let agents perform the mutation and ask for retrospective review:
rejected because it removes the pre-execution governance boundary this
feature is meant to provide.

### Roadmap alignment

Aligns with `ROADMAP.md` sections **Agent Reviews and Approvals**,
**Enforced Outcomes**, **MCP Tool Gateway & Apps (governed tool
access)**, and **Activity History** by making explicit decisions,
authorization gates, auditable execution, and terminal outcomes
first-class control-plane objects.

### Additional context

This does not replace existing approvals or issue-thread interactions,
and it does not add an unrestricted generic mutation effect.

## What Changed

- Added company-scoped decision, option, target, and effect-execution
schema plus migration and shared TypeScript/Zod contracts.
- Added decision routes and services for propose, list/get, decide,
dismiss, cancel, target freshness checks, authorization intersection,
idempotency, activity logging, and execution auditing.
- Added rule-key decision telemetry and attention-feed metadata so open
decisions are visible and measurable.
- Added agent skill documentation for proposing and resolving decisions
through the Paperclip API.
- Added the Decisions UI: API client, query keys, inline attention
resolver, bundle grouping, target-issue strip, terminal history,
destructive confirmation, and per-effect result rendering.
- Added server service coverage, DecisionCard state tests, and Storybook
stories for the supported visual states.

## Verification

- `pnpm -r typecheck` — passed.
- `pnpm test:run` — 2,876 passed, 1 skipped, with one unrelated
cross-suite cleanup-order failure in
`heartbeat-responsible-user-invariant.test.ts`; the failing file passes
in isolation (`6/6`).
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/heartbeat-responsible-user-invariant.test.ts` — passed.
- `pnpm --filter @paperclipai/ui exec vitest run
src/components/DecisionCard.test.tsx` — passed (`9/9`).
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/authz-existence-oracle-guard.test.ts
src/__tests__/openapi-routes.test.ts` — passed (`5/5`).
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/decisions-service.test.ts` — passed (`16/16`).
- `pnpm --filter paperclipai exec vitest run
src/__tests__/company-import-export-e2e.test.ts` — passed (`1/1`).
- `pnpm --filter @paperclipai/server typecheck` and `pnpm --filter
paperclipai typecheck` — passed.
- `pnpm build` — passed.
- Rebased-head focused suite — passed (`6` files, `88` tests): shared
decision contracts, Decisions service, OpenAPI routes, startup feedback
export, DecisionCard states, and attention helpers. The follow-up
stale-secondary-target regression passes in the DecisionCard suite
(`10/10`).
- Rebased-head scoped typechecks — passed for `@paperclipai/shared`,
`@paperclipai/db`, `@paperclipai/server`, and `@paperclipai/ui`.
- Rebased-head migration numbering and safety checks — passed after
renumbering the additive migration to `0193` and making it replay-safe
for environments that applied the earlier feature-branch number.
- `pnpm check:token-gates` — passed with all gates clean.
- GitHub PR workflow and Greptile review for
`1f9f7645882d05dfdd9c99377c03a1f53f20e8be` — running after the
stale-secondary-target fix and PR metadata refresh on July 27, 2026.
- `pnpm --filter @paperclipai/ui build-storybook` exposes an existing
Storybook version mismatch (`storybook` 10.4.6 vs
`@storybook/addon-docs` 10.5.0); Decisions stories were validated with
the docs addon temporarily disabled and the tracked config remains
unchanged.

## Risks

- **Migration:** Adds replay-safe migration `0193`; migration numbering
and safety checks pass. The new tables and indexes are additive.
- **Authorization:** Effect execution intersects the proposing agent's
permissions with the responsible user context and fails closed; mistakes
could reject a valid proposal rather than silently over-authorize it.
- **Concurrency:** Target snapshots and idempotency keys protect against
stale or duplicate execution, but reviewers should focus on mixed-effect
partial outcomes and retry behavior.
- **UI:** Decisions are integrated into the existing attention feed
rather than a separate navigation surface, reducing routing risk but
increasing the importance of attention-item metadata compatibility.

> 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 using `gpt-5.6-sol` for final PR preparation, review
fixes, and verification; repository tools and code execution were
enabled, and context-window size is not exposed in this runtime.
- Anthropic Claude Opus 4.8 with 1M context assisted with the Decisions
UI implementation, as recorded in the relevant commits.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-31 19:17:02 -07:00
71231dfa38 feat(audit): agent audit UI — company page + per-agent tab (#9744)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Operators need an audit record of agent actions across tasks,
comments, documents, approvals, and runs
> - The permission-gated audit read API provides that record, but
operators cannot inspect it in the product
> - A readable UI must preserve company boundaries, server-side
permission decisions, and redaction
> - Audit exports must also be safe to open in spreadsheet software and
must record the export itself
> - This pull request adds company and per-agent audit views plus a
guarded CSV export
> - The benefit is a searchable, filterable, and reviewable agent action
history with direct links back to work

## Linked Issues or Issue Description

**Feature.** This change adds the frontend and CSV export for the agent
action audit log.

Refs #9731 and #9735.

- Problem: agent actions are recorded, but operators have no readable
product surface to inspect or export them.
- Solution: add a company audit page and a per-agent Audit tab that use
the permission-gated audit API.
- Alternative: build a separate plugin-only surface. This was rejected
because the existing permission model already supports a unified,
server-authoritative view.

This pull request targets the audit epic branch, which contains the
merged #9735 audit API.

## What Changed

- Added a company Audit page and sidebar entry.
- Added a per-agent Audit tab with a fixed agent filter.
- Added filters for agent, responsible user, action domain, entity type,
and date range.
- Added task and run links, responsible-user context, cursor pagination,
and readable action text.
- Added a permission-denied Enterprise card for callers without
`audit:view_agent_actions`.
- Added a CSV export that is permission-gated, capped, self-audited,
CSV-escaped, and protected against spreadsheet formula injection.
- Preserved the merged audit API cursor validation, redaction, and
sub-millisecond pagination behavior.

## Verification

- `pnpm exec vitest run ui/src/pages/audit/AuditFeed.test.tsx` — 6
passed.
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/agent-action-audit-routes.test.ts` — 8 passed with
embedded PostgreSQL.
- `pnpm -r typecheck` — passed across all workspaces.
- `pnpm build` — passed across all workspaces.
- `pnpm test:run` — all completed shards passed except one
environment-sensitive CLI assertion caused by injected static AWS
credential variables; the exact test passes 8/8 with those variables
unset.
- Manual Chromium QA exercised the populated feed, active filters,
permission-denied card, per-agent tab, and CSV export.

## Screenshots and Manual QA

- [All audit states exercised in
Chromium](https://github.com/paperclipai/paperclip/pull/9744#issuecomment-4998997001)
- [Detailed browser report and per-agent tab root
cause](https://github.com/paperclipai/paperclip/pull/9744#issuecomment-4998771061)

The per-agent redirect defect found during QA is fixed in this branch.

## Risks

Low to moderate risk. The UI and export route are additive and use the
existing company-scoped permission gate. The main risks are large
exports and spreadsheet interpretation. The export is capped at 10,000
rows, records truncation accurately, and prefixes formula-like cells as
text. There are no schema changes or migrations.

> 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

- Anthropic Claude Opus 4.8, 1M context, extended thinking, tool use,
and code execution produced the original implementation.
- OpenAI Codex, GPT-5 (deployment ID and context window not exposed),
reasoning, tool use, code execution, browser-test orchestration, and
GitHub review tooling repaired and verified the pull request.

## 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>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-31 19:09:13 -07:00
DottaandPaperclip 86b265bb85 test(ui): isolate Cases routing regression (#10591)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The UI test suite protects the board route table
> - The Cases routing regression test needs only the route table and
sentinel pages
> - The test initialized the full cloud access query flow for each route
> - That unrelated setup made the two assertions spend several seconds
polling
> - This pull request isolates the routing dependency and removes the
long timeout
> - The benefit is faster and more focused route regression coverage

## Linked Issues or Issue Description

**What happened?**

The Cases routing regression test initialized cloud health, session, and
board access queries. Its two route assertions spent about 6.69 seconds
in test execution.

**Expected behavior**

The route regression test must bypass unrelated cloud access checks and
resolve the two route assertions synchronously.

**Steps to reproduce**

1. Run `pnpm --dir ui exec vitest run src/App.cases-routing.test.tsx` on
the base commit.
2. Inspect the Vitest test duration.
3. Observe that the test waits through unrelated query transitions.

**Paperclip version or commit**

`7301fae942c3d5826974335cb40d6f1e0d95d1e0`

**Deployment mode**

Built from source. The defect affects the UI unit test suite.

Related pull request: #9198 introduced the Cases route regression
coverage.

## What Changed

- Mock `CloudAccessGate` at the routing boundary.
- Import the app after hoisted CSS setup and module mocks.
- Remove the query client and three unrelated API mocks.
- Replace long polling with a bounded three-turn route wait.
- Remove the custom 20-second test timeouts.

## Verification

- `pnpm --dir ui exec vitest run src/App.cases-routing.test.tsx`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm check:token-gates`

The focused run passed both tests. Test execution changed from about
6.69 seconds on the base commit to 40 milliseconds on this branch.

## Risks

Low risk. The production route table is unchanged. The test still
renders the real `App` route table and the same sentinel pages.

> 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 ID `gpt-5`. The context-window size is not
exposed to this run. The run used reasoning, repository tools, code
execution, and GitHub tools.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 18:54:53 -07:00
DottaandPaperclip a29b10510c fix(server): bound inherited workspace runtime services (#10589)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Execution workspaces can inherit runtime services from a project
workspace
> - A project workspace keeps current and historical runtime service
rows
> - The execution workspace read path returned all current rows,
including services removed from the current configuration
> - This pull request matches inherited rows to the current service
definitions
> - The benefit is bounded workspace payloads and accurate service
summaries

## Linked Issues or Issue Description

**What happened?**

Shared execution workspaces returned current historical service rows
that no longer matched the project workspace configuration. The response
size multiplied across every shared execution workspace.

**Expected behavior**

Shared execution workspaces must return only the newest runtime service
row for each service in the current project workspace configuration.

**Steps to reproduce**

1. Create one project workspace with many historical runtime service
rows.
2. Create many shared execution workspaces that inherit that project
workspace.
3. List the execution workspaces and inspect each `runtimeServices`
array.

**Paperclip version or commit**

`7301fae942c3d5826974335cb40d6f1e0d95d1e0`

**Deployment mode**

Built from source. The defect is in the server read model and is not
deployment-specific.

No duplicate or related public issue or pull request was found.

## What Changed

- Select only runtime service rows that match the current project
workspace service definitions.
- Preserve each matched service definition index in the API result.
- Avoid loading direct execution service rows for workspaces that
inherit project services.
- Add unit, integration, and volume regression coverage.

## Verification

- `pnpm --dir server exec vitest run
src/services/workspace-runtime-read-model.test.ts
src/__tests__/execution-workspaces-service.test.ts -t
'selectConfiguredRuntimeServiceRows|returns full details at the observed
volume|inherits only runtime-service rows'`
- `pnpm --filter @paperclipai/server typecheck`

The focused test run passed 4 tests and skipped 27 unrelated tests.

## Risks

The read path now omits service rows that do not match the current
configuration. This is the intended behavior for inherited runtime
services. The change does not alter service persistence or lifecycle
transitions.

> 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 ID `gpt-5`. The context-window size is not
exposed to this run. The run used reasoning, repository tools, code
execution, and GitHub tools.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 18:54:11 -07:00
DottaandPaperclip 2e4774ac90 fix(adapter-utils): correct confirmation wake semantics (#10588)
<!-- Write all pull request text in Simplified Technical English
(ASD-STE100): short sentences, one instruction per sentence, simple
approved vocabulary, and the active voice. -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Local agent wakes include a default execution contract
> - That contract tells agents how issue-thread continuation policies
behave
> - The current text says `wake_assignee` resumes a confirmation only
after acceptance
> - The server actually wakes for every non-expired resolution and
reserves acceptance-only behavior for `wake_assignee_on_accept`
> - This pull request makes the default prompt match the server contract
and strengthens the recovery follow-up regression case
> - The benefit is that agents choose the correct continuation policy
and recovery tests cover normalized agent name keys

## Linked Issues or Issue Description

Related work: Refs #5473, Refs #5060, and Refs #10562.

**What happened?**

The default local-agent prompt described `wake_assignee` as
acceptance-only for `request_confirmation`. This conflicts with the
server. The server wakes on every non-expired resolution. A recovery
follow-up test also used an already-normalized execution agent name key,
so it did not exercise the normalization seam.

**Expected behavior**

The prompt must state that `wake_assignee` resumes after acceptance or
rejection. It must direct acceptance-only flows to
`wake_assignee_on_accept`. The recovery regression must use a
display-style agent name key and prove that the follow-up path still
works after normalization.

**Steps to reproduce**

1. Read the default local-agent prompt in
`packages/adapter-utils/src/server-utils.ts`.
2. Compare its confirmation continuation text with
`queueResolvedInteractionContinuationWakeup` in
`server/src/routes/issues.ts`.
3. Observe that the prompt gives acceptance-only semantics to
`wake_assignee`.
4. Inspect the recovery hand-back test and observe that its execution
name key is already normalized.

**Paperclip version or commit**

`7301fae942`

**Deployment mode**

Local dev. The prompt and test behavior are not deployment-specific.

## What Changed

- Corrected the default agent prompt for `wake_assignee` and
`wake_assignee_on_accept`.
- Added focused prompt assertions for both the required and obsolete
text.
- Changed the recovery follow-up fixture to use a display-style agent
name key.

## Verification

- `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts
-t 'keeps the default local-agent prompt action-oriented'` passed: 1
test.
- `pnpm exec vitest run
server/src/__tests__/heartbeat-comment-wake-batching.test.ts -t 'defers
recovery hand-back wakes until the resolving run exits'` passed: 1 test.
- `pnpm --filter @paperclipai/adapter-utils typecheck` passed.
- `pnpm --filter @paperclipai/server typecheck` passed.
- `git diff --check origin/master...HEAD` passed.

## Risks

- Low risk. The production change updates prompt text only.
- Agents that followed the old text may now choose
`wake_assignee_on_accept` for acceptance-only flows.
- The server test change only broadens an existing regression fixture.

> 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 GPT-5. The exact serving model ID and context-window
size are not exposed to the agent. The model used reasoning, repository
tools, tests, Git, and GitHub CLI access.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 18:53:53 -07:00
DottaandPaperclip c9116686bd test(installer): cover cross-version update migrations (#10587)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies
> - Managed updates can change both the application payload and its
database schema
> - Unit tests cannot prove that an older live install upgrades through
a real migration and remains recoverable
> - The managed-install work in #10045 needs a repeatable cross-version
system test
> - This pull request adds an isolated end-to-end harness for update,
migration, backup, service restart, and rollback behavior
> - The benefit is a direct proof that managed upgrades preserve the
existing database and service lifecycle across versions

## Linked Issues or Issue Description

Refs #10045

This test is a focused follow-up to the managed install integration.
Merge #10045 first so the tested install, update, service, backup, and
rollback commands are available.

## What Changed

- Added a cross-version managed-update E2E script.
- Installed an older Git ref, initialized its embedded PostgreSQL
database, and updated to a ref with one additional migration.
- Verified the pre-update backup, payload switch, service recovery,
migration result, database-cluster reuse, and rollback behavior.
- Isolated Paperclip state under a dedicated test home and cleaned up
the service and managed install on success or failure.
- Added regression tests for shell syntax, required-ref validation,
side-effect-free preflight failure, and complete failure cleanup.

## Verification

- `node --test scripts/__tests__/e2e-update-migrations.test.mjs`
- `bash -n scripts/e2e-update-migrations.sh`
- GitHub latest-head CI: build, typecheck, release registry, canary
dry-run, general tests, serialized suites, and both browser E2E shards
passed.
- Full harness execution needs an isolated macOS or Linux host with a
real launchd or systemd user service. It is intentionally not run on a
live Paperclip server host.

## Risks

- The script manages a real user service and downloads two Git refs. Run
it only on an isolated test host.
- The test needs #10045 because `origin/master` does not yet contain the
managed install lifecycle.
- The script uses a dedicated `PAPERCLIP_HOME`, refuses a pre-existing
shim or test home, and removes its service and install during cleanup.

> 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 based on GPT-5. The runtime did not expose a more
specific deployment ID or context-window size. Reasoning, repository
access, shell execution, and GitHub tooling were enabled.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 18:53:34 -07:00
DottaandPaperclip 70175d5b6f fix(garden-inbox): preserve declined candidates on reruns (#10586)
## Thinking Path

> - Paperclip uses company skills to give agents repeatable operating
workflows.
> - The garden-inbox skill asks a user to confirm reversible archive
candidates.
> - A user can leave a candidate unchecked because they want to keep it
visible.
> - A later confirmation pass currently checks that candidate again by
default.
> - This pull request adds a repeatable `--unselect` option for
candidates declined in an earlier pass.
> - The benefit is that repeated confirmation cards preserve the user's
prior choice and make that history visible.

## Linked Issues or Issue Description

**What happened?**

When an inbox gardening confirmation was created again, candidates
declined in an earlier pass could start checked again.

**Expected behavior**

The caller can identify previously declined candidates. Those candidates
start unchecked and explain why they are unchecked.

**Steps to reproduce**

1. Create a garden-inbox scan with an archive candidate in bucket A or
B.
2. Leave the candidate unchecked in a confirmation pass.
3. Create a later confirmation for the same candidate.
4. Observe that the default selection does not preserve the earlier
decline.

**Paperclip version or commit**

`7301fae942c3d5826974335cb40d6f1e0d95d1e0`

**Deployment mode**

Built from source.

## What Changed

- Added repeatable `--unselect ISSUE_ID` parsing to the garden-inbox
confirmation command.
- Removed those issue IDs from the default checked options.
- Added a description note for candidates declined in an earlier pass.
- Rejected `--unselect` values that are not offered by the current scan.
- Documented the repeat-pass workflow and added regression coverage.

## Verification

- `node --test
.agents/skills/garden-inbox/scripts/garden-inbox.test.mjs`
- `git diff --check origin/master...HEAD`

## Risks

- Low risk. The new option is opt-in, and existing confirmation behavior
is unchanged when it is omitted.
- An invalid issue ID now fails before any confirmation card is posted.

> 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 family. The runtime does not expose the exact
deployment model ID or context-window size. Reasoning, repository tools,
shell execution, and GitHub tools were enabled.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 18:53:16 -07:00
DottaandPaperclip 627728bdde feat: add authoritative issue PATCH receipts (#10478)
<!-- Write all pull request text in Simplified Technical English
(ASD-STE100): short sentences, one instruction per sentence, simple
approved vocabulary, and the active voice. -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents update tasks through the issue API.
> - The update response did not state which values changed.
> - Blocker updates also did not echo the scalar blocker IDs.
> - Agents therefore used an extra GET request to confirm a successful
write.
> - This pull request adds an authoritative change receipt and an
optional small response.
> - The benefit is fewer API calls with a clear and compatible write
contract.

## Linked Issues or Issue Description

No public GitHub issue exists for this change.

### Subsystem affected

Cross-cutting: `server/`, `packages/shared`, and the UI issue cache.

### Problem or motivation

A successful issue PATCH returned the updated issue, but it did not
identify the effective changes. Blocker writes returned relation
summaries without the scalar IDs. Agents could not distinguish a
confirmed clear operation from missing data. The response must confirm
committed field and blocker changes while existing UI clients continue
to receive the full issue by default.

### Proposed solution

Add a `changes` receipt. Add a conditional `blockedByIssueIds` echo.
Support `Prefer: return=minimal`. Keep the full response as the default.

### Alternatives considered

Make the small response the default for agent tokens. This would create
different response contracts by actor type, so this pull request does
not use that design.

### Roadmap alignment

This is a focused control-plane reliability improvement. It does not
duplicate an open roadmap milestone.

## What Changed

- Compute committed issue row and relation changes in the issue service.
- Omit no-op fields and truncate changed long text values to 200
characters.
- Echo blocker ID arrays for blocker set and clear requests.
- Add the opt-in `Prefer: return=minimal` response and
`Preference-Applied` header.
- Keep receipt metadata out of React Query issue caches.
- Add route and embedded Postgres tests for the new contract.

## Verification

- `pnpm exec vitest run
server/src/__tests__/issue-activity-events-routes.test.ts`
- `pnpm exec vitest run server/src/__tests__/issues-service.test.ts -t
"returns authoritative update receipts for row fields and blocker
relations"`
- `pnpm --filter @paperclipai/shared typecheck`
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm check:token-gates`
- `git diff --check`

## Risks

- Low compatibility risk. The default response only adds receipt fields.
- Minimal mode is opt-in. Existing clients do not receive a smaller
body.
- The receipt excludes `updatedAt` because the response already returns
it as the freshness anchor.
- Prose API and agent workflow guidance will follow after the server
contract is available.

> 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 based on GPT-5. The exact deployment ID, context window
size, and reasoning mode are not exposed to the agent. The agent used
repository tools, code execution, and 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)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 18:52:59 -07:00
DottaandPaperclip b1ac92f305 fix(ui): recover blockquotes the markdown editor escaped as backslash-gt (#10466)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The web UI uses one shared markdown editor for comments, issue
descriptions, and documents.
> - Users type `>` at the start of a line to insert a blockquote.
> - The live editor shortcut does not always run in every browser and
input method.
> - The markdown exporter then changes the leading `>` to `\>` and saves
literal text.
> - The saved text does not render as a blockquote.
> - This pull request restores the blockquote marker when markdown
enters or leaves the editor.
> - The benefit is reliable blockquote insertion on every surface that
uses the shared editor.

## Linked Issues or Issue Description

No public GitHub issue exists.

Related prior attempt: #10465.

**What happened?**

The shared markdown editor sometimes saved a blockquote as literal text.
This happened when the live shortcut did not run. The exporter saved `\>
text`, which rendered as literal `> text`.

**Expected behavior**

A line that starts with `>` must render as a blockquote in comments,
issue descriptions, and documents.

**Steps to reproduce**

1. Open a task comment composer, description editor, or document editor.
2. Add `> ` to an existing line, or use an input method that does not
run the live shortcut.
3. Save the content.
4. Observe that the saved line renders as literal text instead of a
blockquote.

**Paperclip version or commit**

`master` at `78f8c6c3d4`.

**Deployment mode**

Self-hosted server.

## What Changed

- Add `unescapeBlockquoteMarkers()` to restore block-level `\>` markers.
- Keep indented code, list content, nested content, and fenced code
unchanged.
- Apply the helper when markdown enters and leaves `MarkdownEditor`.
- Add focused tests for line position, indentation, container prefixes,
and CommonMark fence rules.

## Verification

- `pnpm exec vitest run ui/src/lib/blockquote-markdown.test.ts` passes
with 22 tests.
- `pnpm exec vitest run ui/src/components/MarkdownEditor.test.tsx`
passes with 37 tests.
- `pnpm --filter @paperclipai/ui typecheck` passes.
- `pnpm check:token-gates` passes.
- `git diff --check origin/master...HEAD` passes.
- A browser harness used the real `MarkdownEditor` and `IssueChatThread`
composer. It confirmed that `> text` renders as a blockquote and exports
as `> text`.
- The [Cutter
preview](https://github.com/paperclipai/paperclip/pull/10466#issuecomment-5140558263)
supplies a task-page screenshot and an editor interaction video.

## Risks

- Low risk. The helper returns the input unchanged when it contains no
`\>`.
- A paragraph that deliberately starts with literal `\>` now becomes a
blockquote. The editor has no literal-marker control, so this matches
the available input behavior.
- There are no database, API, or migration 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

- Anthropic Claude Opus 4.8 (`claude-opus-4-8`, 1M context), extended
thinking, with tool use and code execution.
- OpenAI Codex with GPT-5 (`gpt-5`; runtime build and context-window
metadata were not exposed), with reasoning, tool use, code execution,
and GitHub review tools.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 18:52:42 -07:00
fc5a30805e feat(cli): add managed install, update, and service lifecycle (#10045)
## Thinking Path

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

## Linked Issues or Issue Description

### Problem

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

### Proposed Solution

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

### Alternatives Considered

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

### Related Pull Requests

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

## What Changed

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

## Verification

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

## Risks

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

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

## Model Used

- OpenAI Codex coding agents using GPT-5.5 and GPT-5.6-sol, with
reasoning, repository/API access, shell execution, and test tooling. The
runtime did not expose a reliable context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 18:52:23 -07:00
DottaandPaperclip 7301fae942 fix(heartbeat): atomically claim due timer intervals (#10584)
<!-- Write all pull request text in Simplified Technical English
(ASD-STE100): short sentences, one instruction per sentence, simple
approved vocabulary, and the active voice. -->

## Thinking Path

> - Paperclip coordinates AI agents through scheduled heartbeat runs.
> - The heartbeat scheduler can call `tickTimers()` again before an
earlier tick has finished.
> - Each overlapping tick can read the same old `lastHeartbeatAt` value
and decide that the same agent is due.
> - The existing queue checks do not make that due-time decision atomic.
> - This pull request atomically advances the timer baseline before it
enqueues the wake.
> - The benefit is that one timer interval can create at most one
scheduled run for an agent.

## Linked Issues or Issue Description

No public GitHub issue describes this exact scheduler race. Related pull
requests address active-run overlap or queued-run buildup, but they do
not atomically claim a due timer interval: #9457, #8416, and #3858.

**What happened?**

Two overlapping calls to `tickTimers()` could both read the same due
timer baseline. Both calls could enqueue a timer run for the same agent
and interval.

**Expected behavior**

Only one scheduler tick must claim a due timer interval. A second
overlapping tick must observe that the interval was already claimed and
skip it.

**Steps to reproduce**

1. Create an active agent with a 60-second timer interval.
2. Set `lastHeartbeatAt` to more than 60 seconds in the past.
3. Call `tickTimers(now)` twice with `Promise.all()`.
4. Observe that the old code can enqueue two runs for the same interval.

**Paperclip version or commit**

Reproduced on `master` before this branch.

**Deployment mode**

Local development with embedded PostgreSQL.

## What Changed

- Added an atomic conditional update that claims a due timer interval by
advancing `lastHeartbeatAt`.
- Made `tickTimers()` enqueue only after that conditional update
succeeds.
- Preserved first-heartbeat telemetry when the timer claim advances
`lastHeartbeatAt` before run completion.
- Added regression tests for concurrent claims and first-heartbeat
telemetry.

## Verification

- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/heartbeat-stale-queue-invalidation.test.ts` — 24 tests
passed on the final rebased commit.
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/heartbeat-process-recovery.test.ts -t "preserves
first-heartbeat telemetry after a timer interval claim|tracks the first
heartbeat with the agent role"` — 2 tests passed.
- `pnpm --filter @paperclipai/server typecheck` — passed after the
review fix.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed.
- `pnpm test:run` — 3,121 tests passed and 2 tests skipped. One
unrelated runtime-skills test exceeded its 5-second limit under
full-suite load.
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/heartbeat-runtime-skills.test.ts` — the timed-out file
passed in isolation, 2 tests passed.
- `pnpm --filter @paperclipai/db exec vitest run
src/status-card-migrations.test.ts` — the unrelated CI timeout passed in
isolation.
- The full PR CI matrix passed after one rerun of that unrelated
timeout.
- Greptile passed with zero new comments and no unresolved review
threads.

## Risks

- Low risk. The change only affects due timer claims.
- If enqueue fails after the claim, the next timer attempt waits for one
interval. This is safer than duplicate agent execution.
- No schema, migration, API, UI, or dependency changes are included.

> 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 based on GPT-5. The exact deployment ID and
context-window size are not exposed to this runtime. Agentic reasoning,
shell tools, code execution, and GitHub operations were enabled.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 17:30:41 -07:00
32c1a8576c fix(server): self-heal execution workspaces whose recorded branch no longer exists (#10578)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Each agent task gets an execution workspace (a git worktree) with a
recorded branch name; workspace validation compares that record to the
worktree before every run
> - Agents sometimes rename their task branch (for example to a `feat/*`
PR branch), so the recorded branch never existed or was deleted
> - Validation then fails every run with "expected branch does not
exist" — a deterministic `workspace_validation_failed` loop with no
self-heal path
> - A recorded branch with no resolvable commit has nothing to lose, so
adopting a clean, registered checked-out branch is trivially
forward-only
> - This pull request routes that exact case through the existing
audited forward-reconciliation path, in both the runtime and the manual
board reconcile endpoint
> - The benefit is that these stranded workspaces heal themselves while
dirty worktrees, detached HEADs, unregistered paths, and ambiguous git
states all stay fail-closed

## Linked Issues or Issue Description

No public GitHub issue exists; the underlying bug is described here per
`bug_report.yml`. Related PR: #10574 self-heals the sibling provisioning
failure loop uncovered by the same incident diagnosis.

**What happened?**
An execution workspace whose recorded branch was renamed away failed
every subsequent run with `workspace_validation_failed` ("expected
branch does not exist"). The safe-repair matrix refused the case, so the
task stayed blocked until a human intervened.

**Expected behavior**
When the recorded branch is confirmed absent and the worktree is clean
and registered with its checked-out branch matching HEAD, Paperclip
adopts the checked-out branch through the audited forward-reconciliation
path and the next run proceeds.

**Steps to reproduce**
In an isolated workspace, rename the task branch (`git branch -m
<recorded> feat/something`) or delete the recorded branch, leave the
worktree clean, then start a new run on the task. Validation fails on
every retry.

**Paperclip version or commit**
master as of the branch point of this PR.

**Deployment mode**
Local trusted deployment with git-worktree isolated workspaces.

## What Changed

- `ensureGitWorktreeBranchCoherent` (workspace runtime): a missing
recorded branch with a clean worktree, an existing checked-out branch,
and a registered branch matching HEAD now goes through audited forward
reconciliation instead of failing closed. Gated behind
`enableWorkspaceBranchReconcileForward`.
- `reconcileExecutionWorkspaceBranch` mode `forward` (service): accepts
the same case so the board reconcile endpoint can repair it manually.
- The service inspection now classifies each branch ref as `resolved` /
`missing` / `error` (`git rev-parse --verify --quiet`, distinguishing an
absent ref from git failing to inspect the repo). Adoption requires a
confirmed-missing recorded ref **and** a resolved target ref, so a git
error can never bypass ancestry validation and a nonexistent branch name
is never persisted.
- Removed the test that asserted this case fails closed; it is
superseded by tests that assert the new behavior.
- New tests: successful adoption, dirty-worktree refusal, refusal when
the checked-out branch ref does not resolve either, and disabled-flag
behavior.

## Verification

- `server`: `npx vitest run
src/__tests__/execution-workspaces-service.test.ts -t "reconcil"` — 11
passed.
- `server`: `npx vitest run src/__tests__/workspace-runtime.test.ts -t
"adopt"` — 7 passed.
- `npx tsc --noEmit` in `server/` is clean.
- Manually validated the underlying repair on a live stranded workspace
before automating it: creating the recorded branch at the clean HEAD
ended the validation-failure loop without touching the agent's PR
branch.

## Risks

- The change relaxes a fail-closed gate, so the main risk is
over-adoption. Mitigations: the exception requires flag-on, clean
worktree, registered worktree path, registered branch matching HEAD, a
confirmed-missing (not merely unreadable) recorded ref, and a resolvable
target ref; everything else still fails closed. Every adoption goes
through the audited reconcile path with an issue comment trail.
- No migrations, no API surface changes (the reconcile route returns the
same hand-picked fields).

## Model Used

Claude Fable 5 (Anthropic, model ID `claude-fable-5`), extended
thinking, agentic tool use (Claude Code harness).

## Checklist

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 16:19:13 -07:00
79eff0aea1 fix(scripts): self-heal isolated workspace provisioning when the base CLI is broken (#10574)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents run tasks in isolated execution workspaces that are
provisioned as git worktrees by `scripts/provision-worktree.sh`
> - The script runs the base workspace's CLI (`cli/src/index.ts` via the
base `tsx` install) to seed each new worktree, and it only checked that
those files exist
> - pnpm links each package's `node_modules` into a hash-versioned
virtual store; a lockfile change followed by a partial or filtered
install prunes old hashed dirs without relinking every package, leaving
dangling symlinks
> - A CLI with dangling symlinks fails ESM resolution
(`ERR_MODULE_NOT_FOUND`) at boot, so provisioning aborts with
`setup_failed` — deterministically, on every retry, with no self-heal
path
> - This pull request makes provisioning health-check the CLI by
actually booting it, repair the base install when the check fails, and
degrade to the no-CLI fallback config instead of failing the run
> - The benefit is that a class of permanent `setup_failed` loops
becomes self-healing, and workspace provisioning survives a broken base
CLI

## Linked Issues or Issue Description

No public GitHub issue exists; the underlying bug is described here per
`bug_report.yml`. Related PR: #10578 self-heals the sibling
workspace-validation failure loop uncovered by the same incident
diagnosis.

**What happened?**
Isolated-workspace runs failed at provision time with `setup_failed`.
Every retry failed identically. One observed incident burned 4 runs
across two adapters before the task was stranded.

**Expected behavior**
Provisioning either succeeds or degrades gracefully; a broken base CLI
install repairs itself instead of permanently blocking all new
worktrees.

**Steps to reproduce**
In the base workspace, cause a lockfile-affecting dependency bump plus a
partial/filtered `pnpm install` so a package symlink (e.g.
`cli/node_modules/drizzle-orm`) dangles into a pruned virtual-store dir.
Start any isolated-workspace run. Provision fails with
`ERR_MODULE_NOT_FOUND` and the run ends `setup_failed`; retries never
recover.

**Paperclip version or commit**
master as of the branch point of this PR.

**Deployment mode**
Local trusted deployment with git-worktree isolated workspaces.

## What Changed

- `base_cli_healthy` now boots the base CLI (`--help`) instead of only
testing file existence, which exercises the top-level import graph.
- New `repair_base_workspace_install`: when the health check fails, run
a non-interactive `pnpm install --prod=false --force --frozen-lockfile`
in the base workspace. `--force` guarantees relinking when pnpm's
up-to-date heuristics would skip dangling symlinks; `--frozen-lockfile`
keeps the repair from mutating the shared lockfile.
- The repair install is serialized with `flock` on a lock file inside
the resolved git dir (`git rev-parse --absolute-git-dir`), so locking
also covers base workspaces that are linked worktrees, where `.git` is a
file.
- If every CLI candidate is unusable (including a base CLI the repair
could not fix), provisioning falls back to the existing no-CLI fallback
config writer (loudly, on stderr) instead of failing the run. A CLI that
runs and fails `worktree init` still fails provisioning with its real
exit code — that deliberate fail-closed policy is unchanged and covered
by an existing server regression test.
- Fixed a latent bug: `run_isolated_worktree_init` returned 0
unconditionally after the init subshell, so callers treated a failed
init as success. Exit codes now propagate.

## Verification

- Reproduced the incident state (dangling `cli/node_modules/drizzle-orm`
symlink); the base CLI failed with the exact `ERR_MODULE_NOT_FOUND` seen
in the incident run logs.
- Ran the patched script against a fresh scratch worktree: health check
failed → locked repair install ran (~26 s warm) → symlink relinked →
`worktree init` completed → exit 0 with `.paperclip/config.json` and
`.env` written.
- Happy path (healthy base CLI): provisioning behavior unchanged, exit
0.
- Verified `git rev-parse --absolute-git-dir` resolves a real directory
for both a normal checkout and a linked worktree.
- New hermetic tests: `node --test
./scripts/__tests__/provision-worktree-self-heal.test.mjs` (4 tests:
healthy CLI used, broken CLI degrades, locked repair end-to-end with a
fake pnpm, init failure propagates). Not yet wired into a CI workflow.
- `server`: the existing `realizeExecutionWorkspace` fail-closed
regression test ("fails instead of writing an unseeded fallback config
when worktree init errors after CLI detection succeeds") passes against
the new script.
- `bash -n scripts/provision-worktree.sh` is clean.

## Risks

- Low risk overall: the script only adds recovery paths; the happy path
is unchanged.
- The repair install runs in the shared base workspace. It is bounded by
`--frozen-lockfile` (no lockfile mutation) and serialized by `flock`,
but it can add ~30 s to the first provision after a base install breaks.
- If the repair cannot fix the CLI and no other CLI candidate exists,
runs now continue with an unseeded fallback config instead of failing;
that is intentional, and the fallback path already existed. Genuine
`worktree init` failures from a working CLI still fail the run.

## Model Used

Claude Fable 5 (Anthropic, model ID `claude-fable-5`), extended
thinking, agentic tool use (Claude Code harness).

## Checklist

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 16:18:52 -07:00
2cbbad16fd docs: add External Task Protocol specification (#10568)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Teams often keep their work in external ticket systems
> - Paperclip must keep execution and governance control when those
systems supply work
> - Connector authors need one provider-neutral contract for links,
routing, sync, and recovery
> - This pull request adds that contract as a draft specification
> - The benefit is a shared design for external task connectors without
provider logic in Paperclip core

## Linked Issues or Issue Description

- Refs: #3587
- Related prior connector work: #6271
- Supersedes the non-reopenable #7904.
- Duplicate #10569 was opened during concurrent recovery; this PR
contains the later review fixes
and is the 5/5, green canonical replacement. Recommend closing #10569
without merging it.

## What Changed

- Added a normative External Task Protocol for provider-neutral task
data, link state, routing, synchronization, conflicts, and health.
- Defined a Symphony-compatible execution profile that uses Paperclip
checkout, heartbeat, workspace, budget, approval, and blocker controls.
- Added provider profiles for Linear, Jira, Asana, Notion, Trello, and
GitHub Issues.
- Fixed the link-state transitions, reopen invariant, and section
cross-reference found in review.
- Updated the connector boundary to name the current capability-gated
plugin host clients.
- Aligned backlog wake semantics and issue-scoped run-stop conformance
with the current host API.
- Made terminal-to-active follow-up handoff retry-safe using a
single-record `TaskLink` retarget and
auditable handoff history, without assuming unavailable multi-record
plugin transactions.
- Preserved and refreshed Dotta's original specification work.

## Verification

- Ran `git diff --check`.
- Checked every numbered section reference against the document
headings.
- Compared the protocol integration points with the current plugin SDK
and host issue contracts.
- Ran the current PR template, linked-issue, duplicate-search, and
test-coverage quality gates against this description and title.

## Risks

- Low runtime risk. This pull request changes documentation only.
- The specification can constrain future connector designs. It remains a
draft and keeps provider-specific behavior in plugins.
- The replacement keeps the legacy `PAP-10377-task-protocol` head ref
because renaming it closed
  #7904 and GitHub would not reopen that PR after the ref was restored.

> 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

- The original draft used Claude Code. This review repair used OpenAI
Codex with GPT-5. The exact API snapshot and context window are not
exposed. The run used reasoning, repository inspection, shell tools, and
code editing.

## 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] Branch naming exception is documented above; the legacy public
issue branch was retained to preserve the repaired head ref
- [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: Dev Agent <dev@paperclip.ing>
2026-07-31 15:04:59 -07:00
DottaandPaperclip 1ee1275f11 fix(adapters): persist ACPX process identity for hot restart (#9838)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents for work.
> - Local agent heartbeats need durable process identity so the server
can supervise them.
> - The ACPX runtime owns the child process used by `codex_local`
sessions.
> - ACPX did not expose the child PID and start time to the Paperclip
adapter.
> - Warm ACPX runtimes can also serve a later heartbeat without a new
spawn event.
> - A hot restart could therefore classify a live Codex run as lost
because its heartbeat row had no process identity.
> - This pull request forwards ACPX spawn identity, reuses it for
compatible warm heartbeats, and fails closed when identity cannot be
persisted.
> - The benefit is reliable hot-restart adoption for eligible local
Codex runs.

## Linked Issues or Issue Description

No matching public GitHub issue was found.

**What happened?**

A `codex_local` heartbeat could run through ACPX without a persisted
`processPid` or `processStartedAt`. A Paperclip hot restart then had no
durable identity for the live ACP child. Recovery could classify the run
as `process_lost` even while the child was still alive.

**Expected behavior**

ACPX reports the real child PID and start time before the first prompt.
A compatible warm runtime reports the same known identity to each later
heartbeat that reuses the child. ACPX stops the child if the identity is
invalid or persistence fails. Hot-restart recovery can then adopt the
live run.

**Steps to reproduce**

1. Start a `codex_local` heartbeat through the ACPX execution lane.
2. Keep the run active during a Paperclip hot restart.
3. Inspect the heartbeat row before this change.
4. Observe that the process identity can be null and recovery cannot
adopt the live child.

**Reproduced on**

- Paperclip `master` before this change.
- Linux source deployment.
- `codex_local` with ACPX `0.12.0`.

## What Changed

- Add an awaited `onAgentSpawn` lifecycle hook to the patched ACPX
runtime.
- Forward the ACP child PID and start time through the adapter `onSpawn`
callback.
- Keep a mutable callback sink for cached runtimes so a later respawn
updates the current heartbeat.
- Reuse the last known process identity when a compatible warm heartbeat
reuses the existing child.
- Kill the ACP child and fail session startup when the PID is invalid or
identity persistence rejects.
- Add ACPX and heartbeat recovery tests for callback ordering, warm
reuse, failure cleanup, durable row identity, and hot-restart adoption.
- Document the one-time drain required when an installed pre-fix run
already lacks process metadata.

## Verification

-
`PAPERCLIP_HOME="$PAPERCLIP_RUN_SCRATCH_DIR/test-home-execute-escalated"
pnpm exec vitest run
packages/adapter-utils/src/acpx-engine/execute.test.ts` — 89 passed.
-
`PAPERCLIP_HOME="$PAPERCLIP_RUN_SCRATCH_DIR/test-home-recovery-escalated"
pnpm exec vitest run
server/src/__tests__/heartbeat-process-recovery.test.ts` — 92 passed.
-
`PAPERCLIP_HOME="$PAPERCLIP_RUN_SCRATCH_DIR/test-home-remote-smoke-escalated"
pnpm exec vitest run
packages/adapter-utils/src/acpx-engine/remote-spawn-smoke.test.ts` — 3
passed.
-
`PAPERCLIP_HOME="$PAPERCLIP_RUN_SCRATCH_DIR/test-home-ci-repro-escalated"
pnpm exec vitest run
server/src/__tests__/heartbeat-dependency-scheduling.test.ts` — 6
passed.
- `pnpm --filter @paperclipai/adapter-utils typecheck` — passed.
- Reverse and forward dry-run application of `patches/acpx@0.12.0.patch`
— passed.
- `git diff --check` — passed.
- `git diff --exit-code origin/master...HEAD -- pnpm-lock.yaml` —
passed.
- `git diff --exit-code origin/master...HEAD -- .github/workflows` —
passed.

## Risks

- Runtime risk is low to moderate. ACPX now awaits process-identity
persistence during child startup.
- ACPX kills the child when persistence fails. This prevents an
unsupervised process, but it makes that heartbeat fail visibly.
- A compatible warm heartbeat reuses the identity of the existing ACP
child. Regression tests verify that identity is persisted before the
next prompt.
- The change updates the vendored ACPX patch. Package installation must
apply that patch.
- There are no schema, migration, public API, UI, workflow, or lockfile
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 used GPT-5.3-Codex for the earlier implementation.
- OpenAI Codex used GPT-5 for the lifecycle-hook revision and the
current fail-closed review fix. The runtime did not expose a more
specific snapshot ID or context-window size. Both runs used reasoning,
repository tools, and code execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 14:43:46 -07:00
DottaandPaperclip cd7f84965c fix(recovery): preserve hand-back wake liveness (#10562)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The heartbeat service delivers issue work to assigned agents.
> - Recovery can hand an issue back to its agent while the recovery run
is still active.
> - The hand-back wake can merge into that active run and disappear when
the run exits.
> - The stranded-work scan also treats the successful recovery run as
proof that the handed-back issue is live.
> - This pull request keeps the hand-back wake for follow-up delivery
and lets the scan repair a lost wake.
> - The benefit is that an assigned issue continues after recovery
without manual operator action.

## Linked Issues or Issue Description

No public issue exists. This is related to the wake reconciliation work
in #8943.

**What happened?**

A recovery action could hand an assigned issue back from `blocked` to
`todo`. The `issue_recovery_action_restored` wake then merged into the
recovery run that made the change. The wake disappeared when that run
exited. The stranded-work scan did not repair the issue because it
treated the successful recovery run as current liveness.

**Expected behavior**

Paperclip must dispatch the hand-back wake after the recovery run exits.
If that delivery is lost, the stranded-work scan must enqueue the
assigned `todo` issue again.

**Steps to reproduce**

1. Start a recovery run for an assigned blocked issue.
2. Resolve a recovery action with the `handed_back` outcome.
3. Move the issue to `todo` while the recovery run is still active.
4. Observe that the wake merges into the active run and no new run
starts after it exits.
5. Run the stranded-work scan and observe that the successful latest run
prevents repair.

**Paperclip version or commit**

`131d476a7e`

**Deployment mode**

Local dev (`pnpm dev`). The defect is in the core server and is not
deployment-specific.

**Agent adapter(s) involved**

Not adapter-specific. This is a core heartbeat and recovery defect.

## What Changed

- Added `issue_recovery_action_restored` to the wake reasons that
require follow-up delivery when an issue run is active.
- Made the stranded-work scan detect a resolved hand-back that occurred
during or after the latest successful run.
- Added focused regression tests for the heartbeat coalescing seam and
the stranded-work repair shape.
- Documented the hand-back liveness guarantee in execution semantics
section 9.1.

## Verification

- `pnpm exec vitest run
server/src/__tests__/heartbeat-comment-wake-batching.test.ts
server/src/__tests__/heartbeat-process-recovery.test.ts` passed: 104
tests.
- `pnpm --filter @paperclipai/server typecheck` passed.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- `pnpm test:run` passed the server shard (3,095 passed, 2 skipped) and
UI shard (3,182 passed). One unrelated CLI test failed because the agent
environment exports static AWS credentials. `env -u AWS_ACCESS_KEY_ID -u
AWS_SECRET_ACCESS_KEY -u AWS_SESSION_TOKEN pnpm exec vitest run
cli/src/__tests__/secrets.test.ts` passed all 8 tests.
- `git diff --check` passed.
- All GitHub checks passed on commit `8b380e67e6`.
- Greptile gave 5/5 confidence with no comments or unresolved threads.

## Risks

- Low risk. The follow-up rule affects only a recovery hand-back wake
that arrives while the same issue already has an active run.
- The backstop adds one indexed recovery-action lookup for an assigned
`todo` issue whose latest run succeeded.
- The timestamp check uses the latest run start time. This includes
hand-backs made by that run and later hand-backs, but excludes older
resolved actions.

## Model Used

- OpenAI Codex with GPT-5 (`gpt-5`), agentic reasoning, tool use, and
code execution. The serving context-window size is not exposed to the
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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 11:03:30 -07:00
DottaandPaperclip bec04da2c2 fix(ui): make task header status and priority controls interactive (#10526)
<!-- Write all pull request text in Simplified Technical English
(ASD-STE100): short sentences, one instruction per sentence, simple
approved vocabulary, and the active voice. -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Operators use the task page header to read and change task state
> - The status and priority icons already had picker logic, but the
compact triggers were not semantic controls
> - This made pointer and keyboard interaction unreliable in the task
header
> - This pull request makes both compact icon triggers real buttons and
keeps the existing picker behavior
> - The benefit is that operators can change status and priority
directly from the header with pointer or keyboard input

## Linked Issues or Issue Description

### Subsystem affected

`ui/` — React + Vite board UI.

### Problem or motivation

The compact status and priority icons can receive change handlers, but
their popover triggers are plain icon elements. They do not provide a
reliable click target, keyboard focus, or control label. Operators need
to change both values directly from the task header.

### Proposed solution

Use semantic button triggers in the shared status and priority
components. Keep the existing API update wiring and picker options. Keep
task-row navigation links separate from editable row controls. An
operator can select either icon, open its picker, and choose a new task
status or priority.

### Alternatives considered

A task-page-only wrapper would duplicate control behavior. Moving the
controls would also change the page layout. The shared components
already own the picker behavior, so a shared trigger fix is smaller and
more consistent.

### Roadmap alignment

This is a focused board UI usability and accessibility fix. It does not
duplicate a planned roadmap feature.

### Additional context

The task page already passes change handlers to these shared components.
This change makes that existing path interactive and accessible.

## What Changed

- Added semantic button triggers for compact and labeled status
controls.
- Added semantic button triggers for compact and labeled priority
controls.
- Added accessible current-state labels and keyboard focus styles.
- Separated issue-row navigation links from row controls to avoid nested
interactive elements.
- Added real popover interaction coverage and row semantics regressions.
- Added task-page regression tests for update requests.

## Verification

- Focused task-header and row suites passed with 131 tests.
- The final row, inbox, and picker regression suites passed with 83
tests.
- `pnpm --filter @paperclipai/ui exec tsc -b --force` passed.
- `pnpm run typecheck:build-gaps` reproduced the CI typecheck before the
fix. The forced UI build passed after the fix.
- `pnpm check:token-gates` passed.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- `pnpm test:run` completed the server and UI partitions. One unrelated
CLI AWS doctor assertion saw injected static AWS credentials and
returned `warn` instead of `pass`. The exact test passed after those two
environment variables were removed.
- `git diff --check origin/master...HEAD` passed.
- All latest-head GitHub checks passed, including both e2e shards.
- Greptile passed at the required threshold with zero open review
threads.

## Risks

- The shared issue-row DOM now uses a full-area navigation link beside
native action buttons.
- Existing visual layout, pointer navigation, keyboard navigation, and
action behavior remain covered by row, inbox, and list tests.
- Read-only status and priority icon uses are 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 with the `gpt-5` model. The runtime did not expose its
context window size. The agent used reasoning, repository tools, code
execution, and GitHub CLI integration.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-31 10:49:35 -07:00
b4a7a12985 feat: make recovery updates quieter (#10542)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The recovery subsystem restores work after an agent run stops or
loses state
> - Recovery notices currently use the same visual weight as normal work
comments
> - Recovery agents can also post long narratives that obscure the
useful hand-off
> - The server must identify recovery output because agents cannot set
presentation controls
> - This pull request adds compact recovery notices, structured action
references, and brief recovery prompts
> - The benefit is a quieter issue thread that still keeps recovery
state inspectable

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting: `server/`, `packages/shared`, and
`packages/adapter-utils`.

**Problem or motivation**

Recovery notices and recovery-run comments can dominate an issue thread.
Operators must scan routine recovery narration before they find the work
hand-off.

**Proposed solution**

Give routine recovery output a compact system-notice presentation.
Derive the presentation on the server so agents cannot hide arbitrary
comments. Keep the successful missing-state summary fully visible
because that comment is the recovery deliverable.

**Alternatives considered**

The UI could detect recovery text. That approach is fragile and does not
provide structured action references. Agents could also set presentation
directly, but that would weaken the current board-only security
boundary.

**Roadmap alignment**

This change refines the completed “Self-healing runs & automatic
recovery” and “Enforced Outcomes” roadmap areas. It does not add a
competing roadmap capability.

**Additional context**

The scope covers shared comment validation, server recovery notices,
agent-comment derivation, and recovery prompt text. No database
migration is needed because presentation data already uses JSON.

## What Changed

- Add the `compact` issue-comment presentation density to shared
constants, types, and validation.
- Give recovery escalation, waiting, and in-place notices compact titles
and structured recovery-action metadata.
- Use recovery-action metadata for notice deduplication, with the legacy
text marker as a compatibility fallback.
- Derive compact presentation for comments from recovery-scoped runs
while preserving the board-only presentation boundary.
- Keep successful missing-state recovery summaries fully visible.
- Ask recovery participants to record outcomes in `resolutionNote` and
keep source-issue comments brief.
- Add shared, route, service, and prompt tests for the new behavior and
exceptions.

## Verification

- `pnpm -r typecheck`
- Focused Vitest coverage: 320 tests passed across shared validators,
adapter prompts, issue comments, recovery actions, and heartbeat
recovery.
- Full server phase: 292 files passed, 3,094 tests passed, and 2 tests
skipped.
- Full UI phase: 386 files passed and 3,182 tests passed.
- `pnpm build`
- Known master baseline: `cli/src/__tests__/secrets.test.ts` expects
`pass`, but the current implementation returns `warn` when strict secret
mode is disabled for Postgres. This branch does not change CLI secrets
code.

## Risks

- Low migration risk. The presentation column is JSON and needs no
database migration.
- Recovery-run detection depends on the persisted run context snapshot.
- Structured metadata becomes the primary deduplication key. The
existing body marker remains as a fallback for older comments.

> 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 `gpt-5.6-sol`. The runtime did not expose the
context-window size. The model used agentic reasoning, repository tools,
code execution, and 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)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-31 09:55:01 -07:00
DottaandPaperclip 6a3cbe1c58 fix(ui): load the full selected timeline window (#9576)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The timeline page visualizes company activity across a selected date
window
> - The UI requested only the first paginated issue batch even when the
selected zoom covered seven or thirty days
> - A busy company could therefore render an incomplete timeline while
the controls implied the full window was loaded
> - The timeline query needs to exhaust the API pagination for the
selected date range and combine each page without duplicating shared
timeline records
> - This pull request adds a paginated window loader, merges the
returned timeline data, and covers the multi-page behavior with a
regression test
> - The benefit is that the visible timeline matches the selected zoom
window instead of silently omitting later issues

## Linked Issues or Issue Description

### Pre-submission checklist

- [x] I searched existing open and closed issues and pull requests; no
matching report or implementation was found.
- [x] I reproduced the behavior against the pre-change `master`
implementation.
- [x] I confirmed the error originates in Paperclip's core timeline UI,
not an adapter, provider, or local configuration.

### What happened?

Selecting the default seven-day timeline range loaded only the first API
page (up to 500 issues). Companies with more activity therefore
displayed incomplete data even though the controls showed the full
selected window.

### Expected behavior

The timeline should load all issue pages that fall within the selected
date window.

### Steps to reproduce

1. Open the company timeline for a date range containing more than 500
issues.
2. Keep the default seven-day range or select another multi-day preset.
3. Observe that only the first page of issue-backed timeline data is
shown.

### Paperclip version or commit

Pre-change `master`.

### Deployment mode

Local dev source build. The behavior is not adapter-specific and is
independent of database mode and access context.

### Privacy checklist

- [x] No logs, configuration, personally identifiable information, or
user data are included.

## What Changed

- Added pagination parameters to the timeline API client contract.
- Added a timeline window loader that requests every issue page and
deduplicates actors, spans, events, and edges while preserving
pagination metadata.
- Switched the timeline query to use the complete-window loader.
- Added a regression test proving a 501-issue window loads both API
pages and combines their records.
- Preserved delegation events and edges when parent and child issues
fall on different API pages, with a server regression test.

## Verification

- `pnpm exec vitest run
server/src/__tests__/work-timeline-service.test.ts
ui/src/pages/Timeline.test.tsx` — 16 tests passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `pnpm check:token-gates` — all gates clean.
- `git diff --check origin/master...HEAD` — passed.
- Remote CI: build, typecheck, both e2e shards, canary, policy,
security, every general/serialized test shard, and the aggregate
`verify` gate passed on head `24784b28e9`.

## Risks

- Low risk: the change is isolated to timeline data loading and has no
schema or API endpoint changes.
- Large date windows now make sequential requests for all issue pages,
increasing request count for very active companies; the 500-item page
size bounds each response.
- Merged records rely on stable identifiers or composite event/edge
keys; the regression test covers cross-page combination and
deduplication 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 using GPT-5.4 with reasoning, repository tool use, shell
execution, and test execution. The runtime does not expose the exact
context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-30 21:40:57 -07:00
DottaandPaperclip 7cfb655f60 fix(worktree): disable automatic database backups (#10520)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip creates isolated instances for linked git worktrees so
development does not affect the primary instance
> - Those instances inherited the source instance's automatic
database-backup setting and also repaired older configs without
overriding it
> - As worktrees accumulated, each isolated instance could schedule its
own backup stream, producing redundant backup churn for disposable
database clones
> - This pull request makes backup disablement an invariant of worktree
config creation and repair
> - The benefit is that automatic backups remain focused on the durable
primary instance while isolated development instances stop accumulating
redundant backup files

## Linked Issues or Issue Description

No public GitHub issue exists for this bug, so the report is included
here. The closest related open change is Refs #10266, which hardens
where worktree config repair may write; this PR changes the backup
policy applied by that repair and by worktree initialization.

### What happened?

Isolated worktree instances copied `database.backup.enabled` from their
source config. When the source instance enabled automatic backups (the
normal default), every linked worktree also enabled a scheduled backup
stream. Existing worktree configs kept that state during startup repair,
so the redundant backups continued after the policy changed.

### Expected behavior

Automatic database backups are disabled for isolated worktree instances
created by `paperclipai worktree init` or `paperclipai worktree:make`,
and legacy worktree configs are migrated to that policy during normal
startup repair. The durable primary/default instance keeps its existing
backup behavior.

### Steps to reproduce

1. Start from a Paperclip instance whose database backup setting is
enabled.
2. Create or initialize a linked worktree with `paperclipai worktree
init`.
3. Inspect the generated worktree config and environment.
4. Before this change, the config retained `database.backup.enabled:
true` and the environment had no disabling override; after this change,
the config is false and `PAPERCLIP_DB_BACKUP_ENABLED=false` is
persisted.

### Paperclip version, deployment mode, and environment

- Reproduced against `master` before commit `ea5e0a0269`.
- Deployment mode: local trusted development with linked git worktrees
and embedded PostgreSQL.
- Environment: Node.js 22, pnpm workspace install.

## What Changed

- Always generate isolated worktree configs with automatic backups
disabled.
- Persist `PAPERCLIP_DB_BACKUP_ENABLED=false` in generated worktree
environments.
- Repair existing isolated worktree configs and environments that still
enable backups.
- Add CLI and server regression coverage for creation and legacy repair
paths.
- Document the worktree-specific backup policy and primary-instance
exception.

## Verification

- `pnpm exec vitest run cli/src/__tests__/worktree.test.ts
server/src/__tests__/worktree-config.test.ts` — 52 tests passed.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed.
- All repository commands above were run with inherited worktree runtime
identity variables removed.

## Risks

- Low operational risk: the change is limited to explicitly isolated
worktree instances.
- Operators who intentionally relied on automatic backups of disposable
worktree databases will now need to run a manual backup or explicitly
manage those files outside the scheduled worktree runtime.
- No schema, migration, 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 based on GPT-5 (the runtime does not expose a more
specific snapshot ID or context-window value), using reasoning, tool
use, local code execution, and GitHub CLI integration.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-30 17:35:04 -07:00
DottaandPaperclip a5d252d058 feat(skills): add confirmed inbox gardening workflow (#10462)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators use the Mine inbox to track work that needs their
attention.
> - Old terminal work can make that inbox difficult to review.
> - Inbox cleanup must not change issues, branches, or workspaces.
> - Operators also need to approve each cleanup set before Paperclip
hides any item.
> - This pull request adds a garden-inbox skill with scan, confirmation,
and apply stages.
> - The benefit is a safe and repeatable inbox cleanup workflow with an
explicit undo path.

## Linked Issues or Issue Description

### Subsystem affected

Cross-cutting. This change adds an agent skill that calls existing
inbox, workspace, interaction, and archive APIs.

### Problem or motivation

Old terminal inbox entries can hide current work. Manual cleanup is slow
and can select the wrong entries. A single global result limit can also
hide rows from a large inbox.

### Proposed solution

Add a zero-dependency skill that classifies inbox rows, requests
checkbox confirmation, and archives only accepted rows for the current
user. Scan each relevant status separately, remove duplicate rows, and
report partial coverage if a status reaches its result limit.

### Alternatives considered

Automatic archive was rejected because it removes operator control. A
report-only tool was rejected because it does not complete the cleanup
workflow.

### Roadmap alignment

This is an agent skill. It does not add a new core product capability or
duplicate a planned roadmap item.

### Additional context

The apply stage changes only per-user inbox visibility. It provides the
archive API undo path for every successful item. A GitHub search found
no separate duplicate implementation; this pull request is the existing
result for the search terms.

## What Changed

- Added the `garden-inbox` skill workflow and command reference.
- Added a zero-dependency Node script with `scan`, `confirm`, and
`apply` commands.
- Added four exclusive classification buckets with machine-readable
reasons.
- Added per-status Mine scans, cross-status deduplication, and
partial-coverage reports for capped status results.
- Added chunked checkbox confirmations with deterministic idempotency
keys.
- Added strict accepted-option validation, per-item archive results, and
undo instructions.
- Added Node tests for classification, fail-safe inspection, accepted
selections, tampering, JWT decoding, URL normalization, and capped
scans.

## Verification

- Passed `node --check
.agents/skills/garden-inbox/scripts/garden-inbox.mjs`.
- Passed `node --test
.agents/skills/garden-inbox/scripts/garden-inbox.test.mjs`.
- Passed `pnpm -r typecheck` with inherited Paperclip runtime identity
variables removed.
- Passed `pnpm build` with inherited Paperclip runtime identity
variables removed.
- Ran `pnpm test:run`: 3,241 tests passed and 1 test skipped. One
unrelated current-base server integration assertion failed because it
received `heartbeat.scheduling_suppressed` instead of `issue_commented`
in `plugin-orchestration-apis.test.ts`. The exact test failed the same
way on one focused rerun. This pull request changes only
`.agents/skills/garden-inbox/**`.

## Risks

- Low risk. The skill is opt-in and does not change server or UI
behavior.
- `scan` and `confirm` do not mutate issues. `apply` only updates
per-user inbox archive visibility for accepted option IDs.
- API or workspace inspection failures keep items out of the archive
candidate set.
- A status result at the configured limit produces a visible
partial-coverage warning instead of claiming a complete scan.

> 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. See `CONTRIBUTING.md`.

## Model Used

- OpenAI `gpt-5.6-sol` through the Codex local adapter. The runtime did
not expose the context window size. The model used high-reasoning
coding, shell, API, and code-execution tools.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-30 16:36:46 -07:00
DottaandPaperclip fcf66f3a91 feat(skills): add managed skill rename API (#9688)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies.
> - Company skills are reusable capabilities that operators install,
edit, assign, and materialize for agents.
> - Managed local skills currently lack a safe backend operation for
changing their display name and canonical slug/key together.
> - Treating rename as an ordinary save can leave duplicate records,
stale runtime materializations, or agent assignments pointing at the old
key.
> - This pull request adds a company-scoped managed-skill rename
contract, service operation, and REST endpoint with focused
authorization and activity logging.
> - The benefit is an atomic-enough, recoverable rename path that keeps
disk state, database identity, and agent skill assignments synchronized.

## Linked Issues or Issue Description

- Refs #2121
- Problem: managed company skills need a dedicated rename operation
rather than save-time duplication behavior.
- Expected behavior: renaming a managed skill updates its name, slug,
key, source directory, frontmatter, runtime materialization, and
assigned-agent references while preserving version pins.

## What Changed

- Added shared request/result types and Zod validation for managed skill
rename requests.
- Added `POST /api/companies/:companyId/skills/:skillId/rename` with
`skills.edit` policy checks and `company.skill_renamed` activity
logging.
- Restricted renames to Paperclip-managed local skills and added slug,
key, and target-directory conflict handling.
- Moved the managed directory, rewrote only the `SKILL.md` frontmatter
name, updated the database row, and rolled filesystem changes back when
persistence fails.
- Rewrote assigned agents' desired-skill keys while preserving pinned
version IDs and removed stale runtime materialization.
- Added focused route and service coverage for success, no-op, name-only
changes, conflicts, unsupported sources, assignment rewrites,
rollback-sensitive behavior, and runtime cleanup.
- Rejected multiline rename names before they can inject extra
`SKILL.md` frontmatter fields.

## Verification

- `pnpm exec vitest run
server/src/__tests__/company-skills-service.test.ts
server/src/__tests__/company-skills-routes.test.ts` — 106 tests passed.
- `pnpm --filter @paperclipai/shared typecheck` — passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.

## Risks

- Filesystem and database updates cannot share one native transaction;
the service stages filesystem changes and explicitly restores the
original directory and markdown when the database transaction fails.
- Renames intentionally reject catalog, remote, project-scanned, and
unmanaged local skills to avoid changing identities owned by external
sources.
- No database migration is required; the endpoint updates existing
company-skill and agent configuration fields.

> 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 underlying model ID and
context-window size were not exposed to this runtime), with reasoning,
repository tool use, code execution, and test execution. The rescued
source commit also records assistance from Claude Opus 4.8.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-30 15:29:31 -07:00
DottaandPaperclip efe8b3b707 feat(skills-catalog): add optional /simplified-english skill (#10410)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents draw writing behavior from installable skills in the shipped
skills catalog (`packages/skills-catalog`)
> - Agent-authored comments, plans, and documents are often wordy or
ambiguous, which slows human readers
> - A small, opt-in skill can set a clear house style for user-facing
prose without touching agent code
> - This pull request adds an optional `simplified-english` catalog
skill that tells agents to write user-facing comments, plans, and
documents in ASD-STE100 Simplified Technical English
> - The benefit is shorter, unambiguous, one-meaning-per-sentence
writing that readers understand on the first pass

## Linked Issues or Issue Description

<!-- Feature request (no public GitHub issue). Described inline per
CONTRIBUTING.md → "Link Issues or Describe Them In-PR". -->

**Problem or motivation**

Agent-authored user-facing text (issue comments, plans, documents) is
frequently long-winded, uses inconsistent vocabulary, and packs multiple
instructions into one sentence. Readers have to re-read it. There is no
shared, installable house style for clear technical writing.

**Proposed solution**

Add an optional content skill, `simplified-english`, to the shipped
catalog. It instructs agents to write user-facing comments, plans, and
documents using only ASD-STE100 Simplified Technical English (short
sentences, one instruction each, approved single-meaning words, active
voice, present tense). Orgs opt in by installing it.

**Alternatives considered**

Baking the guidance into every agent's base instructions (too broad, not
opt-in) or a bundled skill (would apply everywhere by default). An
optional skill keeps it opt-in per org.

**Roadmap alignment**

Additive, opt-in catalog content only; no core behavior change.

## What Changed

- Add
`packages/skills-catalog/catalog/optional/content/simplified-english/SKILL.md`
— a short optional skill instructing agents to write user-facing
comments, plans, and documents in ASD-STE100 Simplified Technical
English. Includes an "Approved words" section that identifies the
controlled vocabulary (the ASD-STE100 Dictionary) and gives concrete
house-choice substitutions.
- Regenerate `packages/skills-catalog/generated/catalog.json` via
`build:manifest` so the manifest includes the new skill.
- Pin the new catalog key in
`packages/skills-catalog/src/shipped-catalog.test.ts`.

## Verification

- `pnpm --filter @paperclipai/skills-catalog build:manifest` → wrote
manifest with the new skill.
- `pnpm --filter @paperclipai/skills-catalog validate` → "Catalog
manifest is valid".
- `pnpm --filter @paperclipai/skills-catalog test` → the catalog
set/count/key pinning tests pass with the new skill included.
- Confirmed the generated entry: key
`paperclipai/optional/content/simplified-english`, trustLevel
`markdown_only`, description within the 300-char budget cap.

## Risks

Low risk. Additive, markdown-only optional skill plus a regenerated
manifest and a pinning-test update. No runtime code, migrations, or
workflow changes. Not installed by default (`defaultInstall: false`).

## Model Used

Claude Opus 4.8 (1M context), extended thinking, with tool use / code
execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-30 15:28:07 -07:00
c62fa8d6a0 docs(agents): add create-paperclip-bundled-skill agent skill (#10477)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents learn repeatable procedures through skills, and Paperclip
ships a curated skills catalog in `packages/skills-catalog`
> - People frequently send agents an idea, a tweet, or a task and ask
for it to become a catalog skill
> - Until now no written procedure existed for that flow, so each
attempt rediscovered the catalog rules (frontmatter fields,
`catalog-ref.json`, manifest regeneration, test expectations)
> - This pull request adds a repo agent skill that documents the full
find-or-make-and-publish procedure
> - The benefit is that any agent can turn source material into a
correct catalog pull request on the first pass

## Linked Issues or Issue Description

No public issue exists. Feature description: agents that maintain this
repository need a documented procedure to (a) research whether a
requested skill already exists, (b) add it to the skills catalog as a
local skill or a pinned external reference, (c) include worked examples,
and (d) regenerate the manifest and open a pull request. This change
adds that procedure as an agent skill. Related PR: #10410 (a catalog
skill addition that this skill uses as its worked example).

## What Changed

- Added `.agents/skills/create-paperclip-bundled-skill/SKILL.md`. It
documents: source capture (tweet fetch via the `xc` CLI or delegation),
a FIND-before-MAKE search order, kind/category/slug placement rules, the
`catalog-ref.json` external-reference format, local `SKILL.md` authoring
rules, `examples/` requirements, manifest regeneration,
`shipped-catalog.test.ts` expectation updates, and the PR procedure.
- Added
`.agents/skills/create-paperclip-bundled-skill/examples/new-local-skill.md`.
It is a worked example of the MAKE path, based on the simplified-english
catalog skill (#10410).
- Added
`.agents/skills/create-paperclip-bundled-skill/examples/external-reference.md`.
It is a worked example of the FIND path, based on the last30days
external reference that ships in the catalog today.

## Verification

- `pnpm --filter @paperclipai/skills-catalog test` — 20/20 tests pass.
This suite scans `.agents/**/SKILL.md` frontmatter, so it validates the
new skill's description budget.
- All statements about the catalog builder were checked against
`packages/skills-catalog/src/catalog-builder.ts` and the live artifacts
(`catalog/optional/research/last30days/catalog-ref.json`, PR #10410).

## Risks

- Low risk. The change adds three markdown files under
`.agents/skills/`. No runtime code changes.

## Model Used

- Claude Fable 5 (Anthropic, model ID `claude-fable-5`), agentic coding
session with tool use (file edits, shell, test runs).

## 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 (branch name comes from the
managed execution workspace and cannot be renamed)
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable (no code paths
changed; existing frontmatter tests cover the new files)
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 07:40:33 -07:00
DottaandPaperclip a6436126ce feat(ui): add recency separators to task lists (#10454)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents and their work
> - Project pages give operators a dense task list for understanding
what has changed recently
> - A purely chronological list makes the transition from fresh work to
aging work difficult to scan
> - The existing activity feed already uses a quiet labeled divider to
communicate a recency boundary
> - This pull request applies that familiar pattern to task lists at the
one-day and one-week boundaries
> - The benefit is faster age-based scanning without adding filters,
badges, or repeated metadata to every row

## Linked Issues or Issue Description

### Subsystem affected

`ui/` — React + Vite board UI.

### Problem or motivation

Operators scanning a project task list cannot quickly see where recently
created or updated work gives way to tasks that are more than a day or a
week old.

### Proposed solution

Insert subtle, accessible “Older than a day” and “Older than a week”
separators when a task list is sorted newest-first by creation or update
time.

### Alternatives considered

Per-row age badges would repeat state and add noise; persistent
age-based groups would interfere with the list's existing grouping
controls. Lightweight boundary markers preserve the current ordering and
interaction model.

### Roadmap alignment

This is a tightly scoped board-UI polish change and does not duplicate a
roadmap milestone.

### Additional context

The visual treatment follows the existing activity-feed recency
separator pattern. A public GitHub search found no duplicate or related
open issue or pull request.

## What Changed

- Added rolling one-day and one-week recency buckets for created/updated
timestamps.
- Rendered token-compliant, accessible separators only for newest-first
date sorts and only when visible rows cross a boundary.
- Traversed expanded nested rows in their exact visible order and
emitted every crossed boundary when adjacent rows skip an age bucket.
- Added component and helper coverage for sequential boundaries, skipped
buckets, expanded nested rows, and the no-separator same-bucket case.

## Verification

- `pnpm exec vitest run ui/src/components/IssuesList.test.tsx` — 42
tests passed.
- `pnpm check:token-gates` — all token gates clean.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm --filter @paperclipai/ui build` — passed (with existing build
warnings only).

## Risks

- Low risk: the change is presentation-only and limited to list mode
when sorting `created` or `updated` descending.
- Boundaries use rolling 24-hour and 7-day windows rather than
calendar-day boundaries, matching the age-based labels.

> 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 family (the runtime did not expose a more specific
model build or context-window size), with reasoning, repository tool
use, code execution, and GitHub CLI access.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-29 18:04:36 -07:00
DottaandPaperclip 24aa2f516d feat(ui): add animated paperclip page loaders (#10456)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents for work
> - Operators regularly pass through full-page loading states while
authentication and company context resolve
> - Those states currently render as small bare text, which is easy to
miss and does not reinforce Paperclip's visual identity
> - A shared loading component gives these transitions one accessible,
consistent representation
> - This pull request introduces an animated paperclip loader and uses
it at the existing full-page loading boundaries
> - The benefit is a clearer, calmer loading experience with
reduced-motion and screen-reader support

## Linked Issues or Issue Description

### Subsystem affected

`ui/` — React + Vite board UI

### Problem or motivation

Full-page authentication, access-gate, and company-context waits use
small bare `Loading…` text that is visually weak and inconsistent.

### Proposed solution

Use one large centered paperclip loader at those boundaries, drawing the
SVG with `currentColor` so it follows the active theme.

### Alternatives considered

Keeping text-only states or adding a generic spinner would preserve less
of Paperclip's product identity and would continue duplicating loading
markup.

### Roadmap alignment

This is tightly scoped UI polish and does not duplicate a planned
roadmap capability.

### Additional context

Internal coordination task PAP-15760 requested this focused change.

## What Changed

- Added `AnimatedPaperclipIcon`, a theme-aware SVG whose stroke draws in
a loop.
- Added `PaperclipLoading`, a large full-viewport centered loader with
`role="status"` and an `sr-only` `Loading…` label.
- Added a static fully drawn fallback under `prefers-reduced-motion:
reduce`.
- Replaced bare loading text in `CloudAccessGate`, the Auth session
check, and three company-context redirects.
- Used token-safe Tailwind utilities throughout the component.
- Added focused coverage for the status semantics and the Auth layout
height override.

## Verification

- `pnpm check:token-gates`
- `pnpm -C ui exec tsc -b`
- `pnpm -C ui exec vitest run
src/components/AnimatedPaperclipIcon.test.tsx`
- `pnpm -C ui exec vitest run src/App.test.tsx
src/App.cases-routing.test.tsx` — 8/8 tests passed
- Visually checked light and dark loading states; the screenshot below
shows both themes.

![Large centered paperclip loading state in light and dark
themes](https://pages.paperclip.ing/pap-15760-loading-state/pap15760-loading.png)

## Risks

- Low risk: this changes presentation only at existing loading branches.
- Motion-sensitive users receive a static, fully drawn paperclip through
the reduced-motion media query.
- Screen readers retain a concise loading announcement through the
status role and visually hidden label.

> 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 (exact service build ID and context-window size
are not exposed in this environment), with reasoning, repository
inspection, shell tool use, code execution, and image inspection.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used with all deployment details
available to this environment
- [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 found none
- [x] I have described the issue in-PR following the feature-request
fields
- [x] I included the task-mandated internal parent reference and no
private instance URL
- [x] I preserved the task-mandated existing branch name without
renaming it
- [x] I have run scoped tests locally and they pass
- [x] I added focused component coverage for the new loading state
- [x] No documentation update is required for this presentation-only
change
- [x] I have considered and documented the 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-29 17:58:50 -07:00
DottaandClaude Opus 4.8 2dca2df71f docs: require Simplified Technical English for PR text (#10447)
## Thinking Path

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

## Linked Issues or Issue Description

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

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

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-29 13:50:15 -05:00
DottaandPaperclip 1452d5f413 perf(ui): warm issue detail navigation (#10416)
## Thinking Path

> - Paperclip is the open source control plane people use to coordinate
AI-agent companies
> - The board UI opens issue details from lists, quicklooks, and the
inbox
> - Those navigation paths already have enough issue data to paint the
header immediately, but the comment feed still waits for its first
request
> - That delay makes repeat navigation feel cold and can briefly show an
empty thread before comments arrive
> - This pull request centralizes the comment page shape, prefetches
issue detail plus the first comment page, and renders a reserved
skeleton while an uncached page is loading
> - The benefit is faster, stable warm navigation without coupling this
change to the separate aggregate issue-detail API work

## Linked Issues or Issue Description

- **Subsystem affected:** `ui/` — React + Vite board UI
- **Problem or motivation:** Opening an issue from an already-loaded
list still waits for the first comments request and may flash the
empty-thread state, making warm navigation feel slower than necessary.
- **Proposed solution:** Prefetch the issue-detail snapshot and first
comments page from every issue navigation entry point, reuse one
page-size constant for prefetch and render queries, and show the
existing chat skeleton until the uncached initial page resolves.
- **Alternatives considered:** Relying only on detail-query prefetch
leaves comments cold; bundling this with the aggregate issue-detail
endpoint would make the UI improvement harder to review and land
independently.
- **Roadmap alignment:** `ROADMAP.md` has no overlapping
issue-navigation initiative. This is a focused board responsiveness
improvement.
- **Related pull requests:** #10409 establishes the issue-detail
performance baseline; #10414 reduces server-side issue-detail request
overhead.

## What Changed

- Added one shared issue-comment page-size constant used by rendering
and prefetching.
- Added first-page comment prefetching and a combined navigation
prefetch helper.
- Wired quicklook, issue-list keyboard navigation, and inbox navigation
to warm both caches.
- Kept the existing chat skeleton visible while the first uncached
comment page loads.
- Added focused cache behavior tests for comment and combined navigation
prefetching.

## Verification

- `vitest run ui/src/lib/prefetchIssueComments.test.ts` — 3 tests
passed.
- `tsc -b ui` — passed.
- `pnpm check:token-gates` — passed.

## Risks

- Low risk: this adds background prefetch requests on intentional issue
navigation/hover paths. React Query stale-time deduplication prevents
repeat requests while the cache is fresh.
- The change intentionally remains independent of the separate aggregate
`getView` work and composes with it through the same query keys.

> 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 `gpt-5.6-sol`; context-window
size was not exposed; reasoning mode with repository tool use and code
execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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-29 13:37:22 -05:00
DottaandPaperclip 170c1e5adb fix(claude-local): trust Paperclip URLs in allowlist sandbox (#10438)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Local adapters can confine agent processes with filesystem and
network sandbox policies
> - Allowlist confinement must still let an agent reach Paperclip's own
control plane and managed MCP servers
> - The Codex local adapter already marks those runtime-owned endpoints
as trusted, but the Claude local adapter did not
> - As a result, allowlisted Claude runs could not call their own
Paperclip API unless operators duplicated runtime URLs manually
> - This pull request mirrors the trusted-URL wiring in the Claude local
adapter and adds a regression test at the process-execution boundary
> - The benefit is that confined Claude agents retain their required
control-plane access without broadening the operator-managed network
allowlist

## Linked Issues or Issue Description

Refs #447

No exact public issue was found. The underlying bug is:

- **Observed:** with `claude_local` configured for local-process
`networkScope: "allowlist"`, the sandbox options omitted the
runtime-owned Paperclip API and MCP server URLs. Requests to those
endpoints could therefore be denied by confinement.
- **Expected:** Paperclip's own API URL and managed MCP server URLs are
passed as trusted sandbox targets, matching `codex_local` behavior.
- **Steps to reproduce:** configure a local Claude agent with allowlist
network confinement, omit the runtime Paperclip API URL from the
operator allowlist, and have the agent call its injected
`PAPERCLIP_API_URL`.
- **Version:** `ca92f727c5` (`origin/master` at branch creation).
- **Deployment mode:** local-process sandbox confinement in a local
deployment.

## What Changed

- Added the injected Paperclip API URL and runtime MCP server URLs to
`claude_local` sandbox `networkTrustedUrls`, filtering empty values.
- Added a unit test proving allowlist sandbox construction trusts
`PAPERCLIP_API_URL`.

## Verification

- `pnpm exec vitest run
packages/adapters/claude-local/src/server/execute.acp-fallback.test.ts`
- `pnpm --filter @paperclipai/adapter-claude-local typecheck`

## Risks

- Low risk. The change only affects confined local Claude processes and
trusts runtime-owned endpoints already injected by Paperclip.
- Operator-configured `networkAllowlist` behavior is unchanged; the
added URLs use the sandbox's separate trusted-target path.

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

## Model Used

- OpenAI Codex based on GPT-5 (exact serving snapshot and context-window
size are not exposed), with reasoning, repository inspection, shell tool
use, code editing, and 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)
- [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 (not
applicable: behavior parity fix with no user-facing configuration
change)
- [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-29 13:23:09 -05:00
DottaandPaperclip 487e33b8b6 fix(codex-local): resolve GPT-5.6 model metadata at source (#9780)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents for work
> - The `codex_local` adapter runs OpenAI's Codex CLI through direct CLI
and ACP execution lanes
> - The adapter defaulted to the bare `gpt-5.6` alias while the bundled
ACP Codex version lacked GPT-5.6-family metadata
> - Default and legacy-configured runs therefore emitted
fallback-metadata warnings and could use generic context limits
> - This pull request upgrades the bundled Codex ACP dependency, selects
the concrete `gpt-5.6-sol` model, and normalizes the legacy alias in
both execution lanes
> - The benefit is correct model metadata without hiding genuine stderr
or transcript warnings

## Linked Issues or Issue Description

Related public PRs: Refs #9342, Refs #9352, and Refs #9382. This PR is
narrower: it upgrades bundled Codex metadata and normalizes the legacy
bare alias in both execution lanes.

**Bug report**

### What happened

Default `codex_local` runs, and agents still configured with the bare
`gpt-5.6` model, print a model-metadata fallback warning and use generic
context-window limits.

Root cause: the ACP lane bundled a Codex release predating
GPT-5.6-family metadata, while Paperclip's default and advertised model
used the bare `gpt-5.6` alias for which Codex publishes no metadata.

### Expected behavior

A default Codex run resolves to a concrete model slug with published
metadata and does not emit a fallback-metadata warning.

### Deployment mode

Self-hosted/local `codex_local` adapter.

## What Changed

- Upgraded `@agentclientprotocol/codex-acp` from `^1.1.0` to `^1.1.4`
- Changed `DEFAULT_CODEX_LOCAL_MODEL` from `gpt-5.6` to `gpt-5.6-sol`
- Removed the bare alias from advertised models and listed concrete
GPT-5.6 Fast-mode variants
- Added `normalizeCodexModel()` and applied it in both CLI and ACP
execution lanes
- Updated adapter docs, Storybook fixtures, and regression tests
- Preserved warning visibility; no stderr, transcript, or log filtering
changed

## Verification

- `pnpm --filter @paperclipai/adapter-codex-local typecheck`
- `pnpm check:token-gates`
- `cd packages/adapters/codex-local && pnpm exec vitest run` — 205 tests
passed
- `cd server && pnpm exec vitest run
src/__tests__/adapter-models.test.ts` — 17 tests passed
- Confirmed the PR diff excludes `pnpm-lock.yaml` and
`.github/workflows/**` as required by repository policy
- Confirmed `.github/workflows/pr.yml` regenerates and uploads the PR
lockfile artifact before downstream `pnpm install --frozen-lockfile`
steps

## Risks

Low risk. The behavior change is scoped to `codex_local` model
selection. Existing concrete model IDs pass through unchanged; only the
legacy bare `gpt-5.6` alias is rewritten. Dependency resolution may
select a newer compatible `codex-acp` release within the declared range,
so CI remains the final compatibility gate.

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

## Model Used

- Original implementation: Anthropic Claude Opus 4.8 (`claude-opus-4-8`,
1M context, tool use and code execution)
- Conflict resolution and PR preparation: OpenAI GPT-5.5 (`gpt-5.5`,
Codex CLI coding agent, high-reasoning tool use and code execution;
host-managed context window)

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-28 16:15:08 -05:00
DottaandPaperclip 1cd09ed555 perf(heartbeat): reuse task sessions for issue-scoped timer wakes and bound control-plane write retries (#10350)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents make progress in heartbeats: the server wakes an agent
session, it does a slice of work on an issue, records a disposition, and
exits
> - Benchmarking identical coding tasks run as Paperclip-orchestrated
agent pairs vs invoking the same agent harness directly measured a
1.8–2.2× wall-clock slowdown for the Paperclip pairs, dominated by
per-heartbeat orchestration overhead rather than model time
> - Two contributors stood out: (1) since PF-4 (#4838) every
`heartbeat_timer` wake starts a brand-new task session, so continuation
work on a specific issue repays the full session-start and
re-orientation cost on every heartbeat; (2) in degraded environments
agents burn many tool calls retrying the same failing control-plane
write before giving up
> - This pull request reuses the task session for issue-scoped timer
wakes (keeping the PF-4 fresh-session rule only for unscoped exploratory
wakes, which were the original context-bloat case) and adds a
bounded-retry rule to the wake prompt and core skill: after 2
consecutive failures of the same control-plane write, stop retrying it
for the rest of the heartbeat and rely on the adapter/runtime status
channel
> - The benefit is materially less wall-clock and token overhead per
heartbeat while preserving the context-bloat protection PF-4 was added
for

## Linked Issues or Issue Description

Refs #4838 (merged PF-4 change whose reset rule this refines), Refs
#5287, Refs #1907 (related timer-heartbeat session work).

No public GitHub issue exists for the slowdown itself; bug-report
fields:

- **What happened:** Agent pairs orchestrated through Paperclip
heartbeats complete identical task sets 1.8–2.2× slower (wall-clock)
than the same harness invoked directly. Profiling attributed the gap to
per-heartbeat orchestration overhead: every timer wake discards the task
session (full session start + re-orientation), and in degraded
environments agents repeatedly retry the same failing control-plane
write.
- **Expected behavior:** Heartbeat orchestration should add minimal
wall-clock overhead on top of the underlying harness; issue-scoped
continuation work should not pay a fresh-session tax each interval.
- **Steps to reproduce:** Run a fixed benchmark task set once through
Paperclip issue heartbeats and once via direct harness invocation with
the same model/config; compare wall-clock totals.
- **Version/commit:** master @ 3d23c3b2c3, self-hosted deployment.

## What Changed

- `server/src/services/heartbeat.ts`: `shouldResetTaskSessionForWake`
now resets only for `heartbeat_timer` wakes with no derivable task key
(unscoped exploratory wakes). Issue-scoped timer wakes reuse the issue's
task session. `describeSessionResetReason` updated to stay in exact
agreement.
- `server/src/__tests__/heartbeat-timer-wake-session-reset-pf4.test.ts`:
new cases for scoped vs unscoped timer wakes, plus the scoped case added
to the reset/reason agreement invariant.
- `packages/adapter-utils/src/server-utils.ts`: wake prompt template and
execution contract gain a bounded-retry rule — after 2 consecutive
failures of the same control-plane write, stop retrying it for the rest
of the heartbeat, continue useful work, report the failure in the final
response, and use the adapter/runtime status channel as the sanctioned
fallback.
- `packages/adapter-utils/src/server-utils.test.ts`: asserts the new
prompt lines are present in both the template and the rendered wake
prompt.
- `skills/paperclip/SKILL.md`: documents the same bounded write-retry
rule in the core Paperclip skill.

## Verification

- `node_modules/.bin/vitest run
packages/adapter-utils/src/server-utils.test.ts` — 1 file, 83 tests
passed
- `cd server && node_modules/.bin/vitest run
src/__tests__/heartbeat-timer-wake-session-reset-pf4.test.ts` — 1 file,
14 tests passed
- Both run on this branch rebased onto current master (3d23c3b2c3)

## Risks

- Behavioral shift: issue-scoped timer wakes now reuse sessions, so a
long-lived issue session can grow across heartbeats. Mitigated by
keeping the PF-4 reset for unscoped wakes (the originally observed bloat
case) and by existing session compaction.
- Prompt/skill text changes alter agent guidance; the new rule is scoped
narrowly to repeated failures of the same control-plane write.
- No migrations, no API or schema changes, no dependency changes.

## Model Used

- Claude (Anthropic) — `claude-fable-5` (Fable 5), extended reasoning
with tool use, driven via Claude Code / Claude Agent SDK.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-27 22:01:29 -05:00
DottaandPaperclip c3bd0c5d50 feat(skills): add beta releases for the core Paperclip skill (#10228)
## Thinking Path

> - Paperclip is the open source control plane people use to organize
and operate AI-agent companies.
> - Agent behavior depends partly on the bundled Paperclip core skill
synchronized into each runtime.
> - The existing database and runtime plumbing already supports
immutable skill-version snapshots and per-agent version selections, but
no product workflow exposed that capability.
> - Replacing the live bundled skill globally would make champion
adoption risky and difficult to compare across agents.
> - This pull request adds an experimental, instance-level beta-skills
gate plus a repository release registry, immutable seeded releases,
enforcement, and a per-agent release picker.
> - The benefit is controlled per-agent evaluation of frozen core-skill
releases while the default-off path remains behaviorally unchanged.

## Linked Issues or Issue Description

### Subsystem affected

Cross-cutting: `server/`, `ui/`, `packages/db`, and `packages/shared`.

### Problem or motivation

Paperclip needs a safe way to evaluate improved versions of its core
operating skill without globally replacing the live default. Today the
version-snapshot and per-agent pin plumbing exists, but operators cannot
use it. A global replacement would make regressions difficult to contain
and would prevent controlled comparisons across agents.

### Proposed solution

Add a default-off instance experiment that exposes immutable, named
core-skill releases. When enabled, operators can pin each agent to a
seeded release; when disabled, every agent resolves the live default
while saved pins remain intact. Validate pinned writes at the API
boundary, gate reads at runtime, and expose the selection in the agent
Skills tab.

### Alternatives considered

- **Replace the bundled core skill globally:** rejected because it
changes every agent at once and provides no rollback/isolation boundary.
- **Ship releases as separate skills:** rejected because releases are
versions of one core capability, not independently enabled skills.
- **Store release snapshots only outside the repository:** rejected
because repository provenance and hashes make builds reproducible and
reviewable.

### Roadmap alignment

This extends the Skills Manager / Skill Studio direction in `ROADMAP.md`
by making core-skill versions operable per agent. It does not duplicate
another open implementation PR; GitHub searches found no related
`enableBetaSkills` change.

### Additional context

The feature remains experimental and default off. The V7 champion was
selected through a multi-model evaluation process, and the frozen
release contents are verified by SHA-256 below.

## What Changed

- Added the default-off instance-level `enableBetaSkills` experimental
flag.
- Added `skills-releases/paperclip/` with the ordered release registry
and frozen `v0` plus `v7-roster` snapshots.
- Added release metadata to `company_skill_versions` and idempotent
release seeding. The migration was planned as `0191`, then renumbered to
`0192` because current `master` claimed `0191` before final rebase.
- Added read-time gating and write-time validation so disabled instances
always resolve the live default and reject pinned-version writes.
- Added the per-agent Release picker in the agent Skills tab, including
responsive layout and beta-pin state.
- Kept `EDITS.md` out of the release registry and PR diff.

### V7 Adoption Evidence

- Paid roster: 6 models, 94-case suite.
- Result: 553/564 pass-within-2, mean 92.17/94, versus the P2 baseline
of 544/564.
- Reference model improved 84→91; maximin improved 84→90.
- Final report:
https://pages.paperclip.ing/skills/optimization/paperclip/pap-14624-p3-final-20260721/

### Provenance

- `v7-roster` is the Phase 1 champion plus additions-only edits
E107–E112. Per-edit rationale remains in the evals repository at
`source/v7-roster/EDITS.md` and is deliberately excluded from this PR.
- `v0` is the `skills/paperclip` tree from commit `ea66ea81`.
- Champion selection was accepted on July 21, 2026 via board card
`9c304fc2` (PAP-14624 G3).
- This delivery mechanism was accepted on July 24, 2026 via plan
revision `2367abd2` (PAP-14858).

### QA Evidence

- P4 QA matrix comment `b7f40522-4e9b-4a3a-9821-28e86fe1a987`: all 6
acceptance criteria passed.
- Automated QA matrix: 166 tests passed with 0 failures, including real
filesystem materialization and full SHA-256 assertions.
- UI QA exercised the real agent Skills tab at desktop and mobile widths
with the experimental flag both on and off.

## Verification

- `pnpm check:token-gates`
- Focused beta-release matrix: 169 tests passed across shared
validators, server services/routes/heartbeat behavior, instance settings
UI, and release picker UI.
- `pnpm -r typecheck`
- `pnpm build`
- `pnpm test:run`: server and UI partitions passed; one CLI doctor test
inherited temporary AWS credentials from the agent heartbeat and
expected no static credentials. The isolated rerun with
`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN`
unset passed 8/8.
- V7 SHA-256:
- `SKILL.md`:
`53ab290489684cbf116fdd1406a95f6b6f53c9c36358b1bf8bfeae481e253575`
- `references/cases.md`:
`3b821f59064a7761091020a14819a8d787131f24029748563d6c0e1be7e6eaec`
- `references/workflows.md`:
`69747bd6e05f7e3673d1e67b07ff295df1869c05e1fd029804d5fa9177db92cd`
- Confirmed 49 changed files, no `pnpm-lock.yaml`, no workflow changes,
and no `EDITS.md`.

## Risks

- **Migration:** low-to-moderate risk. Three nullable columns and one
partial unique index are added idempotently; existing rows remain valid.
- **Behavior:** low risk while the flag is off because read-time
resolution forces the live default and saved pins are preserved but
inactive.
- **Frozen content:** release snapshots intentionally diverge from
future live skill edits; provenance and hashes make that divergence
explicit and reproducible.
- **UI:** low risk. The picker only renders for the bundled core skill
when the experimental flag is enabled and seeded releases exist.

> This extends the existing Skills Manager / Skill Studio direction
described in `ROADMAP.md`; it does not duplicate another open
implementation PR. The GitHub PR search found no related
`enableBetaSkills` change.

## Model Used

- OpenAI Codex using `gpt-5.5` with reasoning and
terminal/code-execution tools; context-window size is not exposed by
this runtime. Earlier implementation commits also record Claude Opus 4.8
assistance where applicable.

## 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
- [ ] I have not referenced internal/instance-local Paperclip issues or
links (required governance identifiers are included above; no internal
URL is included)
- [ ] My branch name describes the change and contains no internal
Paperclip ticket id (the approved delivery plan mandated this shared
branch name)
- [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-27 19:45:59 -05:00
DottaandPaperclip c111ee4cb3 feat(server): add per-user document stars (#9952)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies and their work.
> - Artifacts and documents are first-class outputs, but users need a
personal way to keep important documents easy to find.
> - Existing resource memberships already model per-user starred
projects and agents with company scoping and activity logging.
> - Documents lacked the equivalent membership model, route, and
artifact filtering behavior.
> - The shared membership contract also needs to remain safe for
existing UI project/agent mutation helpers when documents become a
recognized resource type.
> - This pull request extends the existing resource-membership system
with per-user document stars and a starred artifacts view.
> - The benefit is a company-scoped, idempotent server foundation for a
dedicated starred-documents experience without weakening authorization
or artifact filtering semantics.

## Linked Issues or Issue Description

### Problem / Motivation

Board users cannot star individual documents, and the company artifacts
API cannot return only the current user's starred documents.

### Proposed Solution

Add company/user-scoped document memberships, a board-only document star
route, document membership data in the shared contract, and a
`starred=true` artifacts filter.

### Alternatives Considered

A document column was rejected because stars are per-user; a separate
star API was rejected because projects and agents already use resource
memberships.

### Roadmap Alignment

This extends the existing Artifacts & Work Products roadmap area and
does not duplicate another open pull request found in the repository
search.

## What Changed

- Added the `document_memberships` schema and migration with
company/user/document uniqueness and starred ordering.
- Extended shared resource-membership and artifact-query contracts for
documents and `starred=true`.
- Added company-scoped document star/unstar service and board-only route
behavior with activity logging.
- Added starred document artifact filtering, including user-authored
documents, document kinds, cursor ordering, and incompatible-kind
handling.
- Preserved idempotency under concurrent star requests and synchronized
UI membership defaults/helpers with the expanded contract.
- Added focused shared, route, service, and UI regression coverage.

## Verification

- `pnpm exec vitest run packages/shared/src/resource-memberships.test.ts
server/src/__tests__/company-artifacts-service.test.ts
server/src/__tests__/resource-memberships-routes.test.ts`
- `pnpm exec vitest run ui/src/components/SidebarAgents.test.tsx
ui/src/components/SidebarProjects.test.tsx
ui/src/components/SidebarStarredProjects.test.tsx`
- `pnpm --filter @paperclipai/db check:migrations`
- `pnpm -r typecheck`
- `pnpm test:run`
- `pnpm build`

## Risks

- The migration adds a new membership table and non-concurrent indexes;
migration safety gates pass with the repository's established policy.
- The starred artifacts query intentionally returns only documents and
relaxes the normal agent-authored/system-kind predicates for documents
the current user explicitly starred.
- Document membership mutations remain board-user-only; agent callers
receive no document-star capability.

> 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; runtime model ID and context-window size were not
exposed to this session. Reasoning, repository tool use, code execution,
and test execution were enabled.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-27 19:13:35 -05:00
DottaandPaperclip 3b0156238a docs(connections): cross-reference the identity model (identity vs. connections) (#9953)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Integrations are governed through the Apps v2 "connections"
substrate documented in `doc/connections/`
> - Contributors adding connectors had no written boundary between
*signing a user in* (identity) and *connecting an external resource* (a
connection), so app-store work could drift into merging the two
> - Unwritten, that boundary risks a design where a sign-in provider's
token gets reused as a resource token, or the identity service grows a
connections hub — exactly the failure the separation exists to prevent
> - This pull request adds an "Identity vs. connections" section to the
public connections docs that names the three planes, states the standing
rule verbatim, and aligns naming across surfaces
> - The benefit is that connector implementers inherit the
identity/connection boundary from accessible repository documentation
instead of re-deriving it

## Linked Issues or Issue Description

Docs-only change. No public GitHub issue.

**Problem:** The `doc/connections/` docs describe how to add a connector
(the First-30 matrix and connector playbook) but never state where
identity ends and connections begin. Without an accessible statement of
that boundary, connector work can accidentally blur sign-in tokens and
resource tokens.

**Change:** Adds a public reference section fixing the boundary and
makes it self-contained for contributors without access to private
identity-service implementation documentation.

## What Changed

- `doc/connections/README.md`: adds an **Identity vs. connections**
section with the P1/P2/P3 model, D7 standing rule, rationale, naming
alignment, and canonical-doc cross-reference.
- `doc/connections/FIRST-30-MATRIX.md`: notes that every listed provider
is a plane-P2 connection and links the new section.
- `doc/connections/CONNECTOR-PLAYBOOK.md`: points connector authors to
the boundary and standing rule before implementation.
- Removes inaccessible private-repository documentation links so every
reference in the new public guidance is usable by contributors.

## Verification

- `git diff --check origin/master...HEAD`
- Verified Markdown table column consistency across the three changed
files.
- Verified no private `paperclip-id` URLs or new internal Paperclip
issue references remain in the diff.
- Current-head CI is fully green, including typecheck, build,
server/workspace tests, serialized suites, canary, and both e2e shards.
- Greptile reviewed commit `d964abab50b39a79fef394c0b1855dd1f2e4b92b` at
5/5 with no unresolved findings; its connections-doc validation returned
`RESULT: PASS`.

## Risks

Low risk — documentation only. No code, schema, migration, or runtime
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

- Anthropic Claude Opus 4.8 (`claude-opus-4-8`), 1M context, extended
thinking with tool use, authored the initial documentation change.
- OpenAI Codex CLI (runtime model identifier not exposed to this
session), agentic reasoning with shell and GitHub tooling, performed PR
preparation, rebase, review-loop diagnosis, and the public-link
correction.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-27 19:12:57 -05:00
DottaandPaperclip 1426494ab8 fix(agents): disable cheap model profiles by default (#10019)
## Thinking Path

> - Paperclip is the control plane people use to create and govern
AI-agent companies
> - Agent creation persists runtime configuration that controls which
model profiles future runs may select
> - Adapters can expose a `cheap` profile, and existing creation paths
implicitly left that profile available when operators made no choice
> - That made a newly created agent eligible for a lower-cost model
without an explicit operator opt-in
> - The UI also dropped an explicit opt-in when the operator selected
the adapter's default cheap model rather than a custom model ID
> - Codex additionally hardcoded `gpt-5.3-codex-spark` into its cheap
profile and static fallback model list, making Paperclip choose an
auth-dependent model rather than requiring an operator choice
> - This pull request makes new-agent creation disable an available
cheap profile by default while preserving explicit opt-in from the UI or
API
> - The Codex cheap profile now remains available for explicit
configuration but supplies no model default, so an unconfigured cheap
request stays on the primary model
> - The benefit is predictable model quality for new agents and an
intentional, auditable choice before lower-cost routing is enabled

## Linked Issues or Issue Description

**Problem**

New agents created with an adapter that exposes a `cheap` model profile
can inherit that profile without the operator explicitly enabling it. In
the UI, enabling the adapter-default cheap model is also omitted because
runtime configuration is only written when a custom model ID is present.

**Expected behavior**

- New agents default an available `cheap` model profile to `{ enabled:
false }` when the caller does not specify it.
- Explicit API configuration remains authoritative.
- UI opt-in persists even when the adapter default model is used.
- Codex does not advertise or automatically select
`gpt-5.3-codex-spark`; operators must explicitly configure any
lower-cost Codex model.

**Related public work**

- Refs #4881, which introduced cheap model profiles for local adapters.
- Supersedes the default-selection portions of #8032 and #10004 by
removing the Codex model default instead of replacing it with another
hardcoded model.

## What Changed

- Detect whether the selected adapter exposes a `cheap` model profile
during agent creation and hiring.
- Persist `runtimeConfig.modelProfiles.cheap.enabled = false` only when
the caller did not explicitly configure the profile.
- Preserve UI cheap-profile opt-in when using the adapter's default
model by writing an empty adapter config.
- Remove `gpt-5.3-codex-spark` from the Codex static model list.
- Keep the Codex `cheap` profile explicitly configurable while giving it
an empty adapter config, so Paperclip never chooses a cheap Codex model
automatically.
- Verify that a Codex cheap request without an explicit model leaves the
primary model unchanged.
- Extend server route and UI runtime-config tests for default-disable
and explicit-opt-in behavior.

## Verification

- `env -u PAPERCLIP_IN_WORKTREE -u PAPERCLIP_WORKTREE_NAME -u
PAPERCLIP_CONFIG -u PAPERCLIP_HOME -u PAPERCLIP_INSTANCE_ID -u
PAPERCLIP_CONTEXT pnpm exec vitest run
packages/adapters/codex-local/src/index.test.ts
packages/adapters/codex-local/src/server/codex-args.test.ts
server/src/__tests__/adapter-models.test.ts
server/src/__tests__/adapter-registry.test.ts
server/src/__tests__/heartbeat-model-profile.test.ts
server/src/__tests__/agent-permissions-routes.test.ts
ui/src/lib/new-agent-runtime-config.test.ts`
- Result: 7 test files passed, 105 tests passed.
- GitHub `Typecheck + Release Registry` check passed on the final head.
- `git diff --check public-gh/master...HEAD`

## Risks

- Low behavioral risk: only newly created or hired agents are
normalized; existing agents are unchanged.
- Explicit `cheap` profile settings remain untouched, including explicit
opt-in.
- Codex users who explicitly opt into the cheap lane must choose a
model; requests without a configured override intentionally continue on
the primary model.
- Adapter profile discovery is now awaited during creation, adding a
small amount of adapter metadata lookup work.
- The source branch name is automation-provided and retained as required
by the task, so it does not satisfy the preferred public branch naming
convention.

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

## Model Used

- OpenAI `gpt-5.4` via Codex CLI, with reasoning, repository editing,
terminal execution, and GitHub/Paperclip tool access. The runtime did
not expose a context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [ ] 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-27 19:11:51 -05:00
DottaandPaperclip 71a6535792 docs(execution-semantics): define routable blocking and watchdog restoration (#10094)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies.
> - Execution semantics define when work may stop, how child work
reports upward, and how watchdog recovery proves liveness was restored.
> - The existing docs did not require a routable waiting path before
entering `blocked`, leaving permission-denial and review workflows
vulnerable to dead ends.
> - Child-to-parent reporting and low-trust review delegation also
needed explicit channels and ownership boundaries.
> - Watchdog recovery needed bounded restoration verification rather
than treating a recovery write as proof of restored progress.
> - The security-sensitive defaults were reviewed and approved before
publication.
> - This pull request documents those contracts and synchronizes the
bundled Paperclip skills that operationalize them.
> - The benefit is clearer stop conditions, safer reporting defaults,
and bounded watchdog recovery without sacrificing liveness.

## Linked Issues or Issue Description

- No public GitHub issue exists for this execution-semantics
documentation phase, so the problem and solution are described here in
full.
- Problem: `blocked` could be entered without a routable owner/action
path, review findings could be reported on the wrong issue or treated as
blockers, and watchdog recovery lacked bounded verification of restored
liveness.

## What Changed

- Require a routable waiting path for `blocked` and clarify that
permission denial alone is not a blocker.
- Define canonical child-to-parent completion/report channels,
review-delegation ownership, and the sanctioned courier pattern.
- Specify atomic watchdog recovery batches, fingerprint validation,
bounded restoration attempts, and human escalation.
- Document the low-trust preset default for report comments and align
both bundled Paperclip skills.

## Scope and Sequencing

- This is the contract-first P1 documentation PR. Runtime enforcement is
intentionally excluded and follows in the separately owned
implementation phases; these docs define the acceptance contract those
phases must satisfy.
- The five-file patch is approved and frozen for this PR, so review
findings about absent runtime support are tracked as
implementation-phase requirements rather than edits to this docs-only
change.

## Verification

- `git diff --check origin/master...HEAD`
- Confirmed the PR diff is exactly 5 approved docs/skill files with 91
insertions and 1 deletion.
- Confirmed the patch preserves the approved execution-semantics
contract after replay on latest `origin/master`.

## Risks

- Low implementation risk: documentation and skill guidance only; no
runtime code, schema, migration, dependency, lockfile, or workflow
changes.
- Semantic risk is limited to readers or agents applying the clarified
contracts; the security-sensitive R1a default was approved before
publication.

> 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 underlying model ID and
context-window size are not exposed by this runtime), with reasoning,
terminal tool use, Git/GitHub operations, and code execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced private URLs or internal issue identifiers
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run the applicable docs-only checks locally and they pass
- [x] Tests are not applicable because this is a
docs/skill-guidance-only change
- [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-27 19:10:28 -05:00
DottaandPaperclip 8339bcc7e7 fix(ui): keep decision training under decisions (#10181)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Operators review decisions and turn useful outcomes into training
examples
> - The training library belongs to the Decisions surface, but its
routes and entry point appeared as a separate top-level destination
> - That mismatch made the training icon feel disconnected and left
internal links pointing at legacy `/training` URLs
> - This pull request nests the training library and inspector under
`/decisions/training`, keeps legacy URLs working through redirects, and
uses one route helper everywhere
> - The benefit is a clearer Decisions workflow without breaking
existing bookmarks or links

## Linked Issues or Issue Description

Refs: #9718
Refs: #9779

**Problem:** The Decisions page exposed training as a labeled header
action while the training library lived at the unrelated top-level
`/training` route. Links across the UI duplicated that legacy path.

**Expected behavior:** Training should be an icon action alongside the
other Decisions controls, and training library/record URLs should live
under `/decisions/training` while old URLs continue to redirect.

**Steps to reproduce:**
1. Open the Decisions page.
2. Observe the separate labeled Training button in the page heading.
3. Open a training record and note the top-level `/training/...` URL.

**Version/commit:** Current `master` before this PR.

**Deployment mode:** All UI deployment modes.

## What Changed

- Move the training library and inspector routes under
`/decisions/training`.
- Redirect legacy `/training` and `/training/:id` URLs to the new
locations.
- Add `decisionTrainingHref()` and use it for training links and
navigation.
- Place the Training icon action with the Decisions filter and sort
controls.
- Add focused tests for library and record URL generation.

## Verification

- `pnpm exec vitest run ui/src/lib/decisionTraining.test.ts`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm --filter @paperclipai/ui build`
- `pnpm check:token-gates`

## Risks

- Low risk: the change is limited to client-side routes and navigation.
- Existing `/training` bookmarks remain supported through replacement
redirects.
- No API, database, migration, dependency, 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 using GPT-5.4 with reasoning, repository tool use, shell
execution, and code/test verification.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-27 19:08:36 -05:00
0cf64d36a5 feat(secrets): write through external values and deep-link details (#10196)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies.
> - Its secrets subsystem can resolve external references such as AWS
Secrets Manager values without copying those values into Paperclip
custody.
> - Operators also need to rotate a referenced secret's value while
preserving the same provider reference for consumers inside and outside
Paperclip.
> - Previously, external-reference rotation could only retarget
metadata, and secret detail sheets were driven by local component state
rather than shareable navigation state.
> - This pull request adds an optional provider write capability,
implements AWS Secrets Manager write-through rotation, and exposes
capability-aware rotate modes in the UI.
> - It also makes secret and each-user definition detail sheets
URL-driven and adds a copy-link action.
> - The benefit is that operators can update the canonical external
value safely while keeping AWS rotation tracking intact, and they can
share or navigate directly to secret details.

## Linked Issues or Issue Description

### Subsystem affected

Cross-cutting (`server/`, `ui/`, and `packages/shared`).

### Problem or motivation

External-reference secrets can follow a provider-managed value, but
Paperclip could not write a replacement value back to providers that
support it. Operators had to leave Paperclip, update the value
separately, and then return without an auditable Paperclip rotation
record. Secret detail sheets also could not be shared or restored
through browser history because their selection lived only in component
state.

### Proposed solution

Add an optional `updateExternalSecretValue` provider capability and
surface it as `supportsExternalValueWrites`. Implement AWS writes with
`PutSecretValue` while leaving the resolution `versionId` unset so
future reads continue following `AWSCURRENT`. Add write-value and
retarget modes to the rotate dialog for capable providers. Drive secret
detail selection from `?secret=` / `?definition=` query parameters and
provide a copy-link action.

### Alternatives considered

Converting an external reference into a Paperclip-managed secret would
break consumers that depend on the existing provider reference. Pinning
reads to the newly written AWS version would prevent later out-of-band
rotations from flowing through. Keeping sheet selection only in React
state would not support browser Back or shareable links.

### Roadmap alignment

This extends the completed “Secrets Manager with per-agent access”
roadmap capability; it does not duplicate a separate planned roadmap
item. Public GitHub searches found no duplicate or closely related issue
or PR.

### Additional context

The PR includes focused provider, service, and UI render coverage.
Cutter also generated previews for the deep-linked detail sheet and
capability-aware rotate modes.

## What Changed

- Added optional external-value write support to the secret provider
contract and provider descriptors.
- Implemented AWS Secrets Manager write-through with `PutSecretValue`,
audit material, and compensation when persistence fails after the
provider write.
- Allowed `secretService.rotate()` value updates for external references
while rejecting ambiguous value-plus-retarget combinations and
unsupported providers.
- Added capability-aware “Write new value” and “Change reference” rotate
modes with updated custody and action copy.
- Made secret and each-user definition detail sheets source their
selection from URL query parameters, compose with folder paths, close
through browser history, and expose a copy-link action.
- Added provider, service, and UI render coverage for write-through,
rollback, capability messaging, dialog modes, and deep links.

## Verification

- `pnpm vitest run
server/src/__tests__/aws-secrets-manager-provider.test.ts` — 18 passed.
- `pnpm vitest run server/src/__tests__/secrets-service.test.ts` — 75
passed.
- `pnpm vitest run ui/src/pages/Secrets.render.test.tsx` — 31 passed.
- `pnpm --filter @paperclipai/shared typecheck` — passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm check:token-gates` — passed with all gates clean.

## Risks

- External value writes affect the canonical provider secret and
therefore all consumers of that AWS secret; the UI explicitly labels
this custody behavior.
- A provider write can succeed before Paperclip persistence fails. The
service records the written version and AWS support includes
compensation coverage to restore the prior value where possible;
unrecoverable failures return explicit audit-safe error details.
- URL-driven sheet state changes navigation behavior; render tests cover
deep links, Back/close behavior, and composition with folder query
state.
- No database migration or breaking API requirement is introduced;
providers without the optional capability retain reference-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 using exact model ID `gpt-5.6-sol`, high reasoning mode,
Codex CLI `0.142.5`, with repository, shell, Git, GitHub CLI, and
code-execution tools. The runtime did not expose a context-window size.
- Earlier implementation commits were assisted by Anthropic `Claude
Fable 5` as recorded in their commit trailers; the exact backend model
ID and context-window size were not preserved in the workspace metadata.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes, or
confirmed no documentation change is required
- [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-27 19:08:07 -05:00
DottaandPaperclip ab2bdfeebb feat(routines): activity-gated advanced run policy (editor + run rows) (#10225)
## 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 activity gate (`activity_gate_policy` / `activity_gate_scope`)
lets a scheduled routine skip a tick when nothing has happened since its
last run, so watcher-style routines stay asleep while the system is
settled instead of burning tokens every tick.
> - The scheduler, database columns, and the create/update API for those
fields already landed (see #9438), but there was no way for an operator
to actually set the policy from the routine editor, and the runs list
rendered gated skips as bare "skipped" rows with no "why".
> - This pull request adds the editor control and the run-row labels:
the Delivery section gets an "Advanced run policy" picker plus a scope
selector, and skipped runs explain why they were skipped.
> - The benefit is that the activity gate becomes discoverable and
usable end-to-end from the UI, closing the loop on the feature the API
already supports.

## Linked Issues or Issue Description

- Refs #8534 — activity gate for scheduled routines.
- Builds on #9438 (merged) which exposed the activity-gate create/update
API and the `Routine` response fields this UI reads and writes. This PR
is the editor/UI companion to that API work.

## What Changed

- **Routine editor — Advanced run policy control**
(`ui/src/components/routine-sections/editable-sections.tsx`): the
Delivery section gains a `RadioCardGroup` to choose between *Run on
every scheduled tick* (default) and *Skip when there's been no activity
since the last run*. When gating is enabled, a second scope picker
(*Company-wide* / *This project*) appears. The control is **disabled
with an explanatory hint** — rather than hidden — when the routine has
no schedule trigger, since the gate only affects scheduled ticks
(webhook/manual/API fires are themselves activity and always run). This
keeps the capability discoverable.
- **Edit-draft plumbing**
(`ui/src/components/routine-sections/context.tsx`,
`ui/src/pages/RoutineDetail.tsx`): `activityGatePolicy` /
`activityGateScope` flow through the edit draft, the delivery section's
dirty-field detection, the save payload, and revision restore, matching
how `concurrencyPolicy` / `catchUpPolicy` are handled.
- **Run-history skip reasons** (`ui/src/lib/routine-run-display.ts`):
skipped run rows now render a human-readable "why" —
`no_external_activity` → "Skipped — no activity since last run", plus
labels for `paused` and `worktree_execution_cutoff` — instead of a bare
status.
- Storybook fixture updates for the new routine fields, plus focused
run-display coverage for the skipped-run labels.

## Verification

- `pnpm exec vitest run ui/src/lib/routine-run-display.test.ts` — 11
tests passing.
- `pnpm --filter @paperclipai/ui typecheck` — clean.
- `pnpm check:token-gates` — all token gates clean.
- `pnpm --filter @paperclipai/ui build` — production build succeeds.
- Current-head GitHub CI for `9f9af8ecccfadcdc4a3afab313aafad81cbd1112`
— all checks pass (Storybook visual check skipped by workflow policy).

## Risks

- **Low risk.** UI-only change; no schema/migration and no server
changes (the API and columns already shipped in #9438). Fields are
optional and default to the pre-feature behavior (`always` / `company`),
so existing routines are unaffected. The scope picker only renders when
gating is turned on, and the whole control is inert without a schedule
trigger.

## Model Used

- Claude Opus 4.8 (`claude-opus-4-8`, 1M context), extended thinking,
with tool use (repo edit + shell verification).

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-27 19:05:44 -05:00
DottaandPaperclip f6ab82d490 feat(interactions): add interaction withdrawal and terminal-issue expiry (#10251)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents and boards coordinate through issue-thread interactions
(request_confirmation, ask_user_questions, suggest_tasks, …) that wait
as `pending` cards until someone resolves them
> - Two lifecycle gaps existed: an interaction's creator could not take
back a card it no longer stands behind, and interactions left `pending`
on issues that reached a terminal status lingered forever as
live-looking approval requests
> - Stale pending cards mislead humans (they look actionable), distort
attention/liveness signals, and in the worst case invite acting on a
proposal whose issue is already closed or cancelled
> - This pull request adds an explicit withdraw route for pending
interactions and automatically expires pending interactions when their
issue reaches a terminal status (including a catch-up sweep for issues
closed before this change)
> - The benefit is that interaction cards now faithfully reflect
reality: only genuinely actionable requests stay pending, and creators
can retract requests that events have overtaken

## Linked Issues or Issue Description

Fixes #5787
Refs #7403

Related prior PRs found while searching for duplicates (all overlap
partially; none combine both lifecycle paths or the route-level
authorization used here): #6709 and #7312 (creator-withdraw attempts),
#8169 (terminal expiry), #8081 and #5137 (generalized cancel/expire
endpoints), #6094 (stale confirmation auto-resolve). Related merged
context: #9568 (agent cancel for ask_user_questions), #10119 (tolerating
legacy `withdrawn_by_creator` result outcomes — the reader side of the
outcome this PR writes).

## What Changed

- New route `POST /issues/:id/interactions/:interactionId/withdraw` that
resolves a `pending` interaction to status `withdrawn` with a structured
result (`outcome: "withdrawn"`, optional trimmed `reason`), stamps
`resolvedBy*`/`resolvedAt`, touches the issue, logs activity, and emits
resolved-interaction telemetry
- Withdrawal authorization: board users, the interaction's creator
agent, or the issue's current assignee agent (assignees additionally
pass the standard issue-mutation gate); task-watchdog runs are
explicitly rejected, and authorization-boundary plus low-trust
control-plane checks apply
- Withdrawing an already-resolved interaction returns `409`;
unknown/cross-issue/cross-company interaction ids return `404`
- New service method `expirePendingInteractionsForTerminalIssue`: when
an issue transitions to a terminal status, all of its `pending`
interactions are resolved to `expired` with `outcome: "issue_closed"`,
guarded by a `status = 'pending'` predicate so concurrent resolutions
are not overwritten
- The same expiry runs as a catch-up when interactions are listed on an
already-terminal issue, so cards stranded by issues closed before this
change also get cleaned up; expired request_confirmations are logged
with a distinguishing source
- Shared package: new `withdrawIssueThreadInteractionSchema` validator,
`WithdrawIssueThreadInteraction` type, and `withdrawn` / `issue_closed`
result-outcome support for all interaction kinds (kind-aware result
shapes for `ask_user_questions` and `request_item_verdicts`)
- UI helper `ui/src/lib/issue-thread-interactions.ts` recognizes the new
outcomes for card rendering
- Docs: bundled skill API reference updated with the withdraw endpoint
- Review follow-up: terminal expiry moved from the HTTP route hooks into
`issueService.update`'s status-transition block, so direct service
callers (tree control, recovery, pipelines, status cards) expire pending
cards too; the list-endpoint catch-up remains for issues closed before
this change
- Review follow-up: withdrawing or issue-close-expiring a
`request_confirmation` also settles its linked `tool_action_requests`
row (withdraw -> `cancelled`, issue closed -> `expired`), so a parked
tool call cannot stay approvable after its card is gone
- Review follow-up: interaction cards render dedicated copy for the new
outcomes ("Withdrawn" with the reason, "Expired when issue closed")
instead of falling through to superseded-by-comment / stale-target
variants; withdrawn plan reviews badge as "Withdrawn" rather than
"Changes requested"

## Screenshots

Card states rendered from a local ux-lab harness with mocked data ([full
gallery](https://pages.paperclip.ing/pr-10251-interaction-withdrawal-cards/)):

| Light | Dark |
| --- | --- |
| ![All card states,
light](https://pages.paperclip.ing/pr-10251-interaction-withdrawal-cards/all-light.png)
| ![All card states,
dark](https://pages.paperclip.ing/pr-10251-interaction-withdrawal-cards/all-dark.png)
|

## Verification

- `pnpm --filter @paperclipai/shared build` — clean tsc
- `cd server && npx vitest run
src/__tests__/issue-thread-interaction-routes.test.ts` — 22 tests pass,
including new coverage for: creator-agent withdraw success,
non-creator/non-assignee agent 403, watchdog-run 403, double-withdraw
409, and board-user withdraw
- `cd server && npx vitest run
src/services/issue-thread-interactions.test.ts` — 4 tests pass,
including terminal-issue expiry writing `issue_closed` results and
leaving already-resolved interactions untouched
- `cd ui && pnpm typecheck` — clean
- `cd server && npx vitest run src/__tests__/issues-service.test.ts` —
includes a new embedded-Postgres test proving a direct
`issueService.update` terminal transition expires pending interactions
and writes the activity-log entry
- `cd ui && npx vitest run
src/components/IssueThreadInteractionCard.test.tsx` — 32 tests,
including new coverage for withdrawn / issue-closed confirmation and
question cards
- `cd server && npx tsc --noEmit` — matches the pre-existing repo error
baseline exactly (no new errors)
- Manual: `POST /issues/:id/interactions/:interactionId/withdraw` with
`{"reason":"superseded"}` as the creator agent resolves the card to
`withdrawn`; closing an issue with a pending confirmation flips it to
`expired` with `outcome: "issue_closed"`

## Risks

- Interactions on terminal issues now auto-expire (including
retroactively via the list-time catch-up), so consumers that expected to
resolve a pending interaction on a closed issue will get `409`; this is
the intended semantics and matches how the attention feed already wants
to treat dead cards
- New result outcomes (`withdrawn`, `issue_closed`) are written to
stored results; readers were already made tolerant of these outcome
strings in #10119, so mixed-version reads are safe
- No schema/migration changes; per-row conditional updates (`status =
'pending'`) avoid clobbering concurrent resolutions
- Withdrawal is a new mutation surface, but it is strictly narrower than
existing resolve paths (board, creator, or assignee only; watchdog runs
blocked)

## Model Used

Claude Fable 5 (`claude-fable-5`, Anthropic Mythos-class tier) with
extended thinking and agentic tool use (Claude Code harness); commit
authored in a Paperclip-managed engineering session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [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-27 19:04:46 -05: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>
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>
2026-07-26 10:52:16 -05: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>
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>
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>
2026-07-25 08:29:26 -05: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>
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>
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>
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>
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>
2026-07-24 15:25:59 -05: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>
2026-07-24 14:32:26 -05: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>
2026-07-24 14:06:14 -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
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>
2026-07-24 10:22:07 -05:00
DottaandPaperclip 7f766526a6 feat(sandbox): add task-scoped egress grants (#10155)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Confinement providers protect agent runs with default-deny network
policies
> - Kubernetes environments currently apply only provider-level,
namespace-wide egress allowances
> - Tasks that legitimately need GitHub or package registries therefore
cannot request narrow access, while network failures do not explain the
governing policy or how to request a grant
> - This pull request adds issue-scoped egress grants that become
workload-owned, run-label-selected policies and carries the effective
grant through lease audit metadata
> - The benefit is that internet-dependent work can run without enabling
broad egress for every concurrent task, and denied requests point
operators to the exact grant path

## Linked Issues or Issue Description

No public issue exists. Related but distinct: Refs #9944, which adds a
provider-wide open-internet posture; this PR keeps provider defaults
narrow and adds per-task grants.

**Problem / motivation**
Kubernetes sandbox egress is configured at the provider/tenant level. A
task that needs to clone from GitHub or install from PyPI cannot request
those destinations without changing the policy for every run in the
tenant namespace. DNS/connectivity failures also surface as generic tool
errors with no policy name or remediation path.

**Proposed solution**
Accept `executionWorkspaceSettings.networkEgress.allowFqdns` and
`allowCidrs`, forward the setting through heartbeat environment
acquisition, and create a workload-owned NetworkPolicy or
CiliumNetworkPolicy selected by `paperclip.io/run-id`. Record the
effective grant in lease activity/metadata, expose policy context
through `PAPERCLIP_NETWORK_EGRESS_*`, and append the grant path to
likely policy-related stderr failures.

**Alternatives considered**
A provider-wide open-internet switch is broader than required and is
already covered by #9944. Mutating the existing namespace policy would
leak each task's destinations to other concurrent runs. Standard
Kubernetes NetworkPolicy cannot enforce FQDNs exactly, so standard mode
uses the existing hardened public-IPv4 TCP 80/443 fallback only for the
selected run; Cilium mode remains exact.

**Roadmap alignment**
This extends the existing cloud/sandbox agent roadmap capability with
task-level control-plane policy and does not duplicate a planned roadmap
item.

## What Changed

- Added validated `networkEgress` grants to issue execution workspace
settings and forwarded them through environment lease acquisition.
- Added workload-owned, run-label-scoped
NetworkPolicy/CiliumNetworkPolicy resources for task FQDN/CIDR grants.
- Added lease audit metadata, sandbox policy environment variables, and
actionable network-denial stderr guidance.
- Added focused parser, manifest, policy creation, and denial-message
tests plus Kubernetes provider documentation.

## Verification

- `pnpm -C packages/shared exec vitest run src/validators/issue.test.ts`
— 27 passed.
- `pnpm -C packages/plugins/sandbox-providers/kubernetes test -- --run
test/unit/network-policy.test.ts test/unit/cilium-network-policy.test.ts
test/unit/scoped-network-egress.test.ts` — 21 passed.
- `pnpm -C server exec vitest run
src/__tests__/execution-workspace-policy.test.ts` — 15 passed.
- `pnpm exec vitest run
server/src/__tests__/heartbeat-plugin-environment.test.ts
server/src/__tests__/environment-runtime.test.ts` — 26 passed.
- `pnpm --dir packages/db build && pnpm --dir packages/shared build &&
pnpm --dir packages/plugins/sdk build` — passed, including migration
safety checks.
- `pnpm --dir packages/plugins/sandbox-providers/kubernetes typecheck &&
pnpm --dir server typecheck` — passed after refreshing the worktree's
frozen offline dependencies.
- End-to-end cluster validation of the `build-cython-ext` benchmark
remains for CI/maintainer Kubernetes infrastructure; the focused tests
assert `github.com` and `pypi.org` produce a policy selected only by the
granted run.

## Risks

- Standard NetworkPolicy cannot express FQDNs, so an FQDN grant allows
hardened public IPv4 TCP 80/443 for that run; use Cilium mode for exact
hostname enforcement.
- The new field is additive and absent by default, so existing runs keep
the current provider-level policy.
- Workload owner references garbage-collect scoped policies with the
Job/Sandbox; a cluster/controller that ignores owner references could
temporarily strand a policy that still selects no future run ID.

> 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, 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
- [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 09:58:58 -05:00
e3f8380e70 feat(skills): make summarize-status actions-first (#10117)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Its built-in Summarizer keeps status slots useful for people
overseeing issue trees
> - Those summaries need to tell the reader what they must do now to
unblock progress
> - The existing skill instead imposed rigid Decide:/Review:/Recent
work: sections, cost commentary, and restrictive issue-fetch guidance
> - This pull request rewrites the summarize-status instructions to lead
with 1–3 specific, concrete unblock actions while letting the model use
its judgment for the remaining context
> - The benefit is a shorter, clearer summary that is immediately
actionable without changing slot writes or the streaming status protocol

## Linked Issues or Issue Description

Refs #9713

The built-in summarizer currently prioritizes a fixed reporting template
over the reader's immediate unblock actions. Summaries should instead
open with the 1–3 specific actions the reader needs to take right now,
then provide only the context needed to act. This prompt-only update
preserves all summary-slot mechanics and protocols.

## What Changed

- Rewrote the bundled `summarize-status` skill to open with 1–3
specific, concrete, actionable items needed right now to unblock the
work.
- Removed the rigid Decide:/Review:/Recent work: template, the Cost
discipline section, and the restrictions against fetching issue detail.
- Kept slot-write mechanics and the streaming `STATUS`/sentinel protocol
unchanged.
- Updated all materialized copies and tests for the same skill text: the
`SKILL.md` source, regenerated catalog manifest hashes, compiled
fallback string, summarizer built-in `AGENTS.md` and routine, summary
generation-issue instructions, and the two tests pinning those strings.
- Although the diff touches eight files, every file is either the same
skill text in another materialized form or a test asserting it. No
behavior outside the summarizer's prompt text changes.

## Verification

- `pnpm --filter @paperclipai/skills-catalog test` — 20/20 tests pass.
- `pnpm exec vitest run server/src/__tests__/summary-slots.test.ts
server/src/__tests__/built-in-agents.test.ts` — 46/46 tests pass.
- `git diff --check origin/master...HEAD` — clean.
- `pnpm exec vitest run server/src/__tests__/summary-slots.test.ts` —
16/16 tests pass after the Greptile consistency fix.
- Latest-head GitHub checks — 25 terminal checks, all successful,
neutral, or skipped.

## Risks

- Low risk: this intentionally changes generated summary wording and
prioritization, but does not change APIs, persistence, slot-write
behavior, or the streaming protocol.
- The branch name contains an internal task identifier because it was
pre-created and pre-pushed for this assigned change; the PR title and
body do not expose the internal ticket.

> 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 mode, with
repository, terminal, GitHub CLI, and code-execution tools.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [ ] 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>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-23 15:59:44 -05:00
DottaandPaperclip 148a5b11f5 Route blocked transitions to explicit unblock owners (#10112)
## Thinking Path

> - Paperclip is the open source control plane people use to coordinate
AI-agent companies.
> - Issue status transitions determine whether work keeps moving or
silently stalls.
> - A blocked issue previously could rely on prose alone, leaving the
intended unblock owner unstructured and unnotified.
> - Existing blocker-attention classification could identify stalled
chains, but the signal was not delivered to the board attention feed.
> - Blocked transitions also need rollout-safe deduplication so upgrades
do not notify for historical issues and repeated processing does not
create notification storms.
> - This pull request adds structured unblock descriptors, prospective
transition timestamps, owner delivery, and board attention routing with
focused authorization controls.
> - The benefit is that newly blocked work has an explicit, routable
next action without weakening company boundaries or allowing agents to
inject arbitrary human attention items.

## Linked Issues or Issue Description

Related documentation PR: #10094.

### Subsystem affected

Cross-cutting: `server/`, `packages/db`, and `packages/shared`.

### Problem or motivation

An issue can enter `blocked` without a machine-readable unblock path.
Prose-only ownership does not reliably wake the responsible agent or
surface human-owned work, while the existing `blockerAttention`
classifier is not delivered to an operator-facing attention feed.

### Proposed solution

Require new transitions into `blocked` to have unresolved blockers, a
pending interaction/approval, or a structured `{ owner, action }`
descriptor. Notify an allowed owner once per prospective transition,
route human-owned cases to board attention, and leave pre-rollout
blocked issues untouched.

### Alternatives considered

- Keep prose-only blockers: rejected because ownership remains
unroutable.
- Backfill all historical blocked issues: rejected because upgrades
would create notification storms.
- Let agents target arbitrary users or the board: rejected after
security review because it creates an attention-injection channel.

### Roadmap alignment

Aligns with `ROADMAP.md` → “Enforced Outcomes (watchdogs, recovery
actions, review gates)” by making blocked work carry an explicit
continuation path.

### Additional context

The implementation is prospective-only and deduplicated per blocked
transition. Agent-authored descriptors are limited to the acting agent;
board actors retain human-owner routing.

## What Changed

- Added persisted unblock descriptors and prospective blocked-transition
delivery timestamps with an idempotent migration.
- Added shared types and validation for board, user, and agent unblock
owners.
- Enforced valid blocked transitions and same-company owner validation
in the issue update route.
- Restricted agent-authored descriptors to the acting agent itself,
preventing board/user attention injection by compromised agents.
- Added one-per-transition agent wake delivery and prospective-only
rollout gating.
- Routed human-owned blocker attention into the board attention feed.
- Added focused tests for validation, prospective delivery, flap
deduplication, attention routing, route authorization, and stop-relay
compatibility.

## Verification

- `pnpm -r typecheck`
- `pnpm exec vitest run
server/src/__tests__/issue-agent-mutation-ownership-routes.test.ts
server/src/__tests__/routable-blocked.test.ts
server/src/__tests__/attention-service.test.ts
packages/shared/src/validators/issue.test.ts`
- `AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= pnpm test:run`
- `pnpm build`
- `pnpm --filter @paperclipai/db check:migrations`

## Risks

- Behavioral shift: new `blocked` transitions without a real blocker,
pending governed action, or structured descriptor now return `422`.
- Notification abuse is constrained by same-company validation, agent
self-only routing, prospective rollout gating, and transition-scoped
deduplication.
- Migration risk is low: columns are additive, nullable, and use `IF NOT
EXISTS`; historical blocked issues are not backfilled or notified.

> 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 with GPT-5.4, reasoning-enabled tool use and code
execution. The runtime did not expose a context-window value.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-23 15:49:28 -05:00
DottaandPaperclip a17bee98f2 Allow trust-gated direct-parent issue reports (#10098)
## Thinking Path

> - Paperclip is the control plane used to coordinate and govern
AI-agent companies.
> - Agent issue access must preserve company boundaries and trust-policy
containment without preventing legitimate task coordination.
> - Checked-out standard-trust child runs need a narrow way to report
progress directly to their parent issue, but existing authorization
treated that report like an arbitrary cross-boundary write.
> - Low-trust review runs must remain contained, and stop propagation
must not copy potentially untrusted child prose into a higher-trust
parent context.
> - This pull request adds an audited, one-hop direct-parent comment
grant only for standard checked-out runs and a sanitized, idempotent
relay for blocked or cancelled child stops.
> - The benefit is restored parent/child liveness while retaining least
privilege, complete mediation, and low-trust output quarantine.

## Linked Issues or Issue Description

### What happened?

A standard-trust agent running a checked-out child issue could not post
a progress comment to the direct parent issue because the authorization
boundary treated it as an arbitrary cross-issue write. This could stall
parent/child coordination. Low-trust review runs also need stop
propagation without exposing quarantined child-authored prose.

### Expected behavior

A standard checked-out child run may add a comment only to its direct
parent issue. The grant must not allow grandparent or sibling access,
issue mutation, document writes, reopening, or resuming. Low-trust runs
remain denied unless separately mentioned, while blocked/cancelled stops
relay only sanitized system metadata once.

### Steps to reproduce

1. Create a parent issue and a child issue assigned to different
standard-trust agents.
2. Check out the child issue in a heartbeat run and authenticate as that
run.
3. Post a comment to the parent issue and observe the authorization
denial before this change.
4. Mark a low-trust child blocked or cancelled and observe that no
bounded sanitized parent notification preserves liveness before this
change.

### Paperclip version or commit

Reproduces on `master` before this PR, including base commit
`d36ea13e08`.

### Deployment mode

Local dev (`pnpm dev`).

### Installation method

Built from source (`pnpm dev` / `pnpm build`).

### Agent adapter(s) involved

Not adapter-specific (core authorization and issue-routing behavior).

### Database mode

External Postgres in the focused route regression suite; behavior is
database-mode independent.

### Access context

Agent (bearer API key associated with a checked-out heartbeat run).

### Additional context

The implementation deliberately distinguishes a direct-parent report
decision from general issue mutation permission and records successful
grants in the activity log.

### Privacy checklist

- [x] I have reviewed all pasted output for PII, API keys, tokens,
company names, and private instance references.

## What Changed

- Adds a distinct authorization decision for standard checked-out runs
commenting on their direct parent issue.
- Keeps low-trust direct-parent reports denied unless an existing
explicit mention grant applies.
- Forces direct-parent grants to remain comment-only even when a closed
parent is unassigned or assigned to the reporting agent.
- Audits successful direct-parent report grants in issue activity
details.
- Adds sanitized, parent-scoped, idempotent system comments and parent
wakeups for blocked or cancelled child stops.
- Extends the low-trust red-team route suite for allowed parent reports,
forbidden upward/sibling writes, closed-parent mutation suppression, and
non-laundering stop relays.

## Verification

- `pnpm exec vitest run
server/src/__tests__/low-trust-red-team-routes.test.ts` — 11 tests
passed after the review fix.
- `pnpm --filter @paperclipai/server typecheck` — passed after the
review fix.
- Confirmed the PR changes four files and excludes `pnpm-lock.yaml`,
workflow changes, migrations, and unrelated branch commits.

## Risks

- This is an authorization behavior change. An overly broad grant could
enable cross-boundary writes, while an overly narrow grant could
preserve the liveness failure.
- The implementation constrains the grant to a standard-trust
checked-out run, a direct parent target, and comments only; activity
auditing and red-team coverage make regressions observable.
- Stop relays intentionally contain only system-generated child
identity/status metadata and are deduplicated; child-authored prose is
not copied.
- SecurityEngineer approval is mandatory before merge.

> 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, and test execution. The runtime does not expose the
context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-23 13:03:04 -05:00
DottaandPaperclip 204c416478 fix(release): publish bundled packages with trusted npm staging (#10047)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip publishes its CLI, server, adapters, and shared packages
through automated canary and stable release workflows.
> - `@paperclipai/adapter-utils` bundles the patched `acpx` runtime, so
it must use npm 11 for OIDC trusted publishing.
> - The prior staging directory contained pnpm's `.pnpm` symlink forest,
which crashes npm 11's directory-pack step on GitHub runners and
produces a consumer-broken bundled dependency tree.
> - This pull request rebuilds staged production dependencies as a
physical npm tree, reapplies repository patches, and publishes that
clean directory directly with npm 11 trusted publishing.
> - The benefit is a release path that retains GitHub Actions OIDC
trusted publishing while shipping a working patched acpx runtime to
consumers.

## Linked Issues or Issue Description

Refs: #9980, #10030, #10041

No public GitHub issue exists for this release failure.

### What happened?

Canary and stable publishing began routing `@paperclipai/adapter-utils`
through npm after it declared `bundleDependencies: ["acpx"]`. Publishing
the pnpm-deployed directory with npm 11 crashes during npm's
directory-pack phase on GitHub runners with `Exit handler never
called!`. The same staged shape also produces a broken consumer artifact
because acpx cannot resolve transitive runtime dependencies after
installation.

### Expected behavior

Bundled packages publish directly from a self-contained staging
directory through npm 11 OIDC trusted publishing, and consumers receive
a working patched acpx runtime with its transitive dependencies.

### Steps to reproduce

1. Stage `packages/adapter-utils` using the old `pnpm deploy`-only
shape.
2. Publish that directory with npm 11 on a GitHub runner.
3. npm crashes before registry/OIDC activity while walking the `.pnpm`
symlink forest.
4. Install an artifact packed from that old shape into a fresh npm
project and run acpx; its runtime dependency resolution fails.

### Deployment mode

GitHub Actions canary/stable release workflow.

### Relevant logs or output

```text
npm error Exit handler never called!
```

## What Changed

- After `pnpm deploy`, remove the staged pnpm `node_modules` tree and
run `npm install --omit=dev --ignore-scripts --no-audit --no-fund` to
create a physical hoisted production tree.
- Apply every root `pnpm.patchedDependencies` patch whose package is
declared in the staged package's bundled dependencies, failing staging
if any patch cannot apply.
- Assert the staged acpx runtime contains the required `onAgentStderr`
patch marker.
- Publish the clean staging directory directly with pinned npm 11.18.0,
retaining GitHub Actions OIDC trusted publishing, verbose diagnostics,
and the duplicate-transparency-log retry without provenance.
- Keep pinned npm 10.9.7 packing only for local/dry-run payload
verification; registry publishing does not use a tarball argument.
- Add focused coverage for npm-tree staging, patch application, direct
directory publish arguments, and bundled tlog retries.

## Verification

- `bash -n scripts/release-lib.sh scripts/release.sh`
- `node --test scripts/release-lib.test.mjs
scripts/acpx-patch-packaging.test.mjs` — 12/12 passed.
- `pnpm test:release-registry` — 68/68 passed.
- Real staging smoke: `node scripts/prepare-bundled-package.mjs
packages/adapter-utils <stage>` produced a real `node_modules/acpx`
directory, no `.pnpm` directory, and the `onAgentStderr` patch marker.
- Real npm 11 directory-publish smoke: `npx --yes npm@11.18.0 publish
--dry-run --tag canary --access public --loglevel verbose` packed 26
bundled dependencies and reached the expected existing-version registry
rejection without `Exit handler never called!`.
- The merge-triggered `publish_canary` workflow remains the live OIDC
trusted-publishing verification.

## Risks

- The live GitHub Actions trusted-publishing path can only be fully
proven by the merge-triggered canary run; npm debug-log upload remains
available if it fails.
- Bundling acpx continues to freeze platform-specific transitive
artifacts such as esbuild binaries from the Linux release runner. This
is a pre-existing consequence of the bundling decision in #9980 and is
not expanded here.
- Rebuilding dependencies with npm depends on the exact bundled
dependency versions in the staged manifest; staging fails hard if
repository patches no longer apply.

> 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 harness did not expose a
model context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-22 17:01:11 -05:00
DottaandPaperclip 4e8cd757eb fix(release): add npm publish crash diagnostics (#10041)
## Thinking Path

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

## Linked Issues or Issue Description

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

## What Changed

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

## Verification

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

## Risks

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

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

## Model Used

- OpenAI Codex, GPT-5.3 Codex, tool-enabled coding agent with repository
and shell execution; context window size is not exposed in this
environment.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-22 14:48:54 -05:00
DottaandPaperclip 47c38777d8 fix(release): use trusted publishing npm for bundled packages (#10030)
## Thinking Path

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

## Linked Issues or Issue Description

**What happened**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Deployment mode**

GitHub Actions canary and stable npm release workflows.

Refs #9980.

## What Changed

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

## Verification

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

## Risks

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

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-22 13:19:15 -05:00
DottaandPaperclip d54ff52fc3 test(heartbeat): await execution drain before cleanup (#10023)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents and their work
> - Heartbeat scheduling tests protect the orchestration rules that
serialize an agent's runs
> - The dependency scheduling suite waits for run rows to become
terminal before deleting shared database fixtures
> - A terminal row is persisted before asynchronous execution
finalization and successful-run handoff work fully drain
> - The test then clears process tracking and deletes heartbeat events
while finalization can still append another event
> - This pull request waits for each tracked run's execution promise to
drain before resetting mocks or deleting fixtures
> - The benefit is deterministic cleanup that preserves the production
lifecycle ordering and prevents release CI flakes

## Linked Issues or Issue Description

### What happened?

Release run `29936031931` failed in
`heartbeat-dependency-scheduling.test.ts` while deleting
`heartbeat_runs`. Asynchronous heartbeat finalization inserted a new
`heartbeat_run_events` row after the test had already deleted existing
events, causing the run-row delete to violate the event foreign key.

### Expected behavior

The serialized heartbeat test suite should finish all asynchronous run
execution work before destructive fixture cleanup.

### Steps to reproduce

1. Check out commit `2aef4641b48e88f5ce7e75ce69fbe3bf6bbfc60d`.
2. Run `pnpm exec vitest run --project @paperclipai/server
server/src/__tests__/heartbeat-dependency-scheduling.test.ts
--pool=forks --isolate` repeatedly with PostgreSQL test support enabled.
3. Observe that teardown can delete heartbeat events while execution
finalization is still able to append another event, causing a
foreign-key failure when heartbeat runs are deleted.

### Paperclip version or commit

`2aef4641b48e88f5ce7e75ce69fbe3bf6bbfc60d`

### Deployment mode

Other — GitHub Actions release verification.

### Installation method

Built from source with pnpm.

### Agent adapter(s) involved

Not adapter-specific (core heartbeat test lifecycle).

### Database mode

External PostgreSQL test database.

### Relevant logs or output

`delete from "heartbeat_runs"` failed because the run remained
referenced by `heartbeat_run_events_run_id_heartbeat_runs_id_fk`.

## What Changed

- Collect heartbeat run IDs after queued/running rows settle and await
`heartbeat.waitForRunExecutionDrain()` for each run.
- Reset the adapter mock and clear process tracking only after
asynchronous heartbeat finalization has completed.

## Verification

- Ran `pnpm exec vitest run --project @paperclipai/server
server/src/__tests__/heartbeat-dependency-scheduling.test.ts
--pool=forks --isolate` 10 consecutive times; all 10 runs passed with
6/6 tests.

## Risks

- Low risk: test-only cleanup ordering change using an existing
heartbeat service drain API. Production behavior is 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 with exact model IDs `gpt-5.5` for this heartbeat and
`gpt-5.6-sol` for the recovered initial implementation run; tool-enabled
code inspection, GitHub diagnostics, and shell test execution. Runtime
context-window sizes were not exposed.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-22 11:53:29 -05:00
Dotta 2aef4641b4 docs(release): add v2026.722.0 changelog (#10008)
## Release changelog: Paperclip v2026.722.0

Adds `releases/v2026.722.0.md`, the user-facing stable changelog for the
`v2026.722.0` release, generated per
`.agents/skills/release-changelog/SKILL.md`.

- **Range:** `v2026.720.0..origin/master` — 44 commits from 13
contributors.
- **Version:** confirmed via `scripts/release.sh stable --date
2026-07-22 --print-version` → `2026.722.0`.
- **Breaking changes:** none. Two additive DB migrations (Connections v3
schema core + connection user authorization state); no destructive
migrations.
- **Sections:** Highlights (run-bound agent secret access; Windows
local-agent spawning), Improvements, Experimental (Connections v3
foundation, gated behind the Apps experimental setting), Fixes, Upgrade
Guide, Contributors.

Contributor count/names follow the skill rules (bots and Paperclip
founders excluded from the listed names but counted in the total).

Related issue: PAP-14983.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-22 10:59:11 -05:00
DottaandPaperclip d31a28828b fix(acpx): support Windows agent spawning (#9980)
## Thinking Path

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

## Linked Issues or Issue Description

Fixes #9941.
Refs #9428 and #9771.

**What happened**

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

**Expected behavior**

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

**Steps to reproduce**

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

**Deployment mode**

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

## What Changed

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

## Verification

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

## Risks

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

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-22 10:22:29 -05:00
0b496c9c03 feat(secrets): add run-bound agent secret access (#9921)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies.
> - Agents already receive selected company secrets through `env.*`
bindings at run launch, but environment injection is ambient,
long-lived, and not suitable for every secret consumer.
> - The existing binding and secret-access-event models already provide
company-scoped authorization and per-resolution audit seams.
> - Agents need an explicit way to discover only the secrets granted to
them and fetch a value on demand without exposing the wider company
catalog.
> - That capability must remain run-bound, preserve low-trust token
carve-outs, and make every value read visible in both security and
operator audit trails.
> - This pull request adds an `access.*` delivery namespace, two
run-bound agent routes, dual audit logging, documentation, and an
operator grants editor.
> - The benefit is least-privilege, revocable, auditable secret access
while preserving existing env injection behavior.

## Linked Issues or Issue Description

No pre-existing public issue. Related work:

- Refs #9797 — existing in-sheet agent access UI that this PR extends to
distinguish env and API delivery.
- Refs #9918 — complementary searchable-agent picker improvement for the
same secrets sheet.
- Refs #9530 — related company-wide metadata catalog proposal; this PR
intentionally exposes only the authenticated run's granted aliases and
values.

**Problem / motivation:** Agents can currently consume secrets only
through process environment injection. This keeps values resident for
the run, does not support on-demand consumers, and cannot provide a
discrete operator-visible activity event for each agent-initiated read.

**Proposed solution:** Treat `company_secret_bindings` as the source of
truth for agent secret grants. Keep `env.KEY` as env delivery and add
`access.ALIAS` for API-only delivery; an env binding also implies read
access because the value is already present in the agent process. Add
run-bound list/fetch endpoints that derive scope from the authenticated
heartbeat run and never accept caller-selected overlays.

**Alternatives considered:** A company-wide agent-readable catalog was
rejected for this value path because it increases reconnaissance and
does not prove a per-secret grant. Reusing the ephemeral
environment-probe resolver was rejected because it lacks binding
enforcement. Approval-gated reads and user-scoped secrets remain
deferred beyond v1.

**Roadmap alignment:** This extends the completed **Secrets Manager with
per-agent access** roadmap capability from launch-time env injection to
explicit run-bound API delivery without duplicating a separate planned
initiative.

## What Changed

- Added `access.*` agent binding validation and a dedicated run-bound
resolver that combines `secrets:read` authorization with binding-context
enforcement.
- Added `GET /api/agents/me/secrets` for minimal granted metadata and
`POST /api/agents/me/secrets/:key/value` for on-demand value fetches
with `Cache-Control: no-store`.
- Preserved the existing denials for low-trust review agents,
task-bridge credentials, and skill-test tokens; standard long-lived
agent API keys cannot call the run-bound routes.
- Added dual audit behavior: value attempts write `secret_access_events`
and `activity_log` (`secret.value.read`), while metadata listing writes
the lighter `secret.access.listed` activity event.
- Kept env compatibility: `env.*` remains injected at launch and also
implies API read for the same bound agent; `access.*` never becomes an
environment variable.
- Added the agent-settings **Secret access** editor plus
delivery-mode/alias surfacing on the Secrets page, with focused UI tests
and tokenized layout styles.
- Updated OpenAPI, shared types, agent-facing skill documentation, and
API reference documentation.

### UI Screenshots

P3 produced and reviewed three screenshots using mock data; images are
intentionally not committed to the repository:

- `secret-access-editor.png` — agent settings grant editor.
- `secret-access-light.png` — Secrets-page delivery surfacing in light
mode.
- `secret-access-dark.png` — Secrets-page delivery surfacing in dark
mode.

The source attachments are retained with the implementation task and
linked in the internal handoff; the public page publisher was
unavailable in the PR-prep runtime.

## Verification

- `pnpm exec vitest run
server/src/__tests__/agent-secrets-routes.test.ts
server/src/__tests__/secrets-service.test.ts
server/src/__tests__/secrets-routes.test.ts
ui/src/lib/secret-delivery.test.ts
ui/src/components/AgentSecretAccessEditor.test.tsx` — 5 files, 122 tests
passed.
- Security follow-up: `pnpm exec vitest run
server/src/__tests__/agent-secrets-routes.test.ts
server/src/__tests__/secrets-service.test.ts` — 2 files, 73 tests passed
after active-run and version-consistency fixes.
- Final-head CI: all feature, typecheck, build, e2e, security, and
review gates pass; `General tests (server (1/3))` remains red after one
rerun because unrelated `heartbeat-retry-scheduling.test.ts` cleanup
deletes `heartbeat_runs` before referenced `activity_log` rows.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `pnpm --filter @paperclipai/shared typecheck` — passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm check:token-gates` — feature-local arbitrary-value violations
fixed; command still reports five unchanged `#9627` literals outside
this PR.
- End-to-end QA passed all eight acceptance criteria: grant/list, fetch,
dual audit, env-implies-read, denial matrix, revocation, UI rendering,
and env-injection regression. Evidence:
https://github.com/paperclipai/paperclip/pull/9921#issuecomment-5027455492
- Security review returned PASS-with-required-changes; the
implementation uses the required dedicated binding-enforcing resolver,
run-bound JWT restriction, run-derived overlays, minimal metadata, and a
resolver redaction-registration hook. Evidence:
https://github.com/paperclipai/paperclip/pull/9921#issuecomment-5027455382

## Risks

- A compromised agent can exfiltrate any secret explicitly granted to
it; explicit company-scoped/run-scoped grants, revocation, and audit
reduce but cannot remove that inherent capability risk.
- The resolver invokes a redaction-registration hook before returning
values, but the current route has no persistent cross-request per-run
redaction registry. Paperclip-owned later comments/events therefore
cannot yet guarantee automatic scrubbing of a deliberately copied
fetched value; QA classified this as non-blocking residual hardening.
- Audit-event insertion currently fails open if the security-event
insert itself fails; the operator activity event provides partial
redundancy, but a future hardening change should define fail-closed
behavior for value delivery.
- This PR overlaps `ui/src/pages/Secrets.tsx` with #9918 and may require
a straightforward rebase after that PR moves.

> 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`, with reasoning, repository tool use,
terminal execution, Paperclip API access, and GitHub CLI capabilities.
Context-window size is not exposed by the runtime.
- Anthropic Claude Opus 4.8 with 1M context and tool use assisted with
the UI implementation commit.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 08:04:39 -05:00
5ed0b74b34 fix(runtime): scope PAPERCLIP_ env-binding strip to reserved keys (#9974)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent runs get their environment from user/adapter/project/routine
env bindings resolved by the server heartbeat, plus `PAPERCLIP_*`
runtime vars (identity, wake, workspace, API access) injected by the
harness
> - The heartbeat stripped **every** `PAPERCLIP_`-prefixed binding
before resolution, so legitimately user-named keys (e.g. cloud provider
token bindings like `PAPERCLIP_CLOUD_PROD_PROVIDER_RAILWAY_*`) were
silently dropped and never reached the run env
> - At the same time, several adapters honored an explicitly configured
`PAPERCLIP_API_KEY` over the harness-minted run token, which is exactly
the one key config must never control
> - This pull request replaces the blanket prefix strip with a precise
three-rule policy: never accept `PAPERCLIP_API_KEY` from config, always
let harness-assigned runtime vars win, and let every other
`PAPERCLIP_*`-named user binding flow through
> - The benefit is that user secrets with a `PAPERCLIP_`-style name work
like any other binding, while runtime identity and API credentials stay
fully harness-controlled

## Linked Issues or Issue Description

**Bug description** (no public issue exists):

- **What happened:** Env bindings whose key starts with `PAPERCLIP_`
(e.g. a cloud provider token a user deliberately named
`PAPERCLIP_CLOUD_PROD_PROVIDER_RAILWAY_TOKEN`) were silently stripped by
the server before secret resolution, so the spawned agent never received
them. No error, no access event — the variable just never appeared.
- **Expected behavior:** A user-named `PAPERCLIP_*` binding should reach
the run env unless the harness itself uses that key. Only
`PAPERCLIP_API_KEY` should be categorically rejected, and
harness-assigned runtime vars (`PAPERCLIP_RUN_ID`, `PAPERCLIP_AGENT_ID`,
wake/workspace vars, …) should always win over config.
- **Steps to reproduce:** Configure an agent/project env binding named
`PAPERCLIP_<ANYTHING>` (plain or secret_ref), run a heartbeat, and
inspect the spawned process env — the key is absent.
- **Deployment mode:** local server, any local adapter.

Related prior PRs (different, save-time/API-layer blanket-ban approach;
this PR supersedes that direction with a runtime allow-except-reserved
policy): Refs #8239, Refs #8439.

## What Changed

- `server/src/services/heartbeat.ts`: the pre-resolution strip now
removes only `PAPERCLIP_API_KEY` (hard denylist) instead of every
`PAPERCLIP_`-prefixed binding; other `PAPERCLIP_*` keys flow into
binding resolution. Low-trust inline-sensitive-env checks now also cover
those keys.
- `packages/adapter-utils/src/server-utils.ts`: new
`isForbiddenConfigEnvKey()` helper; the shared
`refreshPaperclipWorkspaceEnvForExecution` merge drops
`PAPERCLIP_API_KEY` from config and keeps harness-assigned `PAPERCLIP_*`
keys authoritative.
- `packages/adapter-utils/src/acpx-engine/execute.ts`: removed the
explicit-`PAPERCLIP_API_KEY`-from-config allowance; the run token
(`authToken`) is now always applied; config `PAPERCLIP_API_KEY` is
ignored.
- All local adapters (`claude-local`, `codex-local`, `cursor-local`,
`gemini-local`, `grok-local`, `opencode-local`, `pi-local`) plus
`cursor-cloud`, `hermes`, and the server `process` adapter: removed
`hasExplicitApiKey`-style allowances so the harness token always wins,
and guarded the remaining unguarded env-merge loops (claude-local inline
loop, process adapter) with the same policy.
- Tests updated/added: heartbeat binding-strip test now asserts the
three-rule policy; adapter-utils merge tests assert the
`PAPERCLIP_API_KEY` ban and `PAPERCLIP_*` pass-through; acpx engine
tests moved credential fixtures to `authToken` and assert config
`PAPERCLIP_API_KEY` is ignored while other `PAPERCLIP_*` config keys
forward and still bust the session fingerprint on rotation.

## Verification

- `pnpm vitest run packages/adapter-utils/src/server-utils.test.ts
packages/adapter-utils/src/acpx-engine/execute.test.ts` — 127 passed
- `pnpm vitest run server/src/__tests__/heartbeat-project-env.test.ts
server/src/__tests__/heartbeat-local-environment.test.ts
server/src/__tests__/claude-local-execute.test.ts
server/src/__tests__/codex-local-execute.test.ts
server/src/__tests__/cursor-local-execute.test.ts
server/src/__tests__/gemini-local-execute.test.ts` — 68 passed
- Adapter package execute suites and the server tests touching API-key
fixtures (`heartbeat-run-log`, `redaction`,
`effective-run-config-fingerprints`, `agent-permissions-routes`) —
green. Three pre-existing sandbox/SSH fixture failures reproduce
identically on clean `master` on this host and are unrelated.
- `pnpm --filter <pkg> typecheck` for server, adapter-utils, and all
nine touched adapter packages — all pass.

## Risks

- Behavioral change: a deployment that relied on configuring a static
`PAPERCLIP_API_KEY` in adapter config env loses that override — by
design; the harness-minted run token is now the only source. When no run
token exists, no API key is injected at all.
- `PAPERCLIP_*`-named user bindings now reach binding resolution and run
envs; a key that collides with a harness runtime var is still discarded
at merge time, so runtime identity/wake/workspace vars cannot be
spoofed.
- Low risk otherwise: no migrations, no API surface changes.

## Model Used

- Claude Fable 5 (`claude-fable-5`, Anthropic Claude 5 family,
Mythos-class tier), extended thinking enabled, agentic tool use (file
edits, shell, test runner) via Claude Agent SDK.

## 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

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 07:01:57 -05:00
DottaandPaperclip cac3c0fa1a feat(connections): add runtime subjects and grants (#9982)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Connections is the subsystem that lets operators connect external
apps and govern which subjects may use those credentials
> - #9958 established the v3 schema foundation and #9981 adds the
AppDefinition catalog layer
> - The runtime still needs subject-aware authorization state, scoped
key handling, and API/OpenAPI routes so connected apps can actually be
granted and used safely
> - This pull request adds the runtime grants/authorization behavior on
top of the catalog branch, while keeping unrelated dependency and
workflow sync commits out of the stack
> - The benefit is a reviewable runtime layer that can land after the
catalog PR, then unblock the wizard and orchestrator cutover work

## Linked Issues or Issue Description

Refs #9958 and #9981.
Refs #9981.

No public GitHub issue exists for this branch. This is the runtime layer
for the Connections v3 stack and is rebased onto `master` after #9981
landed.

## What Changed

- Adds the connection user authorization state migration and schema
wiring.
- Adds shared runtime subject/grant types and validators.
- Adds runtime grant and scoped key behavior in the tool-access service.
- Adds runtime route coverage and registers the routes in OpenAPI.
- Replays only the Connections runtime commits on top of the catalog
branch, dropping unrelated sync/dependency history from the prior closed
runtime PR.

## Verification

- `pnpm run preflight:workspace-links`
- `pnpm exec vitest run
packages/shared/src/validators/tool-access.test.ts
server/src/__tests__/tool-access-service.test.ts`

## Risks

- Medium: runtime grant enforcement is security-sensitive and must fail
closed for unknown key scopes.
- Migration ordering depends on the schema and catalog layers already
merged through #9958 and #9981.
- This PR is rebased and retargeted to `master` with runtime-only
commits.

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

## Model Used

OpenAI GPT-5 Codex coding agent with repository 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>
2026-07-21 16:17:02 -05:00
DottaandPaperclip d23fbf8ae4 feat(connections): add AppDefinition Wave 1 catalog (#9981)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Connections is the subsystem that defines which external apps and
MCP-style integrations operators can browse, configure, and run
> - The v3 schema core in #9958 added stable connection identities, auth
metadata, and grant-aware contracts, but the app catalog still used the
older gallery shape
> - The product needs a richer, typed AppDefinition catalog so browsing
and setup can render provider-specific auth and configuration
requirements consistently
> - This pull request moves the Wave 1 app catalog onto generated
AppDefinition data and carries that shape through shared types, server
lookup paths, and app connection UI
> - The benefit is that follow-up runtime and wizard work can build
against one catalog contract instead of local-only mock/gallery data

## Linked Issues or Issue Description

Refs #9958.

No public GitHub issue exists for this branch. This is the catalog layer
for the Connections v3 stack after the schema-core foundation in #9958.

## What Changed

- Adds generated AppDefinition data for the Wave 1 catalog and ingestion
reporting.
- Replaces the legacy tool app gallery exports with
AppDefinition-centered shared contracts, validators, and tests.
- Updates server tool-access lookup behavior to use the AppDefinition
catalog.
- Updates app connection UI surfaces and tests to consume
AppDefinition-backed catalog data.
- Documents the catalog ingestion workflow in the connector playbook.

## Verification

- `pnpm run preflight:workspace-links`
- `pnpm exec vitest run packages/shared/src/app-definitions.test.ts
packages/shared/src/app-definitions-url.test.ts
ui/src/pages/apps/AppsConnect.test.tsx
server/src/__tests__/tool-access-service.test.ts`

## Risks

- Medium: this changes the catalog contract used by shared, server, and
UI app connection surfaces.
- Catalog data quality matters because generated definitions now drive
browse/setup display.
- Follow-up runtime and wizard PRs must rebase on this branch or on
master after this lands.

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

## Model Used

OpenAI GPT-5 Codex coding agent with repository 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>
2026-07-21 15:57:12 -05:00
DottaandPaperclip 7e00f67138 feat(connections): add v3 schema core (#9958)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies and their governed access to external systems.
> - Connected Apps build on the existing Apps and MCP gateway substrate
so companies can configure reusable, auditable integrations.
> - The current connection record does not yet have a stable public
address, explicit ownership/auth method fields, or subject-specific
credential grants.
> - Without that schema core, later OAuth, per-user authorization, token
brokering, triggers, and connector-service phases cannot enforce tenant
and subject boundaries consistently.
> - This pull request adds the forward-compatible Connections v3 schema
core while preserving the existing connection lifecycle and directly
migrating the remote MCP transport name.
> - The benefit is a company-scoped, least-privilege foundation for
one-click integrations without bypassing Paperclip secrets, profiles,
rules, or audit controls.

## Linked Issues or Issue Description

No matching public issue was found.

**Problem**

Paperclip's current app connections need a durable identity and
authorization substrate before Connected Apps can safely support
multiple setup methods, per-user credentials, provider tenants, and
managed connector services. The existing schema only models a single
connection-level credential set and uses legacy transport terminology.

**Proposed solution**

Add a stable company-scoped connection UID, explicit
ownership/auth/transport fields, a subject-aware `connection_grants`
table, and multi-key credential annotations. Backfill existing
connections and workspace grants in a reversible migration, then update
shared/server/UI contracts to the new `mcp_remote` transport name.

**Related work**

- Related foundation: #9534
- Roadmap: Connected Apps (one-click integrations)

## What Changed

- Added company-scoped connection `uid`, `ownership`, `authKind`, and
canonical transport fields across database, shared contracts,
validators, services, and UI fixtures.
- Added `connection_grants` with workspace/user subject rules, provider
tenant metadata, credential secret refs, revocation state, company
scoping, and uniqueness constraints.
- Added migration `0182_connections_v3_schema_core` to backfill stable
UIDs, rename `remote_http` to `mcp_remote`, infer auth kinds, create
default workspace grants, and support rollback coverage.
- Added multi-key credential annotations and updated gateway/access
services without changing the existing lifecycle behavior.
- Updated the connection glossary, connector playbook, and security
threat model for the new identity, grant, and relay boundaries.
- Added explicit test UIDs to direct database fixtures so the new
non-null invariant is exercised across affected server suites.

## Verification

- `pnpm --filter @paperclipai/shared typecheck`
- `pnpm --filter @paperclipai/db typecheck`
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm exec vitest run server/src/__tests__/tool-access-service.test.ts
server/src/__tests__/tool-gateway-service.test.ts
server/src/__tests__/tool-gateway.test.ts
server/src/__tests__/heartbeat-runtime-skills.test.ts
server/src/__tests__/tool-oauth-legacy-backfill.test.ts
server/src/__tests__/tool-access-policy-service.test.ts
server/src/__tests__/heartbeat-runtime-mcp-servers.test.ts
packages/db/src/connections-v3-schema-core-migration.test.ts
packages/shared/src/validators/tool-access.test.ts --config
vitest.config.ts` — 9 files, 218 tests passed.
- Latest-head GitHub Actions: build, typecheck, general/serialized
suites, backup/worktree restore coverage, both e2e shards, canary,
policy, and security scans pass.
- Greptile: 5/5 with zero unresolved threads.
- `pnpm check:token-gates` remains red only on five pre-existing `#9627`
color literals outside this change.

## Risks

- **Migration risk:** UID backfill and default-grant creation touch
every existing connection. The migration uses company-scoped uniqueness,
deterministic legacy UIDs with ID suffixes, and seeded up/rollback
coverage.
- **Authorization risk:** Grant rows carry credential references.
Constraints enforce workspace-vs-user subject shape, company/connection
lookup indexes, one default grant per connection, and one user grant per
connection/subject. Security review is requested specifically for this
design.
- **Compatibility risk:** `remote_http` is renamed directly to
`mcp_remote`; all repository call sites and fixtures are updated in the
same change.
- **Future-phase risk:** Subject-bound token issuance, triggers, and
connector-service relay verification remain fail-closed requirements
documented for later phases; this PR does not expose those capabilities.

> 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. The runtime did not expose an exact
underlying model ID or context-window size; capabilities used include
repository inspection, code editing, shell execution, test execution,
Git/GitHub CLI operations, and structured reasoning.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-21 15:16:26 -05:00
DottaandPaperclip 53d6297f75 fix(ui): simplify external object labels and star controls (#9929)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents and their work
> - Operators rely on task detail properties and header actions to scan
linked resources and make quick decisions
> - External GitHub objects used a long pull-request label and repeated
mention counts that added visual noise without adding state
> - The task-detail star action also rendered as a labelled outline
button, unlike the compact star controls used elsewhere
> - These inconsistencies made dense task-detail surfaces slower to scan
and broke Paperclip's content-first visual language
> - This pull request shortens the GitHub pull-request label, removes
duplicate mention-count decoration, and aligns the detail star action
with the icon-only control pattern
> - The benefit is a calmer, more consistent task-detail experience with
accessible labels preserved for assistive technology

## Linked Issues or Issue Description

No matching public GitHub issue or open pull request was found.

**What happened?**

On the task detail surface, linked GitHub pull requests were labelled
`Github Pull Request` and could show a repeated `×N` mention count. The
detail-header star control used a labelled outline button rather than
the compact icon-only star pattern.

**Expected behavior**

Linked pull requests should use the concise `Github PR` label without
duplicate mention-count decoration, and the detail star action should
render as an accessible icon-only ghost button consistent with
neighboring controls.

**Steps to reproduce**

1. Open a task with a linked GitHub pull request mentioned more than
once.
2. Inspect the external-object property label and value row.
3. Inspect the star action in the task detail header.

**Paperclip version or commit:** `230126d80b` (`master` at preparation
time)

**Deployment / installation:** Local development, built from source.

**Scope:** Core UI; not adapter-specific, database-related, or
configuration-related.

## What Changed

- Render GitHub pull-request property labels as `Github PR`.
- Remove repeated external-object mention-count decoration from property
values.
- Render detail-header star controls as icon-only ghost buttons while
preserving `aria-label`, pressed, busy, error, and tooltip states.
- Expand component coverage for concise labels, duplicate-count
suppression, visual variants, and accessible star actions.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/IssueProperties.test.tsx
src/components/StarToggle.test.tsx` — 54 tests passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- Visual review (before/after plus normal, starred, pending, and error
states):
https://htmlpreview.github.io/?https://gist.githubusercontent.com/cryppadotta/9688862a8826c1134aa2b2e8c16509d8/raw/45cb4921851f8968b21e7490e0d705161a9e165d/star-toggle-review.html
- `pnpm check:token-gates` — reports five existing `#9627` violations in
files unchanged by this PR; the same values are present on `master`.

## Risks

- Low risk: changes are limited to task-detail presentation and tests.
- The star action remains fully accessible through its existing ARIA
label and tooltip, but it no longer displays visible text.
- External-object mention counts remain available in data; only the
redundant property-row decoration is removed.

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

## Model Used

- OpenAI Codex, GPT-5.3 Codex, tool-enabled coding agent with repository
and shell access.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-21 09:14:29 -05:00
DottaandPaperclip 59eee4829c fix(inbox): stop archived items from resurfacing (#9931)
## Thinking Path

> - Paperclip is the control plane operators use to coordinate AI-agent
companies and review work needing attention.
> - The Inbox is the operator-facing surface that aggregates tasks
requiring attention across server state and shared client polling.
> - Archiving a task optimistically removed it, but ordinary background
activity and stale polling responses could make it reappear seconds
later.
> - The server therefore needs to distinguish genuine user-attention
events from routine agent/system activity.
> - The client also needs a bounded local archive guard across every
Inbox query path while the server mutation and in-flight polls settle.
> - This pull request fixes both resurrection paths and adds
race-focused regression coverage.
> - The benefit is stable archive behavior without hiding a genuine
archive failure after reconciliation or reload.

## Linked Issues or Issue Description

### Pre-submission checklist

- [x] Searched existing open and closed issues and pull requests; no
duplicate implementation was found.
- [x] Reproduced on `master` before this branch.
- [x] Confirmed this is a Paperclip core bug, not adapter or provider
behavior.

### What happened?

Archiving an Inbox task hid it optimistically, then background refresh
activity could insert it back into the list seconds later.

### Expected behavior

A successfully archived task remains hidden during normal polling. A
genuine failed archive may become visible again after reconciliation or
reload.

### Steps to reproduce

1. Open Inbox with a visible task.
2. Archive the task.
3. Wait for shared polling or routine agent activity to refresh task
data.
4. Observe the archived task reappear without a hard page refresh.

### Paperclip version or commit

`master` before this branch.

### Deployment mode

Built from source using the local development application.

### Installation method

Built from source (`pnpm`).

### Agent adapter(s) involved

Not adapter-specific; this is a core Inbox bug.

### Database mode

Not database-mode-specific.

### Access context

Board (human operator).

### Additional context

The failure had independent server and client causes: routine activity
could resurface archived rows server-side, while stale shared-poll
responses could bypass optimistic client removal.

## What Changed

- Restrict server-side Inbox resurfacing to explicit user-attention
events rather than any issue activity write.
- Add a bounded client-side archive guard with confirmation, failure
restoration, and cache reconciliation behavior.
- Apply the guard to Inbox rendering, badge counts, optimistic cache
updates, and shared-poll result application.
- Classify the generic compact Inbox query so stale shared-poll data
cannot bypass the guard.
- Add server visibility-matrix tests and UI race-condition regression
tests.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/hooks/useSharedPolling.test.ts src/lib/inboxArchiveCache.test.ts
src/pages/Inbox.test.tsx` — 25 passed.
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/issues-service.test.ts` — 107 passed.
- Branch rebased cleanly onto current `origin/master` before push.

## Risks

- Low-to-moderate behavioral risk: resurfacing is intentionally
narrower, so the server tests cover human comments, mentions,
interactions, and status transitions that must still regain attention.
- The client guard is bounded and cleared on mutation failure, limiting
the risk of hiding a task whose archive did not persist.
- No schema, migration, public API, workflow, dependency-lock, or
visual-token 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

- Anthropic Claude via Claude Code (`claude_local`; prior
implementation/review run, exact underlying model ID and context window
were not retained in the handoff metadata), with repository tool use and
test execution.
- OpenAI `gpt-5.5` via Codex CLI for final review repair and PR
preparation, with reasoning, repository editing, GitHub tooling, and
code execution.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and
linked/described the result above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change and contains no internal
Paperclip task identifier
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation where needed; no
documentation change is required for this bug fix
- [x] I have considered and documented risks above
- [x] All Paperclip-authored commits include the required co-author
trailer

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-21 08:13:14 -05:00
DottaandPaperclip 26890650b2 test(ui): cover secret creation within folders (#9927)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Secrets UI lets operators navigate slash-delimited secret names
as folders
> - PR #9913 shipped create-in-folder behavior for company and per-user
secrets
> - The production behavior is already on master, but several
create-in-folder interaction paths lack retained regression coverage
there
> - Without that coverage, prefix composition, derived keys, prefix
removal, and staged empty folders could regress unnoticed
> - This pull request adds focused render tests without changing
production behavior
> - The benefit is safer maintenance of the folder-based secrets
workflow with a small, reviewable patch

## Linked Issues or Issue Description

- Refs #9913

## What Changed

- Added render coverage for creating a company secret from a folder and
deriving its key from the full slash-delimited name.
- Added coverage for per-user secret prefixes and exposing the full name
when the prefix chip is removed.
- Added coverage for inline folder-name validation and URL-backed
staging of an empty folder.

## Verification

- `env -u PAPERCLIP_IN_WORKTREE -u PAPERCLIP_WORKTREE_NAME -u
PAPERCLIP_CONFIG -u PAPERCLIP_HOME -u PAPERCLIP_INSTANCE_ID -u
PAPERCLIP_CONTEXT pnpm exec vitest run
ui/src/pages/Secrets.render.test.tsx` — 29 tests passed.
- `pnpm check:token-gates` — reports five existing `#9627` literals in
unrelated files; this PR changes no token-gated component code and
introduces no new violation.

## Risks

- Low risk: test-only change with no production, API, schema, migration,
dependency, or runtime behavior changes.
- The tests exercise existing DOM interactions and may need updates if
the Secrets creation UI copy or controls intentionally change.

> 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 managed coding agent with repository inspection, code
execution, Git/GitHub, and Paperclip API tools. The managed harness does
not expose the exact underlying model ID or 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)
- [ ] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
— the assigned execution branch name is fixed by the task
- [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
documentation change is needed for test-only coverage
- [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-21 08:08:55 -05:00
DottaandPaperclip 37d84700fa docs: refresh Star History badge and chart (#9945)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The README is the first project surface most prospective users and
contributors see
> - The existing Star History presentation only showed one static chart
at the bottom of the page
> - The project also lacked the compact Star History Rank badge
alongside its other top-level badges
> - The chart should respect the reader's light or dark color scheme
while preserving the existing history link
> - This pull request adds the rank badge and replaces the chart with
responsive light/dark sources
> - The benefit is a more useful, theme-aware project-growth snapshot in
both prominent README locations

## Linked Issues or Issue Description

No public GitHub issue exists for this documentation request.

- **Problem / motivation:** The README's Star History presentation is
less visible than the other project badges and its chart does not adapt
to light and dark themes.
- **Proposed solution:** Add Star History's rank badge to the centered
badge row and use the provider's responsive `<picture>` markup for the
chart section.
- **Alternatives considered:** Keeping the current single static chart
would avoid markup changes but would not provide theme-aware rendering
or the requested rank badge.
- **Roadmap alignment:** Documentation-only presentation change; it does
not add or duplicate a product roadmap item.
- **Related PR:** #9922 refreshed the surrounding README roadmap content
before this focused follow-up.

## What Changed

- Added the Star History Rank badge to the README's centered badge row.
- Replaced the single Star History image with light- and dark-theme
chart sources using the supplied sealed chart URL.
- Preserved the existing Star History destination and accessible chart
label.

## Verification

- `git diff --check`
- Confirmed the badge, light chart, and dark chart endpoints each return
HTTP 200.
- Rendered the updated section through GitHub's GFM API and confirmed
GitHub preserves the linked `<picture>` and both theme sources.
- Confirmed the diff contains only `README.md`.

## Risks

- Low risk: documentation-only change with no runtime, API, dependency,
or migration impact.
- The chart depends on Star History's hosted badge/chart endpoints and
supplied sealed token remaining available.

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

## Model Used

- OpenAI `gpt-5.4` via Codex CLI; context-window size not exposed by the
runtime; medium reasoning with repository, shell, GitHub API, and live
HTTP verification tools.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-21 07:09:01 -05:00
DottaandPaperclip b9f4073a13 fix(ui): use searchable agent picker for secret access (#9918)
## Thinking Path

> - Paperclip is the control plane people use to manage AI-agent
companies.
> - Operators need to grant secrets to specific agents safely and
efficiently.
> - The secrets access sheet previously used a native select while
similar agent-assignment surfaces use a searchable picker.
> - That inconsistency makes finding an agent slow and error-prone as
companies grow.
> - This pull request reuses the shared agent picker behavior for
single-agent secret access grants.
> - The benefit is a consistent, searchable selection experience without
changing secret-access semantics.

## Linked Issues or Issue Description

Refs #9797

**Problem / motivation:** The in-sheet agent access form introduced in
#9797 renders every grantable agent in a native select. In companies
with many agents, operators cannot filter by name or title and the
experience differs from other agent-selection surfaces.

**Proposed solution:** Add a single-select variant beside the existing
`AgentMultiSelect`, then use it in the secret access grant form.

**Alternatives considered:** Keeping a native select would preserve less
code but would not scale or align with existing searchable agent
selection.

**Roadmap alignment:** This is a focused usability fix for an existing
core control-plane surface and does not overlap an unstarted roadmap
initiative.

## What Changed

- Added `AgentSelect`, a searchable single-agent popover that filters by
agent name and title.
- Replaced the secret access form's native select with the shared
searchable picker.
- Added focused coverage for filtering, selecting, callback behavior,
and popover closure.

## Verification

- `pnpm exec vitest run ui/src/components/AgentMultiSelect.test.tsx` —
passes (3 tests).
- `pnpm --filter @paperclipai/ui typecheck` — passes.
- `pnpm check:token-gates` — branch adds no violations; the command
currently fails on five unchanged `#9627` literals already present on
`master`.
- Manual: open Secrets, choose a secret, add agent access, filter by
agent name or title, select the result, and grant access.

## Risks

- Low risk: the change is limited to agent selection UI and preserves
the existing grant request payload.
- The new picker depends on the existing popover/input primitives and
resets its filter when closed.

> 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-series coding agent (exact runtime model ID and
context-window size are not exposed), with reasoning, repository tool
use, terminal execution, and GitHub CLI 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>
2026-07-20 18:00:34 -05:00
DottaandPaperclip 631cca509d docs: refresh README roadmap and four pillars (#9922)
## Thinking Path

> - Paperclip is the open source control plane people use to organize
and govern companies of AI agents
> - The README is the project’s front door, while `ROADMAP.md` is the
detailed statement of shipped and planned product direction
> - The existing README roadmap had fallen behind capabilities that are
already available and did not explain the product’s organizing model
> - That drift made current features look unfinished and left the
relationship between tasks, organization, training, and infrastructure
implicit
> - This pull request synchronizes the roadmap preview with the detailed
roadmap and introduces the four-pillar product framing
> - The benefit is a more accurate, coherent first impression for users
and contributors, with theme-aware visuals that render correctly on
GitHub

## Linked Issues or Issue Description

- **Subsystem affected:** Documentation (`README.md`, `ROADMAP.md`, and
documentation assets); no runtime subsystem changes.
- **Problem or motivation:** The README roadmap understated shipped
capabilities, the detailed roadmap had corresponding stale statuses, and
the README did not clearly explain the four product pillars that connect
Paperclip’s task, organization, training, and infrastructure surfaces.
- **Proposed solution:** Refresh both roadmap views from one ordered
list, add the four-pillars section and light/dark graphic, and keep
future capabilities explicitly marked as planned or partial.
- **Alternatives considered:** Updating only `ROADMAP.md` would leave
the project’s front page stale; updating only the README would create a
second source of truth; a single non-theme-aware image would be less
legible for half of GitHub’s color schemes.
- **Roadmap alignment:** This change directly updates `ROADMAP.md` and
its README preview rather than introducing an unplanned runtime feature.
- **Additional context:** Searched open pull requests for related README
roadmap/four-pillars work and found no duplicate.

## What Changed

- Added a **The four pillars** section covering Agentic Task Manager,
Org Chart for Agents, Agent Employee Training, and Agentic OS, with a
theme-aware `<picture>` graphic.
- Flipped four roadmap entries from ⚪ to ✅: Cloud / Sandbox agents,
Artifacts & Work Products, Deep Planning, and Enforced Outcomes.
- Added shipped ✅ entries for MCP Tool Gateway & Apps, per-agent Secrets
Manager access, activity logging and action attribution, self-healing
recovery, and agent evals/feedback; expanded the skills entry to include
Skill Studio and Skills Store.
- Added planned ⚪ entries for Bring-your-own-ticket-system and Connected
Apps, resolving the README FAQ inconsistency around external ticket
systems.
- Moved Cloud deployments to 🟡 and documented the shipped multi-tenant
isolation, local-to-cloud sync, and cloud-managed bootstrap scope.
- Synchronized the README preview and `ROADMAP.md` ordering/statuses: 18
✅, 9 ⚪, and 1 🟡 entry.

## Verification

- `git diff --check origin/master...HEAD`
- Focused Node consistency check confirms README and `ROADMAP.md` have
the same 28 ordered entries/statuses and expected 18 ✅ / 9 ⚪ / 1 🟡
counts.
- `file doc/assets/four-pillars-light.png
doc/assets/four-pillars-dark.png` confirms both assets are valid
3840×2160 RGB PNGs.
- Visual QA rendered the README through GitHub’s GFM API in Chromium at
GitHub content width under both light and dark `prefers-color-scheme`
modes; the correct graphic swapped per theme, all links resolved, the
section placement/table were correct, and `ROADMAP.md` matched the
README preview.

### Visual Evidence

**Light theme**

![Rendered README four-pillars section in light
theme](https://raw.githubusercontent.com/paperclipai/paperclip/pr-evidence-9922/pr-evidence/9922/light-pillars.png)

**Dark theme**

![Rendered README four-pillars section in dark
theme](https://raw.githubusercontent.com/paperclipai/paperclip/pr-evidence-9922/pr-evidence/9922/dark-pillars.png)
- Prettier was not run because this repository does not expose a
configured `prettier` binary; markdown whitespace was checked with `git
diff --check` and the rendered QA above.

## Risks

- Low risk: documentation and image assets only; no application code,
API contract, schema, dependencies, lockfile, or workflow changes.
- Roadmap status wording can become stale as product work evolves, so
future shipped capabilities should update both the README preview and
`ROADMAP.md` together.

> 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`, with reasoning,
terminal/tool use, GitHub API access, and Paperclip control-plane
integration. The model context-window size was not exposed by this
execution environment.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-20 18:00:12 -05:00
b94907f8af feat(ui): navigate slash-named secrets as folders (#9913)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Operators store company and user secrets under human-readable names
> - Slash-delimited names already express useful hierarchy, but the
Secrets page previously rendered them as one flat list
> - Large secret collections therefore became harder to scan, navigate,
and create within consistently named groups
> - A client-derived folder model preserves the existing server contract
while making those names navigable
> - This pull request adds folder browsing, URL-addressable paths,
global search, and create-in-folder behavior without adding folder
records
> - The benefit is a more scalable secrets workflow with no migration or
API compatibility risk

## Linked Issues or Issue Description

Slash-delimited secret names such as `dev/github/oauth/clientid`
currently appear as raw flat rows. This change treats name prefixes as
client-side navigation folders on the main Secrets tab while leaving
stored names, API contracts, validation, and the database unchanged.

- Wireframes and interaction specification:
https://pages.paperclip.ing/pap-14698-secrets-folders/
- Folder paths are derived only from secret names; there is no
server-side folder entity or data-model change.

## What Changed

- Added pure secret-path utilities for normalized segments, breadcrumbs,
nested folder listings, counts, and leaf/path rendering.
- Added a Folders/Flat view to the main Secrets tab with folder-first
sorting, breadcrumbs, empty-folder states, filters, and global search
results.
- Added URL navigation through `?path=<normalized/path>` so deep links,
reload, browser Back, and new-tab folder navigation work.
- Persisted the preferred view in `localStorage` under
`paperclip.secrets.viewMode`; an explicit `?path=` deep link takes
precedence for that visit.
- Added create-in-folder behavior with a removable prefix chip, staged
New folder paths, inline segment validation, and full-name key
derivation.
- Kept My secrets flat while rendering slash-delimited names with muted
paths and emphasized leaves.
- Added unit/render coverage for path helpers, folder navigation, and
create-in-folder behavior.

## Verification

- `pnpm exec vitest run ui/src/pages/secrets/secret-path.test.ts
ui/src/pages/Secrets.render.test.tsx` — 35 tests passed.
- `pnpm -r typecheck` — passed.
- `pnpm test:run` — server suite passed 2,707 tests and UI suite passed
3,022 tests; one unrelated CLI doctor test was environment-sensitive
because this agent inherited AWS variables.
- `env -u AWS_PROFILE -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY -u
AWS_SESSION_TOKEN -u AWS_REGION -u AWS_DEFAULT_REGION pnpm exec vitest
run cli/src/__tests__/secrets.test.ts` — 8 tests passed.
- `pnpm build` — passed.
- `pnpm check:token-gates` — feature files are clean; the command
reports five existing `#9627` color literals outside this diff.

## Risks

- Low data risk: folders are derived client-side from existing names,
with no schema, migration, API, or stored-name changes.
- URL behavior changes only the main Secrets tab and uses the additive
`?path=` contract.
- View preference is browser-local and scoped to the
`paperclip.secrets.viewMode` key.
- Renaming or deleting the last secret under an open prefix
intentionally leaves the user on an empty-folder state instead of
redirecting.
- “Move to folder…” bulk prefix rename remains deferred because it is a
multi-secret mutation with separate conflict and partial-failure
semantics.

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

## Model Used

- OpenAI `gpt-5.5` via Codex CLI for PR preparation, verification,
GitHub/Paperclip tool use, and codebase analysis; the managed harness
does not expose the active context-window size.
- Anthropic Claude Opus 4.8 (1M context) and Claude Fable 5 assisted
earlier implementation/design commits, as recorded in their commit
trailers; both used repository and code-editing tools.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [ ] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
— the assigned shared execution branch name is fixed for this work
- [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>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-20 16:11:35 -05:00
DottaandClaude Opus 4.8 903bd157c2 docs(release): v2026.720.0 changelog (#9903)
Release changelog for **v2026.720.0** (released 2026-07-20). Supersedes
#9612 (the 7/15 draft — that cut was never released, no `v2026.715.0`
tag exists).

Range is the full `v2026.707.0..master` — **195 commits from 16
contributors**.

## New since the 7/15 draft
- **Decision Training** — library + inspector, snapshot foundation,
decision image galleries
- **Built-in Summarizer & summary slots**
- **Skill organization** — nested folders, "My Skills",
import-from-project, open-by-default company skill policy (alongside
Skill Studio)
- **Issue monitor visibility** across task surfaces + issue properties
- **Reworked secrets dialog** with in-sheet per-agent access
- **Active PR-gardening workflow**
- Recovery / hot-restart / codex-auth reliability fixes and inbox/list
polish

No `BREAKING:` signals — DB migrations are additive and run
automatically (captured in the Upgrade Guide).

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 11:29:33 -05:00
f12bb27bcd feat: make issue monitors visible across task surfaces (#9783)
## Thinking Path

> - Paperclip is the open source control plane people use to supervise
AI-agent companies.
> - Operators need task execution state to be visible where they read,
reply to, and manage an issue.
> - Scheduled monitor state was easy to miss because it lived in a
description-area card and used inconsistent, mostly static time copy.
> - The task page, composer, retry card, and properties panel therefore
needed one shared monitor-state and countdown language.
> - This pull request adds shared live-ticking time utilities, moves
monitor status into a top-of-page banner and composer strip, and
redesigns the properties row with complete read-only details.
> - The benefit is that operators can immediately understand when an
agent resumes, why it is waiting, and how to act without hunting across
the page.

## Linked Issues or Issue Description

Issue monitors can schedule a future agent check, retry, or wake, but
the UI did not present that state consistently or prominently. The
existing description-area activity card competed with issue content, the
composer did not explain that replying wakes the agent early, compact
properties copy truncated important details, and relative times did not
share a live two-unit formatter.

This change makes scheduled monitor state visible and consistent across
the issue header, reply composer, properties panel, and scheduled-retry
card. Related prior server-side recovery visibility work: #9629
(distinct scope).

## What Changed

- Added shared two-unit monitor ETA/offset formatters and a live-ticking
countdown hook, including compact absolute-time rules for Today,
weekday, and cross-year dates.
- Replaced the description-area monitor activity card with a top-of-page
status banner and added an inline composer strip that explains replies
wake the agent before the scheduled check.
- Redesigned the properties Monitor row as readable two-line copy with
attempt state, due/overdue/cleared wording, click-to-edit behavior, and
a hover/tap details tooltip.
- Adopted the shared two-unit formatting in the scheduled-retry card and
added focused coverage for monitor formatting, state transitions,
visibility, and controls.
- Added the approved wireframe package and published reference:
https://pages.paperclip.ing/pap-14557-monitor-visibility/

## Verification

- `pnpm vitest run ui/src/lib/issue-monitor.test.tsx
ui/src/components/IssueMonitorBanner.test.tsx
ui/src/components/IssueProperties.test.tsx` — 3 files, 74 tests passed.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed with existing Vite optimization/chunk-size
warnings.
- UX review approved the rendered real components across desktop/mobile,
light/dark, and the scheduled/retrying/due/overdue/cleared/none state
matrix.
- QA passed 6/6 criteria in Chromium, including a live countdown
transition without refresh. Review evidence included the P2 banner
state-matrix screenshot and the P3 properties-row and details-tooltip
screenshots, plus a dark-mode capture.
- `pnpm check:token-gates` currently reports five pre-existing `#9627`
comment literals on `origin/master`; this branch introduces none of
those literals or any new token violation.

## Risks

- Low-to-moderate UI behavior risk: monitor copy and placement change
across several issue surfaces, but all derive from one shared state
builder and focused tests cover the state matrix.
- Countdown rendering wakes once per minute while a visible monitor is
scheduled; the hook is limited to active monitor surfaces and stops when
hidden.
- No database, API contract, migration, telemetry, or authorization
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.6-sol`; context-window metadata was unavailable
in this runtime; reasoning, repository tool use, command execution, and
test execution enabled. Earlier implementation commits were assisted by
Claude Fable 5 and Claude Opus 4.8 (1M context), as credited in their
commit trailers.

## Checklist

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-18 14:39:37 -05:00
67616dd7ea Rework secrets dialog and add in-sheet agent access (#9797)
## Thinking Path

> - Paperclip is the open source control plane people use to manage AI
agents and the credentials those agents need for work.
> - The secrets UI is responsible for making credential creation
understandable and for showing where credentials are used.
> - The create flow previously exposed an editable generated key too
early, used an unnatural field order, and rendered uneven provider tab
rows.
> - The detail sheet also lacked an in-context way to see and manage
which agents reference a selected secret.
> - This pull request makes the create dialog follow a predictable
name-to-value flow and adds agent access management directly to the
secret details sheet.
> - The benefit is a clearer secrets workflow with fewer accidental key
edits and less navigation when granting or revoking agent access.

## Linked Issues or Issue Description

**Subsystem affected:** `ui/` — React + Vite board UI

**Problem or motivation:** Creating a secret currently makes its
generated key look immediately editable, places fields in an awkward
keyboard order, and applies provider-tab overrides that produce uneven
rows. After creation, operators cannot inspect or change agent access
from the selected secret's detail sheet.

**Proposed solution:** Generate the key from the path-style name and
keep it read-only until an explicit Edit action; place Value directly
after Name; use the standard tab sizing; and add an Agent access section
that reads and updates `secret_ref` / `user_secret_ref` environment
bindings through agent adapter configuration.

**Alternatives considered:** Keeping access management only on agent
configuration screens was rejected because it hides a secret-centric
question—“which agents can use this?”—and requires repetitive
navigation. Keeping the key always editable was rejected because the
generated value should be the safe default.

**Roadmap alignment:** No matching item was found in `ROADMAP.md`; this
is a focused usability and access-management improvement to the existing
secrets surface.

**Additional context:** GitHub search found no duplicate PR for this
dialog and in-sheet access change. PR #9321 also mentions user-secret
resolution but addresses unrelated skills-route behavior.

## What Changed

- Auto-generate the create-secret key from Name, keep it read-only by
default, and expose an explicit Edit action.
- Use a path-style Name placeholder (`/dev/foo/bar`) and place Value
immediately after Name for natural keyboard navigation.
- Remove tab sizing/whitespace overrides that caused uneven provider-tab
row heights.
- Add an Agent access section to the Details tab that lists referencing
agents and grants or revokes `secret_ref` / `user_secret_ref`
environment bindings in place.
- Cover company secrets and each-user definitions with focused render
tests.

## Verification

- `pnpm exec vitest run ui/src/pages/Secrets.render.test.tsx` — 17/17
passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm check:token-gates` — changed files are clean; the
repository-wide command currently reports five pre-existing `#9627`
violations in unrelated files (`Sidebar.tsx`, `Inbox.tsx`,
`IssueDetail.tsx`, `Issues.tsx`, and `Routines.tsx`).
- Additional secrets verification completed during implementation: 35/35
adjacent secrets tests passed, and the flow was checked in a real
browser in light and dark themes.

## Risks

- Agent access mutations update adapter environment configuration, so
malformed legacy env entries could affect how a binding is displayed or
revoked.
- Each-user definitions use `user_secret_ref` rather than `secret_ref`;
focused tests cover selecting the correct binding type.
- No database or API contract changes are included.

> 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

- Anthropic Claude Fable 5 assisted with the implementation using
repository-aware code editing and test execution.
- OpenAI GPT-5.5 via Codex CLI assisted with PR preparation, branch
hygiene, focused verification, GitHub operations, and review/check
loops.

## Checklist

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-18 14:39:06 -05:00
Dotta 83765f08d1 fix(ui): reap React 19.2 performance-track measures (memory leak) (#9827)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Its web UI is a long-lived single-page app; users leave tabs open
for hours/days
> - We chased multi-GB tab memory growth through several fixes (#9569,
#9624, #9627, #9701) that cut real churn — but the footprint kept
climbing
> - A heap-snapshot diff on a 12-hour tab finally showed the true cause:
of 13.2M heap nodes, **12.1M were `PerformanceMeasure` objects** — React
19.2 emits a `performance.measure()` per component render for its
DevTools "Performance Tracks" and never clears them
> - These are native objects, so `performance.memory` never reported
them (it read a flat ~74 MB while the real heap was ~308 MB), which is
why our earlier heap/DOM sampling looked stable while the footprint
ballooned
> - This pull request periodically clears the User Timing measure
buffer, since nothing in the app consumes it
> - The benefit is that long-lived tabs stop accumulating millions of
native `PerformanceMeasure` objects, eliminating the remaining unbounded
growth

## Linked Issues or Issue Description

No public GitHub issue exists; describing inline per CONTRIBUTING.md →
"Link Issues or Describe Them In-PR", following the bug report template.
This is the root-cause fix for the memory growth chased in #9569 / #9624
/ #9627 / #9701.

**What happened?**

Long-lived browser tabs grew to multiple GB of memory footprint over
hours/days. A heap snapshot of a 12h tab showed **13.2M nodes, of which
12.1M were `PerformanceMeasure`** (vs ~1.0M total nodes on a fresh tab).
Live capture showed **~340 `performance.measure()` calls/sec**, named
after React components with a `detail.devtools` payload — React 19.2's
"Performance Tracks". Nothing ever clears them, so they accumulate
without bound.

**Expected behavior**

A long-lived tab should not accumulate millions of `PerformanceMeasure`
entries. Idle/long-running tabs should hold a bounded footprint.

**Steps to reproduce**

Open the app (React 19.2 production build), leave a tab open with normal
activity, and run `performance.getEntriesByType('measure').length`
periodically — it climbs unbounded (12.3M after ~12h).
`performance.clearMeasures()` drops it to near-zero and frees the
memory.

**Paperclip version or commit**

Branch `fix/react-perf-measure-leak`, off `master` (after #9701).

**Deployment mode**

Local dev (`pnpm dev` build served by the dev instance), web UI. React
19.2.7. Not adapter-specific.

## What Changed

- **`ui/src/lib/perf-measure-reaper.ts` (new)** —
`startPerfMeasureReaper(intervalMs = 10_000)` clears
`performance.clearMeasures()` on a timer and returns a stop function. It
never calls `getEntriesByType('measure')` (which would materialize the
huge buffer). Honors a `window.__paperclipKeepPerfMeasures = true`
opt-out so a developer recording a React Performance Track in DevTools
can keep the entries.
- **`ui/src/main.tsx`** — start the reaper at app boot.
- Only *measures* are cleared — React's tracks pass explicit start/end
times and leave no marks, and the app doesn't use the User Timing API at
all (verified), so nothing else is affected.

## Verification

- **Root cause proven** by heap-snapshot diff: fresh tab ~1.0M nodes vs
12h tab 13.2M nodes, 12.1M of them `PerformanceMeasure`; live capture
showed ~340 measures/sec with `detail.devtools` and React component
names.
- **Fix proven live**: `performance.clearMeasures()` on the aged tab
dropped the buffer from **12,418,266 → 1,500** and reclaimed the memory
(heap `perf.memory` 308 → 269 MB, plus the ~12M native objects, which
are the bulk of the footprint).
- `vitest`: `perf-measure-reaper.test.ts` — interval clearing, `stop()`,
opt-out flag, and no-API no-op. All pass.
- `tsc -b` clean.

## Risks

Very low, client-only.
- Clearing the User Timing measure buffer only affects the DevTools
Performance panel's React track *history*; normal users never consume
it. Developers who want to record it can set
`window.__paperclipKeepPerfMeasures = true`.
- Only `performance.clearMeasures()` is called (not `clearMarks`), so
any mark-based timing elsewhere is untouched; a grep confirmed the app
makes no `performance.mark()/measure()` calls of its own.
- Adds exactly one 10s interval (negligible), and `clearMeasures()` does
not materialize the buffer.

Note: this is a React 19.2 upstream behavior (its performance tracks are
emitted in the production build and never cleared). If React later gates
or clears them, this reaper can be removed.

## Model Used

- **Provider:** Anthropic, via the Claude Code CLI.
- **Model:** Claude Opus 4.8 (`claude-opus-4-8`).
- **Reasoning mode:** Extended thinking enabled.
- **Capabilities used:** tool use (shell, file editing), the Chrome
DevTools MCP to reproduce and profile, and a streaming heap-snapshot
parser to identify the `PerformanceMeasure` accumulation.

## 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 (continues #9701; no 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 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 considered and documented any risks above
- [ ] I have updated relevant documentation to reflect my changes (N/A —
no user-facing docs; rationale documented inline)
- [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)
2026-07-18 14:05:25 -05:00
DottaandPaperclip 051ae4d102 feat: restore decision training library and inspector (#9779)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies and supervise governed work.
> - Decisions capture high-value operator judgment, and the
decision-training foundation merged in #9702 freezes that evidence for
later evaluation and learning.
> - Operators still need the UI from the closed stacked PR #9718 to
intentionally capture examples and inspect the resulting dataset.
> - GitHub automatically closed #9718 when its stacked base branch was
deleted after #9702 merged, leaving the server foundation on `master`
without the corresponding UI.
> - This pull request restores the final UI and its still-required
supporting API fields directly on current `master`, while excluding the
obsolete migration and duplicated server-foundation diffs.
> - The benefit is a reviewable replacement PR that preserves the
completed decision-training workflow without replaying stale stack
history.

## Linked Issues or Issue Description

- Refs #9718
- Refs #9702

## What Changed

- Restored the top-level `/training` library and record inspector with
search, filters, JSONL export, notes editing, and evidence tabs.
- Restored the Decisions-row training affordance and capture drawer,
including preview, provenance, deletion, cache refresh, and approval
consistency behavior.
- Restored the shared types and focused server support needed by the UI
without reintroducing decision-training migrations or the already-merged
server foundation.
- Restored focused UI and attention-service tests from the final #9718
state.
- Credit to the authors and reviewers of #9718; this recovery
transplants their final reviewed delta after the stacked base deletion.

## Verification

- `pnpm exec vitest run ui/src/pages/Training.test.tsx
ui/src/components/DecisionTrainingDrawer.test.tsx
ui/src/components/AttentionQueueRow.test.tsx
server/src/__tests__/attention-service.test.ts
server/src/__tests__/decision-training.test.ts` — 5 files, 48 tests
passed.
- `pnpm --filter @paperclipai/shared typecheck` — passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm exec vitest run server/src/__tests__/openapi-routes.test.ts` — 3
tests passed; confirms exact route/OpenAPI parity for the restored
preview endpoint.
- `pnpm check:token-gates` — the restored files are clean; the
repository-wide command currently reports five pre-existing false
positives where comments reference GitHub issue `#9627` as if it were a
color literal.

## Risks

- Low migration risk: this PR contains no database migrations and is
based directly on current `master`.
- The main behavioral risk is cache invalidation across Decisions and
Training views; focused tests cover capture, update, deletion, row
state, and approval refresh behavior.
- The token-gate baseline remains red on unrelated `#9627` comment
references; this PR does not modify those files.

> 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, reasoning with repository/tool access and
code execution. Context window 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>
2026-07-17 13:27:32 -05:00
DottaandPaperclip f7e511a3e5 fix(ui): stop the inbox unread dot from indenting rows (#9767)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Inbox lists issues as rows; unread rows show a small blue
mark-read dot at the leading edge
> - The dot was rendered as an `order-first` flex column that existed
only on unread rows, so it changed each row's leading layout depending
on read state
> - On parent (chevron) rows the dot stacked on top of the collapse
chevron and pushed the whole row's status/title to the right, so unread
rows sat indented relative to their read siblings
> - This PR gives every inbox row a reserved leftmost dot slot so the
dot never changes horizontal alignment
> - The benefit is a stable, non-shifting inbox: read and unread rows
line up at the same x, and the dot no longer crowds the collapse caret

## Linked Issues or Issue Description

No public issue exists. Describing as a bug report:

- **What happened:** In the Inbox, an unread issue row's blue mark-read
dot pushed the row's status/title to the right, so unread rows were
indented relative to read siblings. On parent (collapsible) rows the dot
also overlapped the collapse chevron.
- **Expected behavior:** The unread dot should not change a row's
horizontal alignment. Read and unread rows should line up identically,
and the dot should sit clear of the collapse caret.
- **Steps to reproduce:** Open the Inbox with a mix of read/unread
issues, including a parent issue with children. Observe unread rows
indented vs. read rows, and the dot crowding the chevron on parent rows.
- **Deployment mode:** UI-only (frontend).

Related PR (same inbox area, in flight):
https://github.com/paperclipai/paperclip/pull/9685

## What Changed

- `ui/src/components/IssueRow.tsx`: Add a reserved leftmost dot slot
(`w-4`, desktop) that is present on **all** inbox rows — read and unread
alike — so the mark-read dot renders far-left ahead of any leading
control without shifting content. The dot button markup is now shared
between the desktop reserved slot and the mobile in-flow rendering. The
row is `relative` for slot positioning.
- `ui/src/pages/Inbox.tsx`: Always reserve the leading spacer for
non-chevron rows (removed the special-case that dropped it for unread
rows), since the dot now has its own dedicated slot to the left of the
spacer. This removes the double-indent.
- Mobile keeps the dot in flow as the leading item (no reserved desktop
gutter there).
- Tests: `IssueRow.test.tsx` and `Inbox.test.tsx` updated to assert the
reserved dot slot exists on read and unread rows and that alignment no
longer differs by read state.

## Verification

- `cd ui && NODE_ENV=development npx vitest run
src/components/IssueRow.test.tsx src/pages/Inbox.test.tsx` → 28 tests
pass.
- `cd ui && npm run typecheck` → clean.
- Note: running the full UI suite with `NODE_ENV=production` surfaces
pre-existing `act is not a function` failures unrelated to this change
(React's production bundle strips `act`); they pass under a normal test
env.

## Risks

Low risk. UI-only, scoped to inbox row layout. The reserved slot is
`hidden ... sm:inline-flex`, so mobile layout is unchanged (dot stays in
flow). No API, schema, or telemetry changes.

## Model Used

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

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-17 12:21:28 -05:00
DottaandPaperclip a090c09ee5 feat: add decision training snapshot foundation (#9702)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies and their work
> - Human approvals, issue interactions, and execution decisions already
capture high-value decision moments
> - Those moments are currently transient and cannot be reused as stable
evaluation or training examples
> - Reusable examples need a server-owned, immutable snapshot so later
comments or runs cannot leak into the recorded state
> - Human notes need to remain editable and auditable without changing
the captured state
> - This pull request adds the database model, snapshot capture service,
API, export format, and attention-feed enrichment for decision training
> - The benefit is a durable, inspectable foundation for evaluating
whether agents can reproduce good human decisions from only the context
available at decision time

## Linked Issues or Issue Description

### Subsystem affected

Cross-cutting (`server/`, `packages/db`, and `packages/shared`).

### Problem or motivation

Paperclip has no durable dataset for converting human decisions into
evaluation-ready examples. Teams need to capture pending or resolved
decisions with the exact issue context, comments, runs, and repository
evidence available at a cutoff, while preventing future context from
leaking into the example.

### Proposed solution

Store immutable, schema-versioned snapshots anchored to durable
interaction, approval, or execution-decision records; keep notes
separately editable with history; expose human-only CRUD, list, and
JSONL export APIs.

### Alternatives considered

Client-generated snapshots were rejected because they duplicate cutoff
logic and cannot reliably enforce no-leakage boundaries. Automatic
outcome backfill was deferred so captured examples remain faithful to
what was known at capture time.

### Roadmap alignment

Supports the roadmap direction of turning completed work and decision
patterns into reusable organizational knowledge.

### Additional context

The implementation records explicit commit-resolution confidence
(`exact`, `nearest_run`, `workspace`, or `none`) so downstream
evaluation can distinguish evidence quality.

## What Changed

- Added the `decision_training_examples` schema and idempotent migration
with company, issue, and source/author indexes.
- Added shared types for decision-training records, notes history, and
versioned snapshots.
- Added a single server-side snapshot capture path with inclusive
comment cutoffs, pre-cutoff run capture, durable decision payloads, and
explicit commit-resolution confidence.
- Added create, list, detail, notes-only update, delete, and JSONL
export routes with human-only write authorization and activity logging
that skips no-op note submissions.
- Added per-user `trainingExampleId` enrichment to attention items.
- Added focused embedded-Postgres tests for cutoff boundaries,
post-cutoff leakage, immutable snapshots, human-only writes, duplicate
prevention, notes history, attention enrichment, and export shape.
- Updated UI test and Storybook attention-item factories for the new
required `trainingExampleId` contract.

## Verification

- `pnpm exec vitest run server/src/__tests__/decision-training.test.ts`
— 10 tests passed.
- `pnpm --filter @paperclipai/db typecheck` — passed, including
migration numbering and safety checks.
- `pnpm --filter @paperclipai/shared typecheck` — passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.

## Risks

- The migration adds a new table and indexes only; it does not rewrite
existing rows or install resolve-time hooks.
- Snapshot JSON can grow with long comment threads and run histories; v1
intentionally favors complete, inspectable examples over aggressive
truncation.
- Commit SHA resolution is evidence-based and records `exact`,
`nearest_run`, or `none` so downstream consumers can account for
confidence.
- The API is additive, but future UI work must continue to treat the
snapshot as immutable and use notes-only updates.

> 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.3-codex`, with repository tool use, terminal
execution, and code-editing capabilities; 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
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-17 12:17:34 -05:00
1f1f545238 feat: add built-in summarizer and summary slots (#9713)
## Thinking Path

> - Paperclip is the open source control plane people use to organize,
govern, and understand AI-agent work
> - Operators need concise, current status views across projects and
execution workspaces without manually reading every issue and run
> - Paperclip already has auditable issues, documents, built-in agents,
routines, and live run events, but no first-class summary-slot workflow
connecting those systems
> - A built-in Summarizer can generate status prose through ordinary
governed tasks while summary slots provide stable, revisioned
destinations for that output
> - The UI needs to show current summaries, generation progress,
failures, revisions, and streaming draft status in the places operators
already work
> - This pull request adds the end-to-end summary-slot data, API, agent,
orchestration, and UI surfaces behind an experimental setting
> - The benefit is decision-oriented status context that remains
company-scoped, auditable, retryable, and inexpensive by default

## Linked Issues or Issue Description

No public GitHub issue exists for this feature.

**Problem**

Operators currently have to reconstruct project and workspace status by
reading many issues, runs, and comments. This makes it hard to identify
decisions, review queues, recent work, and the next event worth
watching.

**Proposed capability**

Add an experimental summary system with revisioned summary slots for
projects and workspaces, a paused-by-default built-in Summarizer agent,
governed generation tasks, live draft status, and reusable UI cards.

**Expected behavior**

- Summary data remains company-scoped and revisions remain auditable.
- Generation runs through normal issue/agent orchestration and
deduplicates active requests.
- Only the linked built-in Summarizer generation task can author a slot
revision.
- Operators can generate, retry, inspect revisions, and follow draft
progress from project and workspace views.
- The feature remains opt-in and background generation remains paused by
default.

## What Changed

- Added summary-slot schema, idempotent migrations, shared contracts,
validators, API paths, and service tests.
- Added company-scoped summary-slot routes for reading revisions,
requesting generation, and guarded Summarizer writes with activity
logging.
- Added terminal generation finalization, failure reasons, assignment
wakeups, and orchestration integration.
- Added the paused-by-default built-in Summarizer bundle, low-cost
runtime defaults, status-summarization skill, and stale-summary routine.
- Added summary cards, revision selection, retry/configuration states,
live draft streaming, transcript chunk handling, and project/workspace
integrations.
- Updated Claude local parsing for streamed status output and expanded
server, adapter, shared, database, catalog, and UI coverage.

## Verification

- `pnpm -r typecheck`
- `pnpm exec vitest run packages/db/src/summary-slots-schema.test.ts
packages/shared/src/summary-slot.test.ts
server/src/__tests__/summary-slot-routes.test.ts
server/src/__tests__/summary-slots.test.ts
server/src/__tests__/built-in-agents.test.ts
ui/src/components/SummarySlotCard.test.tsx
ui/src/components/SummarySlotCard.status.test.tsx
ui/src/components/useSummaryDraftStream.test.tsx
ui/src/lib/summary-draft-stream.test.ts
ui/src/lib/run-log-chunks.test.ts
ui/src/context/LiveUpdatesProvider.hook.test.tsx` — 113 tests passed
- `pnpm test:run` — server and UI suites passed; one CLI AWS doctor test
was affected by inherited `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`,
and passed when those host credentials were removed
- `pnpm exec vitest run cli/src/__tests__/secrets.test.ts` with
inherited AWS credential variables removed — 8 tests passed
- `pnpm build`
- `pnpm check:token-gates` currently reports nine `#9627` comment
references introduced by current `master`; none are in this PR diff

## Risks

- Database risk is limited by incrementally ordered, idempotent
migrations and migration safety checks.
- Summary generation creates normal issues/runs, so misconfiguration can
produce failed slots; the UI exposes retryable failure reasons and agent
configuration entry points.
- Streaming draft parsing depends on the documented `STATUS:` protocol;
final persisted revisions remain the source of truth.
- The feature is experimental, opt-in, and its built-in routine is
paused with no background token spend by default.

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

## Model Used

- OpenAI GPT-5.3 Codex with reasoning, repository tool use, code
execution, GitHub CLI, and Paperclip control-plane integration. Earlier
branch commits also record Claude model co-authorship where applicable.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:03:07 -05:00
DottaandPaperclip 009410164f Fix inbox unread badge alignment (#9685)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Inbox lets operators scan task state and distinguish unread
activity at a glance
> - Read and unread rows should keep the same status-and-title alignment
so the list remains easy to scan
> - The mark-read dot previously participated in flex layout, which
added an extra leading column and visibly indented unread rows
> - Parent rows also needed special handling because their collapse
chevron occupies the normal leading gutter
> - This pull request moves the unread dot out of desktop flex flow,
preserves a consistent leading spacer, and positions parent-row dots
after the chevron
> - The benefit is consistent alignment for read, unread, leaf, nested,
and collapsible parent rows without hiding tree controls

## Linked Issues or Issue Description

### What happened?

In the Inbox, an unread row rendered its status icon and title farther
right than an equivalent read row because the mark-read dot occupied its
own flex column. On a collapsible parent row, the dot also competed with
the leading chevron.
### Expected behavior

Read and unread Inbox rows keep identical status/title alignment while
preserving the unread affordance and any tree-expansion controls.
### Steps to reproduce

  1. Run Paperclip from `master` and open the Inbox at desktop width.
  2. Compare otherwise-equivalent read and unread leaf rows.
  3. Expand a task tree containing an unread depth-zero parent.
4. Observe the unread row indentation and the dot competing with the
parent chevron.
### Paperclip version or commit

Reproduced against the pre-fix `master` parent of this PR.
- **Deployment mode:** Local dev (`pnpm dev`).
- **Installation method:** Built from source.
- **Agent adapters involved:** Not adapter-specific; this is a core
Inbox UI bug.
- **Database mode:** Not database-related.
- **Access context:** Board (human operator).
- **Additional context:** No logs or configuration are involved; the
regression is visual layout behavior covered by focused component/page
tests.

## What Changed

- Render the desktop unread dot as an absolute overlay so it does not
consume row width; retain the existing in-flow behavior on mobile.
- Add an `unreadDotPlacement` option so depth-zero collapsible parents
place the dot after the leading chevron.
- Reserve the same leading spacer for read and unread non-chevron Inbox
rows.
- Expand `IssueRow` and Inbox tests to cover leaf alignment, nested
rows, parent chevrons, fading state, and mobile behavior.

## Verification

- `pnpm exec vitest run ui/src/components/IssueRow.test.tsx
ui/src/pages/Inbox.test.tsx` — 2 files, 30 tests passed.
- `pnpm check:token-gates` — all three token gates clean across 630
scanned files.
- Browser QA (desktop 1280px and mobile 375px) — PASS: read/unread
desktop content measured at identical x positions; nested guides, parent
chevron hit target, fading state, and mobile mark-read hit targets
verified.

## Risks

- Low risk: the change is isolated to Inbox row presentation and has
focused regression coverage.
- The main visual risk is breakpoint-specific placement of the mark-read
dot; tests explicitly cover desktop absolute positioning and mobile
in-flow positioning.

> 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.6-sol`, high reasoning effort, with
repository/tool execution. The runtime did not expose a context-window
size.
- Original implementation commit also records assistance from Claude
Opus 4.8.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-17 09:20:44 -05:00
5d42382df4 feat(ui): stabilize workspace service controls (#9705)
## Thinking Path

> - Paperclip is the open source control plane people use to coordinate
AI-agent work.
> - Execution workspaces provide the local service loop where operators
start, stop, restart, inspect, and open workspace services.
> - The existing header exposed those actions through separate controls
whose position and labeling changed across runtime states.
> - That movement made the most common development actions harder to
scan and easier to misclick, especially with multiple services or long
URLs.
> - The design therefore uses one fixed-geometry, state-aware control
bar and keeps service-specific detail behind a compact disclosure.
> - This pull request adds that control surface, maps existing runtime
data and every pending mutation into it, and integrates it into the
execution-workspace header without changing server contracts.
> - The benefit is a calmer, predictable service-control loop across
stopped, transitional, running, unhealthy, failed, multi-service, and
narrow-width states.

## Linked Issues or Issue Description

### Subsystem affected

`ui/ — React + Vite board UI`

### Problem or motivation

Execution-workspace service actions move and change shape as runtime
state changes, while URLs and multi-service status compete for header
space. During bulk actions, operators also need every targeted service
to show its transitional state immediately.

### Proposed solution

Use one fixed-geometry, state-aware service control bar in the workspace
header. Map existing runtime records into a stable status, URL, and
actions model, and track each in-flight bulk request independently until
it settles.

### Alternatives considered

Keeping the separate quick-control buttons was rejected because their
geometry changes by state. Showing every service inline was rejected
because it makes the header too wide; per-service detail remains in a
compact disclosure and the Services tab.

### Roadmap alignment

Reviewed `ROADMAP.md`; this focused execution-workspace UI improvement
does not duplicate a listed roadmap initiative.

### Additional context

The published design and state viewer is available at
https://pages.paperclip.ing/pap-14233-workspace-service-controls/.

## What Changed

- Added `WorkspaceServiceControlBar`, a fixed-geometry responsive
control for single- and multi-service runtime states.
- Added 15 Storybook states covering running, stopped, transitions,
unhealthy, failed, disabled, long-URL, mobile, and multi-service
behavior.
- Replaced `WorkspaceRuntimeQuickControls` in the execution-workspace
header with adapters that map live services and all pending requests
into the new control model.
- Added focused unit coverage for service-entry construction, bulk
pending overlays, request resolution, clipboard feedback, and header
integration.

## Verification

- `cd ui && NODE_ENV=development pnpm vitest run
src/components/WorkspaceServiceControlBar.test.tsx
src/components/WorkspaceRuntimeControls.test.tsx
src/pages/ExecutionWorkspaceDetail.test.tsx` — 29 tests passed.
- `NODE_ENV=development pnpm --dir ui typecheck` — passed.
- `pnpm check:token-gates` — all token gates clean.
- Reviewed the Storybook captures for all primary states.

## Risks

- Low-to-moderate UI risk: service controls depend on adapter mapping
from existing runtime records; focused tests cover single-service and
bulk-action mapping and integration paths.
- Multi-service bulk actions intentionally apply to all eligible
services, while per-service actions remain in the disclosure.

> 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.3-codex`; runtime-managed context
window; coding/reasoning mode with repository, terminal, Git, GitHub
CLI, and test execution tools.

## Checklist

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-16 21:07:04 -05:00
DottaandPaperclip b07b2994cc feat: stamp responsible users on activity logs (#9731)
## Thinking Path

> - Paperclip is the control plane people use to manage AI-agent
companies and their work
> - The activity log is the generic audit spine for mutations across the
control plane
> - Activity rows identify agents and runs, but they do not persist the
responsible human upstream
> - Relying only on run joins loses attribution after run pruning and
misses agent API-key actions outside a run
> - This pull request resolves responsible-user attribution when each
activity row is written and stores it directly
> - The benefit is durable, queryable agent audit feeds without
rewriting historical provenance

## Linked Issues or Issue Description

### Problem or motivation

Agent activity records do not persist the responsible user, so
attribution can disappear when runs are pruned and no-run API-key
mutations cannot be attributed correctly.

### Proposed solution

Resolve attribution for each new activity row from the run, related
issue, active agent API key, or company default, in that order, and
persist the result directly.

### Alternatives considered

Read-time joins alone were rejected because pruned runs lose durable
attribution and out-of-run agent-key actions have no run to join.
Historical backfill was rejected because it would invent provenance.

### Roadmap alignment

This strengthens the durable audit-trail direction described in
`ROADMAP.md` without adding a new product surface.

## What Changed

- Added nullable `activity_log.responsible_user_id` plus
company/agent/time and company/responsible-user/time indexes.
- Added an idempotent forward-only migration with no historical
backfill.
- Added centralized write-time resolution: heartbeat run → issue
attribution → active agent API key → company default.
- Propagated authenticated API-key IDs through existing request-backed
`logActivity()` calls.
- Added unit coverage for every fallback and an embedded-Postgres
assertion for the no-run API-key stamping path.

## Verification

- `pnpm --filter @paperclipai/db typecheck`
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/activity-log-responsible-user.test.ts
src/__tests__/authz-company-access.test.ts`
- Initial focused verification: 25 tests passed; migration safety
passed.
- Follow-up regression verification: 54 focused
attribution/company-skill/environment/issue-tree/tool-gateway tests
passed; server typecheck passed.
- GitHub: full build, typecheck, server shards, serialized suites, e2e,
security, and policy checks passed.

## Risks

- Adding two indexes to an existing large table can hold a write lock
while the transactional migration runs. The migration safety
suppressions document why `CONCURRENTLY` is unavailable under the
current Drizzle migration runner.
- Historical rows remain nullable by design; this avoids inventing
provenance and keeps the migration forward-only.
- API-key attribution requires request-backed activity call sites to
pass the authenticated key ID; this PR mechanically updates the existing
actor-based activity calls and covers the no-run path with integration
testing.

> 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`; context-window size was not exposed by the
runtime. Medium reasoning with repository editing, terminal execution,
and test execution capabilities was used.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-16 20:54:55 -05:00
DottaandPaperclip 53f09cb818 fix: prevent duplicate task creation and recovery loops (#9648)
## Thinking Path

> - Paperclip is the open source control plane people use to coordinate
AI-agent companies
> - Agents, routines, productivity review, and recovery services can all
create or re-trigger work
> - Repeated heartbeats or catch-up cycles can produce duplicate tasks
or repeat recovery actions before prior work is visible
> - The base duplicate-create and routine catch-up coalescing work has
now landed on `master` via related PRs while this PR was being prepared
> - This pull request carries the remaining hardening: bounded
idempotency retention, recovery cooldown/throttle fixes,
productivity-review query batching and ordering fixes, and regression
coverage
> - The benefit is fewer duplicate tasks, safer retries, and enough
provenance to diagnose any future recurrence

## Linked Issues or Issue Description

Agents can retry issue creation after ambiguous responses or
independently recreate the same child title, while recovery and
short-interval routine catch-up paths can repeat before prior work
settles. This can produce visible duplicate tasks and makes the
originating heartbeat difficult to identify.

Related work: Refs #8356 for caller-supplied issue-create idempotency
and Refs #9224 for plugin-scoped issue-create idempotency. Prior related
PR: #6936. The base issue-create deduplication and routine catch-up
coalescing pieces have since landed on `master` via #9650 and #9649;
this PR remains as the follow-up hardening stack on top of those
changes.

## What Changed

- Add 7-day retention for issue-create idempotency claims with indexed,
batch-limited cleanup so the claim table does not grow forever.
- Preserve recovery cooldown intent after terminal recovery actions are
closed, and throttle repeated source-scoped recovery work.
- Batch productivity-review source-activity checks to avoid repeated
per-source queries while keeping the no-action suppression behavior.
- Order productivity-review no-action streak windows by review creation
time, matching the window semantics even when completion timestamps are
out of order.
- Preserve generated issue IDs in route mocks used by backlog/assignment
contract tests.
- Document PR-gardening task deduplication expectations in the company
skill.
- Add focused regression tests for idempotency retention, liveness
recovery cooldowns, and productivity-review
batching/suppression/ordering behavior.

## Verification

- `pnpm --filter @paperclipai/server typecheck` — passed on latest head.
- `pnpm exec vitest run --project @paperclipai/server
server/src/__tests__/productivity-review-service.test.ts
server/src/__tests__/issue-create-deduplication-routes.test.ts
--reporter verbose` — 2 files, 23 tests passed on latest head.
- `pnpm --filter @paperclipai/adapter-utils build && pnpm exec vitest
run --project @paperclipai/adapter-utils --reporter dot` — 30 files
passed, 476 tests passed, 8 skipped.
- `pnpm build` — passed on latest head.
- `pnpm -r typecheck` — passed on the rebased head before the final
productivity-review ordering commit; the latest touched server code is
covered by the server typecheck above.
- `pnpm check:token-gates` — passed.
- `pnpm test:run` — progressed through server, UI, CLI, shared,
skills-catalog, and DB sections, then exposed an adapter-utils
compiled-test fingerprint mismatch before rebuilding adapter-utils; the
adapter-utils project passed after rebuild, and the GitHub split PR
checks passed on the pushed head.

## Risks

- Caller-supplied idempotency replay is now bounded to 7 days; reusing
an old key after retention can create new work, which matches
retry-oriented idempotency semantics.
- Recovery and productivity-review timing changes may suppress redundant
follow-up work; focused tests cover the intended boundaries.
- Advisory locking and idempotency cleanup rely on PostgreSQL-compatible
transaction semantics already used by the production data layer.
- The migration extends the private claim table indexes without
rewriting existing issue rows.

> 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 based on GPT-5, with reasoning, repository editing,
shell/tool execution, and test execution. Exact model ID and
context-window size are not exposed by the runtime.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-16 17:00:53 -05:00
DottaandPaperclip a015ac7a57 fix(ui): allow interrupting queued issue runs (#9725)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The issue detail chat lets operators send messages while an issue
run is live
> - Messages sent during a live run are shown as queued and can expose
an interrupt action
> - The UI only treated running runs as interruptible, even though
queued runs can also own the pending message
> - That mismatch hid the interrupt button after sending a message while
the agent run was still queued
> - This pull request treats queued and running issue runs as
interruptible and preserves the exact target run on optimistic and
persisted comments
> - The benefit is that operators can immediately interrupt the queued
run their message is waiting behind

## Linked Issues or Issue Description

- **What happened:** Sending a message while an issue-owned agent run
was in `queued` state showed the message as pending but did not make the
interrupt action available.
- **Expected behavior:** A message queued behind either a queued or
running issue run should retain that run as its interrupt target and
expose the interrupt control.
- **Steps to reproduce:** Open an in-progress issue with an issue-owned
run still queued, send a chat message, and inspect the queued message
actions.
- **Version/commit:** Reproduced against the pre-change `master` UI
behavior.
- **Deployment mode:** Paperclip board UI with a queued issue execution
run.

## What Changed

- Generalized issue-run resolution from running-only to
queued-or-running interruptible runs.
- Used the interruptible run consistently for optimistic queue metadata,
persisted comment decoration, cancel controls, and targeted
interruption.
- Added a regression test that sends a message behind a queued run and
verifies the exact run is cancelled.

## Verification

- `pnpm exec vitest run ui/src/pages/IssueDetail.test.tsx` — 44 tests
passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm check:token-gates` — repository-wide gate currently reports nine
pre-existing `#9627` comment literals; this patch adds no token literals
or gate violations.

## Risks

- Low risk: the behavior change is limited to selecting queued
issue-owned runs as valid interrupt targets in the existing chat flow.
- Cancellation remains targeted by run ID, and the regression test
verifies the queued run ID is preserved through optimistic and persisted
comment states.

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

## Model Used

- OpenAI `gpt-5.4` via Codex CLI; context-window size is not exposed by
this runtime; reasoning-enabled with repository, shell, GitHub CLI, and
code-execution tools.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-16 16:55:51 -05:00
59fb27ff79 feat(inbox): let agents safely tidy user inboxes (#9724)
## Thinking Path

> - Paperclip is the open source control plane people use to manage
AI-agent companies and their work
> - The inbox is a per-user attention view, so archiving an item must
not alter the underlying issue, assignment, or status
> - Agents can help responsible users tidy resolved work only when the
action is company-scoped, reversible, policy-controlled, and fully
attributable
> - The database and authorization foundations landed in #9654 and
#9658, but the end-to-end archive routes, audit details, agent workflow
guidance, and operator UI still need to ship together
> - Separate stacked PRs #9659 and #9661 made the complete behavior
harder to review and land as one coherent capability
> - This pull request consolidates the remaining server,
shared-contract, documentation, skill, and UI work on top of current
master
> - The benefit is a single reviewable change that lets agents safely
archive responsible-user inbox items and lets users control or undo that
behavior

## Linked Issues or Issue Description

### Subsystem affected

Cross-cutting inbox management across shared contracts, server
authorization/routes/services, shipped agent skills, and the board UI.

### Problem or motivation

Agents may complete work whose issue remains in the responsible user's
Mine inbox. Existing board-user archive behavior does not provide the
agent-facing policy endpoints, target resolution, heartbeat-run
attribution, typed denials, conservative workflow guidance, or UI needed
for safe agent-managed cleanup.

### Proposed solution

Allow authorized agents to archive or unarchive responsible-user inbox
items under the user's open, allowlist, or disabled policy; preserve
actor/agent/run attribution in issue detail and activity records; expose
policy controls and agent archive attribution in the UI; and document
conservative cleanup rules for agents and PR gardening.

### Alternatives considered

- Reuse generic issue mutation permissions: rejected because inbox state
belongs to a target user and requires user-scoped authorization.
- Automatically archive every completed or closed item: rejected because
completion signals can still require human review or a decision.
- Keep the backend and UI as separate stacked PRs: superseded by this
consolidated PR so the complete user-visible behavior can be reviewed
and verified together.

### Related work

- Builds on merged foundations #9654 and #9658.
- Supersedes the remaining stacked changes in #9659 and #9661.
- `ROADMAP.md` has no overlapping inbox archive or inbox authorization
initiative.

## What Changed

- Added shared inbox-agent policy types and validators plus
company-scoped self-service policy routes and OpenAPI coverage.
- Enabled agent archive/unarchive mutations with responsible-user
targeting, policy enforcement, typed failures, attribution, idempotency,
and detailed activity auditing.
- Returned agent archive attribution in issue detail and documented
reversible inbox cleanup semantics in the implementation spec and
Paperclip skill.
- Added conservative PR-gardening inbox tidy guidance that keeps GitHub
access read-only and avoids archiving work that still needs human
action.
- Added the Profile settings policy control and Issue Properties
attribution/unarchive UI with focused component coverage and narrow-pane
handling.

## Verification

- `pnpm exec vitest run
server/src/__tests__/inbox-archive-routes.test.ts
server/src/__tests__/inbox-agent-policy-routes.test.ts
server/src/__tests__/authorization-service.test.ts
server/src/__tests__/openapi-routes.test.ts
ui/src/components/InboxAgentPolicyControl.test.tsx
ui/src/components/IssueProperties.test.tsx` — 110 passed.
- `pnpm --filter @paperclipai/db exec vitest run
src/inbox-archive-agent-policies-migration.test.ts` — 1 passed.
- `node --test
.agents/skills/pr-gardening/scripts/pr-gardening.test.mjs` — 9 passed.
- `pnpm --filter @paperclipai/server typecheck` — passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm check:token-gates` — changed files are clean; the
repository-wide command currently reports nine unrelated pre-existing
`#9627` literals outside this PR's diff.

## Risks

- Agent inbox mutations broaden an existing endpoint path, so
authorization and target resolution must remain fail-closed; focused
route and authorization tests cover allowed and denied paths.
- Archive state affects only the responsible user's inbox presentation
and remains reversible; it does not mutate issue status, assignment, or
visibility.
- The UI policy defaults to the existing open behavior, while allowlist
and disabled modes can reduce agent access.
- This PR intentionally builds on #9654 and #9658 and contains no new
migration number or modification to an already-applied migration.

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

## Model Used

- OpenAI Codex using GPT-5.4, medium reasoning, repository tool use,
shell execution, code review, and 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)
- [x] My branch name describes the change
(`feat/inbox-agent-archive-complete`) and contains no internal Paperclip
ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 16:49:18 -05:00
DottaandPaperclip 89af58b6dc Clarify task-level model overrides in issue properties (#9710)
## Thinking Path

> - Paperclip is the control plane where operators configure and inspect
AI-agent work.
> - An issue can override the assigned agent's primary model for that
task.
> - The issue-properties UI labeled that per-task setting as `Custom ·
<model>`, which could be read as a property of the model rather than a
replacement of the agent default.
> - Operators need the UI to distinguish the agent's primary model from
an issue-specific override at both the collapsed summary and selection
point.
> - This pull request renames the lane presentation to `Override` and
adds concise provenance text without changing the stored lane value or
adapter configuration behavior.
> - The benefit is that operators can immediately understand which model
will run and why it differs from the agent default.

## Linked Issues or Issue Description

No matching public GitHub issue was found. Related implementation work:
#9700 moved Codex ACPX model configuration to startup and is already on
`master`; #9355 also addresses ACP session-config rejection behavior.
Those PRs concern execution behavior, while this PR is limited to
clarifying the issue-level override UI.

Bug report details:

- **What happened?** The issue-properties Model row displayed `Custom ·
<model>` for a task-level
`assigneeAdapterOverrides.adapterConfig.model`. Operators could misread
`Custom` as describing the model itself and could not see that the value
replaced the agent's primary model for this issue.
- **Expected behavior:** The UI should explicitly identify a task-level
model as an override and explain that it replaces the agent's primary
model for the issue.
- **Steps to reproduce:** Configure an agent with a primary model, set a
different model on an issue, and inspect the Model row and model picker
in Issue Properties.
- **Paperclip version or commit:** Reproduced on the pre-change branch
derived from current `master`.
- **Deployment mode:** Local development or any deployment using the
board UI.
- **Installation method:** Built from source.
- **Agent adapters involved:** Adapter-agnostic; any adapter exposing
model selection.
- **Database mode:** Not database-related.
- **Access context:** Board operator viewing issue properties.
- **Relevant logs or output:** Not applicable; this is a presentation
ambiguity.
- **Relevant config:** An issue-level
`assigneeAdapterOverrides.adapterConfig.model` differing from the
assigned agent's primary model.
- **Additional context:** The internal lane identifier remains `custom`;
only user-facing copy and explanatory text change.
- **Privacy checklist:** No private instance links, internal ticket IDs,
secrets, usernames, or local paths are included.

## What Changed

- Renamed the collapsed issue model label from `Custom · <model>` to
`Override · <model>` and added a provenance tooltip.
- Renamed the model-picker lane from `Custom` to `Override` and added
explanatory subtext at the selection point.
- Updated the Issue Properties component test to assert the new label.
- Added an isolated Storybook fixture for the task model override state
so visual review has a stable target.

## Verification

- `pnpm exec vitest run ui/src/components/IssueProperties.test.tsx` — 43
tests passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `git diff --check public-gh/master...HEAD` — passed.
- `pnpm check:token-gates` — the changed files are clean, but the
repo-wide command currently reports nine unrelated `#9627` comment
references already present on `master` as color literals.

## Risks

- Low risk: this changes display strings and explanatory copy only;
override storage, lane identifiers, API contracts, and execution
behavior are unchanged.
- The global token-gate false positive may also appear in CI until the
unrelated `#9627` references on `master` are allowlisted or the scanner
ignores issue-number comments.

> 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 assisted this PR preparation using medium
reasoning, repository-aware shell execution, Git/GitHub tooling, and
local test/typecheck execution. The hosted runtime did not expose an
exact model ID or context-window size to this session.

## Checklist

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

> - Paperclip is the open source control plane people use to organize
and govern AI-agent companies
> - Company skills are durable resources that users browse, import,
assign, and maintain over time
> - A flat skill list plus tags does not provide a stable location or
hierarchy for personal, company, project-imported, and bundled skills
> - Folder paths need to be canonical, company-scoped, safe to move, and
preserved across re-imports without changing skill IDs
> - The `/skills` UI also needs traversal, breadcrumbs, move/create
flows, and a dedicated My Skills namespace that work on desktop and
mobile
> - This pull request adds the folder data model and APIs, reserved-root
lifecycle, project import behavior, and the folder-first skills
experience
> - The benefit is a predictable filesystem-like organization model
while tags remain available for cross-cutting classification

## Linked Issues or Issue Description

Refs #9619 — the reviewed folder foundation was intentionally closed and
folded into this combined feature PR.
Refs #9026 — earlier flat-folder attempt superseded by this integrated
implementation.
Refs #3281 — related skill organization proposal; this PR uses canonical
persisted folders rather than deriving groups from skill keys, and does
not add hidden-skill behavior.

**Feature request**

- **Problem:** Skills currently lack a canonical hierarchical location,
making personal skills, project imports, bundled skills, and
company-authored skills difficult to traverse and manage at scale.
- **Proposed behavior:** Add nested company-scoped folders with stable
paths, reserved My/Projects/Bundled roots, subtree queries, safe
move/create operations, and a folder-first `/skills` library UI.
- **Import behavior:** New project scans file skills under
`projects/<project-slug>`; later imports update content without
overriding a user-selected folder.
- **Alternatives considered:** Tags alone remain useful for
cross-cutting classification, but they do not provide canonical
location, nesting, reserved namespaces, or stable import placement.
- **Roadmap alignment:** Extends the completed Skills Manager and
Scheduled Routines capabilities without duplicating an active roadmap
item.

## What Changed

- Adds `folders` persistence for routine and skill folders, nested
canonical paths, parent/slug/system-key fields, migration backfills, and
reapply-safe migrations `0174`–`0175` after current master migrations.
- Adds company-scoped folder CRUD, cycle/depth/namespace validation,
reserved My/Projects/Bundled lifecycle, item moves, subtree filtering,
and folder paths on skill results.
- Preserves project-import placement: first import files into the
project folder, while re-import keeps user-owned placement and stable
skill IDs.
- Adds the `/skills` folder tree rail, tags facet, breadcrumbs,
subfolder browser, move/new-folder dialog, canonical detail location,
inline tag editing, and folder-aware Studio creation.
- Keeps bundled skills read-only even when their source metadata is
incomplete by detecting the reserved Bundled folder and hiding
selection/move actions.
- Extends routine folder UI and OpenAPI coverage, and adds regression
tests across migrations, services, routes, tree helpers, pages, and
Studio creation.

## Verification

- `pnpm exec vitest run
packages/db/src/nested-skill-folders-migration.test.ts
server/src/__tests__/folders-routes.test.ts
server/src/__tests__/folders-service.test.ts
server/src/__tests__/company-skills-service.test.ts
server/src/__tests__/routines-service.test.ts
ui/src/components/folders/FolderControls.test.tsx
ui/src/components/folders/SkillFolderTree.test.tsx
ui/src/components/folders/skill-folder-tree.test.ts
ui/src/pages/CompanySkills.test.tsx ui/src/pages/Routines.test.tsx
ui/src/pages/SkillStudio.test.tsx
ui/src/lib/company-skill-routes.test.ts ui/src/lib/skill-create.test.ts`
— 13 files, 192 tests passed.
- `pnpm exec vitest run ui/src/pages/CompanySkills.test.tsx
ui/src/components/folders/SkillFolderTree.test.tsx` — 2 files, 20 tests
passed after preserving the existing PR's bundled-skill fixes.
- `pnpm -r typecheck` — passed for all workspace packages.
- `pnpm test:run` — passed in an isolated CI-like environment with
inherited Paperclip runtime identity and static AWS credential variables
removed.
- `pnpm build` — production build passed for all workspace packages.
- Greptile iteration 2 — 5/5 confidence with zero unresolved threads on
commit `ff2d67aa71`.
- Latest-head GitHub checks — all success, neutral, or skipped; PR is
mergeable with a clean merge state.
- `pnpm check:token-gates` — reports nine existing `#9627` comment false
positives already present on `master`; this PR introduces no new token
violation.

## Risks

- **Migration/backfill:** `0174` creates the foundation and `0175` adds
nested/reserved semantics. Both are ordered after current master
migration `0173`, are covered by numbering/safety checks, and are
designed to be reapply-safe.
- **Reserved namespaces:** My, Projects, and Bundled roots are
service-managed. Regression coverage prevents namespace squatting,
cross-company folder use, bundled writes, cycles, and excessive depth.
- **Behavioral change:** Project scans choose a project folder only on
initial creation; existing skills deliberately retain their current
folder during refresh.
- **UI scope:** The folder rail applies to the Installed library;
Catalog retains the discovery-oriented category sidebar.

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

## Model Used

- OpenAI `gpt-5.5` in Codex CLI, medium reasoning mode; runtime did not
expose a context-window value. Used repository/file tools, terminal
execution, Git/GitHub operations, test execution, and code editing.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-16 15:50:45 -05:00
Dotta 8b04147ca4 perf(ui): stop polling the event-sourced company live-runs list (#9701)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Its web UI keeps live views fresh with a live-events websocket plus
React Query, and #9627 began replacing polling with event-sourcing
(pushing data into the cache)
> - After the churn fixes (#9624) and #9627 shipped, a long-lived tab's
memory footprint was still climbing, so I re-profiled with the Chrome
DevTools MCP
> - The dominant remaining churn is React Query re-arming a polled
query's `refetchInterval` timer on **every** observer notification — and
our live-event handlers `setQueryData(liveRuns(companyId))` on nearly
every event, so each pushed update re-arms every `liveRuns` observer's
timer (the sidebar is always mounted)
> - #9627 event-sourced the live-runs data but left the now-redundant
`refetchInterval` in place, so we did half the fix — the poll is pure
waste and the thing re-arming timers
> - This pull request removes `refetchInterval` from the event-sourced
company live-runs queries so the frequent cache writes have no timer to
re-arm
> - The benefit is that the steady-state timer churn on the
most-observed resource collapses, so the off-heap footprint stops
climbing

## Linked Issues or Issue Description

No public GitHub issue exists; describing inline per CONTRIBUTING.md →
"Link Issues or Describe Them In-PR", following the bug report template.
Continues #9569 / #9624 / #9627.

**What happened?**

With the earlier fixes deployed, a browser tab left open on the app kept
growing its memory footprint. MCP profiling showed ~100+ `setInterval`
create/clear cycles per 5s on an aged tab (vs ~16 fresh), all from React
Query's refetch-interval timers being re-armed on every `setQueryData`
to the frequently-written `liveRuns(companyId)` query.

**Expected behavior**

A resource whose data is pushed (event-sourced) should not also poll;
cache writes should not repeatedly re-arm interval timers. Idle tabs
should hold a bounded footprint.

**Steps to reproduce**

Open a tab with agents streaming, leave it open, and instrument
`setInterval`/`clearInterval`: the churn rate climbs and traces to
`QueryObserver.updateTimers` (`refetchInterval`) for `liveRuns`,
re-armed by every live-event cache write.

**Paperclip version or commit**

Branch `perf/drop-live-runs-refetch-interval`, off `master` (after
#9627).

**Deployment mode**

Local dev (`pnpm dev`), web UI. Core UI live-updates plumbing; not
adapter-specific.

## What Changed

- Set `refetchInterval: false` on every site that polls the **plain**
`queryKeys.liveRuns(companyId)` query (event-sourced by #9627):
`Sidebar`, `SidebarAgents`, `Issues`, `Inbox`, `IssueDetail`
(companyLiveRuns), `ProjectDetail` (×2), `Routines`,
`ExecutionWorkspaceDetail`, `bridge-init`.
- Removed the now-unused `useVisibilityRefetchInterval` interval
vars/imports in `Issues`, `Inbox`, `IssueDetail`.
- **Left variant-key sites polling on purpose** — `Agents` page
(`[...liveRuns, "agents-page"]`) and `ActiveAgentsPanel` (`[...liveRuns,
scope, …]`) are NOT event-sourced by #9627 (different exact cache key),
so dropping their poll would make them stale. Those are a later phase.
- Freshness for the converted queries now comes from event-sourcing
(#9627) + its reconnect reconcile; the initial mount fetch and cross-tab
publish (`usePublishSharedQueryData`) still happen.

## Verification

- MCP profiling identified the churn: the single churning callback is
React Query's `refetchInterval` timer, re-armed by
`setQueryData(liveRuns)` on live events.
- `vitest`: all affected suites pass (`Sidebar`, `SidebarAgents`,
`Issues`, `Inbox`, `IssueDetail`, `ProjectDetail`, `Routines`,
`ExecutionWorkspaceDetail`, `LiveUpdatesProvider`) — 153 tests.
- Updated two `SidebarAgents` linger-window tests: they advanced fake
timers to the *exact* linger-expiry boundary and had relied on
poll-induced re-renders to flush. The linger self-schedules its own
`setTimeout`, so the tests now cross the boundary with a small margin +
an explicit flush (no product change).
- `tsc -b` clean.
- End-to-end footprint reduction should be re-measured against a rebuilt
bundle with the same instrumentation.

## Risks

Low, client-only.
- `liveRuns(companyId)` freshness now depends entirely on event-sourcing
+ reconnect reconcile (both from #9627). If an event path is missed, the
reconnect handler refetches once; durable replay is a planned later
phase.
- Variant-key run lists (Agents page, ActiveAgentsPanel) are unchanged
and still poll, so they don't regress.
- Issue-scoped run queries (`issues.liveRuns/activeRun/runs`) are
**not** touched here — they aren't event-sourced yet and are a separate
phase.

## Model Used

- **Provider:** Anthropic, via the Claude Code CLI.
- **Model:** Claude Opus 4.8 (`claude-opus-4-8`).
- **Reasoning mode:** Extended thinking enabled.
- **Capabilities used:** tool use (shell, file editing), and the Chrome
DevTools MCP to re-profile the live instance and pinpoint the
`refetchInterval` timer churn.

## 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 (a perf/plumbing change)
- [x] I have searched GitHub for duplicate or related PRs and linked
them above (continues #9627; no 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 (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 considered and documented any risks above
- [ ] I have updated relevant documentation to reflect my changes (N/A —
no user-facing docs; rationale documented inline)
- [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)
2026-07-16 11:42:04 -05:00
DottaandPaperclip 5a5c918705 fix(acpx): configure Codex models at startup (#9700)
Move Codex ACPX model, reasoning effort, and fast-mode settings into CODEX_CONFIG startup config so arbitrary model IDs avoid ACP session picker validation.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-07-16 11:41:48 -05:00