Commit Graph
12 Commits
Author SHA1 Message Date
DottaandPaperclip ab15aff390 feat: add experimental persistent agent chat (#13284)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Conversations must use the same tasks, controls, and execution
history.
> - Users need an ongoing chat with an agent without managing task
properties.
> - Agents should clarify and plan work, then hand execution to assigned
project tasks.
> - This pull request combines the reviewed Agent Chat stack for one
squash merge.
> - The benefit is persistent conversation with normal task governance
and shared UI.

## Linked Issues or Issue Description

**Subsystem affected**

Task lifecycle, agent runtime tools, shared task UI, and browser/paid
runner tests.

**Problem or motivation**

Users need one persistent conversation with each agent. A separate chat
store or renderer would duplicate task behavior and bypass existing
controls.

**Proposed solution**

Use a task-backed chat per company, user, and agent. Reuse the task
composer and transcript. Clarify and plan in chat, then create assigned
project tasks with the relevant plan. Keep Agent Chat behind its own
disabled-by-default experimental setting.

**Roadmap alignment**

This implements the task-backed direction in [CEO
Chat](https://github.com/paperclipai/paperclip/blob/master/ROADMAP.md#-ceo-chat).
Related proposals: #2504 and #9693. Related request: #7981. The
maintainer requested one squash merge of the complete stack.

Consolidates the reviewed runtime
[#13281](https://github.com/paperclipai/paperclip/pull/13281), backend
[#13282](https://github.com/paperclipai/paperclip/pull/13282), and UI
[#13283](https://github.com/paperclipai/paperclip/pull/13283) layers
with this PR's E2E coverage. All four layers passed CI and received
Greptile 5/5 before consolidation. This PR targets master and includes
the complete feature.

## What Changed

- Add personal canonical chat tasks with ordinary company visibility,
immutable identity, idempotent first sends, and an idle waiting state.
- Process `/new` in queue order. Preserve history, release a chat pause,
and fence old provider context and delayed writes.
- Keep chat lifecycle rules across recovery, finalization, assignment,
task lists, and rollups.
- Support research and plan revision in chat. Hand plans to ordinary
assigned project tasks before execution starts. Reject new chat
subtasks.
- Add repository-aware project creation and discovery tools, including
multiple repository IDs and GitHub URLs, authorization, idempotency, and
durable project-created cards.
- Reuse task UI components for chat, with starred/recent agent
navigation and a separate `enableAgentChat` experimental flag.
- Add deterministic browser tests and 24 paid chat cells across four
Codex/Claude profiles, with validated reports and screenshots.
- Integrate current master recovery, controller lease, queued-message,
and task UI changes. Gate chat interruption and deferred promotion on
ownership/feature policy. Guarantee lease renewal and active controls
are stopped even if teardown fails.
- Preserve master's migration 0273 and generate chat migration 0274 with
idempotent replay for development databases.

## Verification

- Prior exact heads of all four PRs passed Linux CI, including build,
typecheck, general/serialized tests, and browser E2E. Each had Greptile
5/5 and no unresolved findings.
- Integrated local verification passed: full repository typecheck and
production build, Storybook build, token gates, 340 focused UI tests,
all 20 deterministic chat browser tests, two migration replay tests, 88
focused chat/queue/native/controller tests, and provider/session
regressions including real lease expiry. These include the three
lifecycle regressions for the final admission/teardown fixes; server
typecheck also passes. Current head
`1268eda16cc2af892055917e7292f068820be135` has Greptile 5/5 with no
unresolved findings and passing security scans. All final-head CI gates
passed: build, full Runner verification, typecheck/release registry,
canary, all general/serialized test shards, and all browser E2E shards
([CI
run](https://github.com/paperclipai/paperclip/actions/runs/34696739927)).
Local PostgreSQL startup contention required serialized retries; skipped
fixtures do not count as passing coverage.
- The earlier paid campaign passed all 24 chat cells and retained 32
screenshots:
[report](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-34648511170-1/index.html?report=agent-chat#suite-agent-chat).
It tested `abacbdfd2f660709ec37312cdb758284c8399d04`; it is prior
evidence, not a paid run of this integrated head.
- Manual check: enable Agent Chat in Experimental settings, open an
agent, clarify and revise a plan, then hand off to an assigned project
task. Stop a reply, send `/new`, and verify fresh context with retained
history. Disable the setting and verify agent shortcuts/new chat turns
are blocked.

## Risks

- Queue/session integration can affect retries and delayed writes. Tests
cover ownership, cancellation, reset boundaries, idle recovery, and
ordinary task behavior.
- Migration 0274 adds conversation fields and constraints. Replay is
idempotent and preserves existing development chat history.
- This combines the previously reviewed stack at the maintainer's
request. Agent Chat remains off by default and is separate from
Conference Room.

## Model Used

OpenAI Codex, GPT-6 Astra (`gpt-6-astra`), with reasoning, code
execution, browser tools, and parallel review. The exact context-window
size is not exposed in this session. Codex and Claude also ran as test
subjects in the linked paid campaign.

## 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-09-12 08:56:04 -05:00
Devin Foley 2585ed0550 test(server): settle three contention flakes that killed canary verifies (#13186)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Every master push publishes a canary through release-verify; the
staging fleet and the nightly/beta/stable chain start from those
canaries
> - The server suite grew substantially on 2026-09-10 and now runs under
real contention in CI, where three tests assert timing properties that
only hold on an idle machine
> - Each of the three failed a release-verify canary run that day (runs
34497348802 and 34517515849), and together with the shard timeouts
(#13185) they kept any canary from publishing after 18:50 UTC
> - This pull request makes the three assertions contention-tolerant
without weakening the invariants they prove
> - The benefit is a canary lane whose verdicts reflect the code, not
the load on the runner

## Linked Issues or Issue Description

**What happened?**

Three server tests failed release-verify canary runs on 2026-09-10 under
CI load:

1. `chat-channels.integration.test.ts › returns a retryable webhook
failure when the delivery insert fails before durable receipt` — the
duplicate-redelivery request drew the retryable 503 instead of an
immediate 200 (run 34517515849).
2. `chat-channels.integration.test.ts › returns ephemeral guidance for
exact Slack controls in channels without creating tasks or actions` — a
`provider_effect` row was read before its async settlement reached
`processed` (run 34497348802).
3. `runner-connection-eval-fixtures.test.ts › resets paired attempts…` —
the fixture's `TRUNCATE companies CASCADE` was chosen as a deadlock
victim (40P01) against the helper app's own background sweeps (run
34497348802).

**Expected behavior**

Verify runs fail only for real regressions. A momentary-contention 503
on a duplicate redelivery, an in-flight settlement row, and a
deadlock-victim reset are all recoverable states the code handles by
design.

**Steps to reproduce**

Run the three tests under a loaded 3-shard release-verify split; the
timing assertions flake. Under `pr-trusted`'s lighter shards they
usually pass, which is why the PRs that introduced them were green.

**Paperclip version or commit**

`master` at `d1ba17eec`.

## What Changed

- The duplicate-redelivery assertion retries on 503 the way Slack itself
would (bounded, 250 ms apart), then asserts the 200 and the unchanged
dedup invariants: duplicate count increments, still exactly one issue.
- The channel-controls settlement read is wrapped in a bounded
`vi.waitFor`, the same pattern the file's durable-receipt paths already
use.
- The runner eval fixture retries its TRUNCATE on Postgres error 40P01,
bounded at five attempts, and rethrows anything else.

## Verification

- All three run green locally: the two chat tests via `-t` filters, the
eval fixtures file in full (6 tests).
- Each change is assertion-shape only; no product code is touched.
- Observation for a follow-up, not this PR: the chat integration file
costs ~15 s transform + ~28 s import per vitest worker before any test
executes — splitting it would give back real shard time.

## Risks

- Low risk: the retries and waits are bounded, so a genuine regression
(permanent 503, settlement that never lands, persistent deadlock) still
fails within the same timeouts as before.

## Model Used

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

## 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
2026-09-10 17:24:10 -07:00
DottaandPaperclip e095b84dab feat(connections): connect services from native task feeds (#13058)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents use connections to reach external services.
> - A fresh native task can have no service tools installed.
> - The agent needs a way to discover services and ask the responsible
person for access.
> - This pull request brings the existing connection-intent flow into
native task execution.
> - The person can connect from the task, and the agent can continue
with updated tools.

## Linked Issues or Issue Description

**Subsystem affected**

Native runner tool authority, connection intents, task interactions, and
shared connection setup.

**Problem or motivation**

A task that needs an unconnected service cannot finish its work. Leaving
the task to configure access also loses context. A resolved request must
survive a restart and resume the correct agent once.

**Proposed solution**

Expose connection discovery and access requests as server-owned native
tools. Render a durable task card and use the shared setup dialog.
Persist outcome delivery and start a fresh provider session after access
is ready.

**Alternatives considered**

Sending the person to the Connections page adds navigation and does not
solve continuation. Polling for authorization consumes runs and can
create duplicate requests.

**Roadmap alignment**

This extends the existing connection-intent runtime and setup
experience. It reuses the shared access model and the native runner.

Related: #12345, #12347. The service-slug fix in #12906 is related but
separate. Companion evaluation PR:
https://github.com/paperclipai/paperclip-evals/pull/21.

## What Changed

- Expose `connections_search` and `connection_request` with server-bound
company, task, agent, and responsible user. Preserve the legacy entry
points.
- Discover catalog services and authorized custom connections. Check
installation, identity, health, and executable permissions before
reporting ready.
- Keep pending cards through ordinary messages. Reuse requests and
retire stale ownership. Put Connect at the right of Not now.
- Reuse the shared setup flow in a task dialog. Keep access additive and
default to the requesting agent. Recover from cancelled or blocked OAuth
windows with a new-tab fallback.
- Persist outcome delivery with an idempotent wake key. Resume in a
fresh session and recheck ownership before dispatch.
- Add native browser fixtures, offline Storybook states, server
contracts, and evaluation fixtures. Update guidance and documentation.

## Verification

- `pnpm build`: passed after replaying the change on current master.
- `pnpm -r typecheck`: passed.
- `pnpm check:token-gates`: passed.
- `pnpm --filter @paperclipai/ui build-storybook`: passed.
- New continuation-policy regression cases: 16 passed.
- Docker-backed PostgreSQL regressions passed for requester-only OAuth
access, assignment-only expiry, terminal expiry, and credential-free
setup metadata.
- Shared setup and task-card UI tests: 121 passed, including configured
MCP reconnect URL recovery and preserving user edits across refetch.
- Storybook browser checks: all 119 passed on the latest reconnect fix.
- `pnpm test:run`: 4,734 tests passed in the first server group, but
embedded PostgreSQL startup failures and resulting cleanup errors
prevented a complete local pass. All Linux CI lanes passed on the latest
reviewed commit. One external-object route test returned an unexplained
500 on the first run; it passed twice locally and the failed shard
passed on retry without code changes.
- Earlier feature-checkout evidence: three deterministic native browser
journeys passed, including restart delivery and an actual fixture tool
result. Legacy scripted coverage also passed. All 59 added stories were
inspected in light and dark themes.
- Live Notion testing recorded successful provider reads. The manual
test used a local-trusted instance. It does not prove
authenticated/cloud deployment or every provider journey.
- Native browser rerun reached the embedded PostgreSQL startup limit
before bootstrap, so the latest checkout’s full native browser journey
remains unverified. Both OAuth page/task regression cases passed against
isolated Docker-backed PostgreSQL 17. They verify no premature task
access, requester-only completion, additive retries, and reconnect
preservation.
- Applied both new migrations twice to isolated PostgreSQL 17. Foreign
keys remained intact, duplicate active delivery keys were rejected, and
failed delivery records did not block retries.

Reviewer path: start a fresh test drive, enable the native runner, use
an agent that can perform work directly, and ask it to summarize a
Notion page. Connect from the card, then verify the resumed provider
call and source-linked answer. The default test-drive CEO is instructed
to delegate, so it can introduce an unrelated hiring step.

## Risks

- Two additive migrations create durable deliveries and a partial unique
wake index. They are idempotent. The wake index can require a
maintenance window on large tables because migrations run in a
transaction.
- OAuth and continuation cross asynchronous boundaries. Tests cover
ownership changes, retries, additive access, and restart delivery; live
provider behavior still varies.
- The latest requester-scope fix has not yet been exercised through live
OAuth. GitHub, API-key, authenticated-user, and all recovery journeys
are not claimed as verified.

## Model Used

OpenAI GPT-6-based Codex assisted with implementation, tests, and review
using tools and code execution. The runtime does not expose the exact
model version, context window, or reasoning setting. Live evaluation
used `gpt-5.6-luna`; manual native testing used `gpt-5.6-sol`.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used and disclosed unavailable runtime
details
- [x] I have checked ROADMAP.md and confirmed this extends existing
connection work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have described the issue in-PR following the feature issue
template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket id
- [ ] I have run all required tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented risks
- [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-09-08 15:55:26 -05:00
DottaandPaperclip 5bddff0920 feat(runner): add guarded API search and call fallback (#13003)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - The new runner gives agents dedicated tools for common tasks.
> - Some API operations and parameters have no dedicated tool.
> - Agents need a controlled way to find and use those operations.
> - This pull request adds API search and calls through the real server
routes.
> - Existing tools remain the preferred path. The new tools are disabled
by default.
> - Paired tests measure correctness, tool choice, cost and time.

## Linked Issues or Issue Description

**Subsystem affected**

Paperclip Runner contracts, production tool authority and the server API
catalog.

**Problem or motivation**

The runner cannot use much of the API described by the old Paperclip
skill. A generic HTTP client would also let agents bypass runner control
rules.

**Proposed solution**

Add `search_api` and `call_api`. Resolve calls from the mounted API
catalog. Use server-held, run-bound credentials. Preserve route checks
and runner lifecycle rules. Keep the tools disabled until an operator
enables selected companies.

**Alternatives considered**

A dedicated tool for every endpoint would add a large initial prompt. An
unrestricted HTTP tool would weaken authorization and replay controls.

**Roadmap alignment**

This extends the native runner tooling. The repository owner requested
this design and implementation. The roadmap and related open PRs were
checked. No duplicate API escape-hatch PR was found.

## What Changed

- Register two compact fallback tools in canonical contracts and
provider projections.
- Build deterministic API discovery from OpenAPI, mounted experimental
routes and the old skill reference.
- Execute bounded JSON, text, file and download requests through
authenticated HTTP routes.
- Recheck active runs, company access and work modes. Block runner
lifecycle, scheduling, credential and approval bypasses. Keep routine
annotation collaboration available.
- Retain mutation receipts. Report uncertain outcomes without blindly
repeating writes.
- Add a company rollout gate and a durable eval worker with complete
cost accounting checks.
- Record child-task creation in the activity log with the agent and run.
- Add contract, authorization, file, replay and real runnerd/PRP/HTTP
tests.
- Document rollout gates and paid coverage limits. The companion eval
repository retains immutable attempts and reports.

## Verification

- Final app commit `da58370524c3626a744eec20164397c5fb6ba9ef`: all 32
checks passed; the unrelated Storybook visual check was skipped.
Greptile 5/5; no unresolved review threads.

- Full Linux build and recursive typecheck passed. Repository tests were
run by project and serialized shard; all 143 serialized server suites
passed.
- Runner TypeScript: 1,599 passed, two skipped. Rust release: 451
passing test reports. Conformance and replay parity passed. The required
API check passed 837 tests, including runnerd → PRP → authority → real
HTTP.
- Bindings cannot enable API tools without the explicit deployment flag.
Unit and real-authority tests prove the default-off boundary.
- The standalone API check builds and stages its own binary. It passed
after existing staged and debug binaries were removed from the test
container.
- UI and CLI tests passed. Initial environment failures (missing jq,
Docker overlay file identity, and parallel linker memory pressure) and
focused passing reruns are retained. The macOS full runner suite has
platform-specific failures; Linux is the qualified full-check platform.
- Eval harness: 27 tests passed; existing CI discovery ran 86 tests with
two unrelated skips. Credential export rejection is tested against the
actual report command.
- Luna and OpenRouter Sonnet each passed 60 common-workflow runs: ten
workflows, three repetitions per arm, zero unnecessary API fallback.
- Sonnet passed 11 selected capability/contract cases after fixes.
Gemini passed three smoke cases. DeepSeek exceeded the 120-second limit
and remains unqualified.
- Luna's two cost flags received focused follow-up. The original flags
and a later n=1 latency flag remain visible. Sonnet had no cost or
latency increase above 20%.
- The catalog contains 785 entries; 58 were exercised across all stages.
Most operation probes remain unrun and some need additional fixtures.
Authored probes do not establish successful coverage.
- Total conservative accounted cost: $9.875960. Active paid-campaign
time: 88.16/90 minutes. No missing accounting. Later security and
harness fixes have provider-free verification; no paid validation is
claimed for those revisions.
- Inspect the [qualification
report](https://github.com/paperclipai/paperclip-evals/blob/codex/seach-call-api-tools/evals/runner-api-tools/reports/2026-09-07-production/READINESS.md)
and [verification
record](https://github.com/paperclipai/paperclip-evals/blob/codex/seach-call-api-tools/evals/runner-api-tools/reports/2026-09-07-production/verification.json).

## Risks

- This is a broad authenticated API surface. Keep the default-off gate
until an operator selects initial rollout companies.
- Paid coverage is incomplete. Small regression samples do not prove all
workflows are unchanged.
- A timeout or server failure can follow a committed mutation. The
result reports an unknown outcome and requires state inspection.
- The new definitions add prompt tokens. The report retains cost flags
and cache variation.
- No database migration is required.
- Repository rules require code-owner approval before merge. Technical
CI and automated review are complete.

## Model Used

OpenAI Codex based on GPT-6 assisted with code, tests and review. The
exact serving model ID and context window are not exposed in this
session. It used reasoning, tool calls and code execution.

Eval models: `gpt-5.6-luna` with low reasoning,
`openrouter/anthropic/claude-sonnet-5`,
`openrouter/google/gemini-3.8-flash`, and
`openrouter/deepseek/deepseek-v4-flash-0731`. Attempts retain runtime
versions, model identity, usage and source provenance.

## 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-09-07 14:14:43 -05:00
Dotta 51ad751e0b feat(runner): integrate Codex native execution (#12616)
## Thinking Path

> - Paperclip is the open source control plane for teams of AI agents.
> - Agent runs currently use direct adapters and their established
finalization paths.
> - The new runner package needs one production integration before it
can execute a real provider through the server.
> - That integration must not change direct adapters or expose
unsupported providers.
> - The rollout must also preserve native runs that were already
recorded when the feature flag changes.
> - This pull request adds a default-off, Codex-only native execution
path and its authority boundary.
> - The benefit is a recoverable production vertical slice with explicit
compatibility guards.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting server orchestration and adapter selection.

**Problem or motivation**

The runner package exists, but the server cannot yet start and recover a
governed Codex run through it. A careless integration could also route
existing direct adapters into the native runtime or lose cancellation
and finalization state.

**Proposed solution**

Add a hidden `paperclip_runner` adapter for Codex. Keep it behind the
default-off instance flag. Bind native execution, resume, cancellation,
semantic tool authority, and finalization to the recorded company,
issue, run, and coordinator identities. Leave every direct adapter on
its existing path.

**Alternatives considered**

A multi-provider launch was rejected because only Codex has the complete
production bridge in this series. Replacing direct adapter execution was
rejected because the runner remains experimental.

**Roadmap alignment**

This work supports governed tool access, action attribution, and
self-healing runs. It keeps the integration narrow and default-off.

## What Changed

- Add the Codex-only native session executor and persisted resumption
path.
- Add run-scoped semantic tool projection, authorization, receipts, and
idempotency.
- Add audited native cancellation with durable issue and coordinator
binding.
- Add result fencing so a recorded result cannot reacquire the provider
and run twice.
- Reject fresh runner starts when the rollout flag is off while
preserving recorded native recovery.
- Keep direct adapters outside native status, cancellation, record
creation, and finalization.
- Add focused conformance, recovery, cancellation, status, portability,
and compatibility coverage.

## Verification

- GitHub Actions is the authoritative test environment for this large
stack.
- The PR policy and lightweight stack checks run while this is a middle
PR.
- The full required suite runs when this PR becomes the lowest unmerged
or top PR.
- Greptile will review this exact delta after the branch is pushed.

## Risks

- The main risk is routing a legacy adapter into native execution.
Runtime selection and heartbeat tests cover that boundary.
- The next risk is stale or cross-company cancellation. Durable binding
checks and transactional audit persistence cover it.
- The adapter remains hidden and default-off. Only Codex is admitted.
- There are no database migration, lockfile, or GitHub workflow changes
in this PR.

## Stack

1. [Runner package, SDK, and developer
tools](https://github.com/paperclipai/paperclip/pull/12608)
2. This PR: Codex production server integration
3. [Provider-neutral task-thread
UI](https://github.com/paperclipai/paperclip/pull/12617)

## Model Used

OpenAI Codex with GPT-5, extended reasoning, repository tools, and
parallel review agents.

## 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
- [ ] 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
2026-08-31 22:51:17 -05:00
Nicky LeachandPaperclip b7fd6c59b6 fix(server): load the costs-service route module graph once per file (#12375)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The server test suite checks budget and cost routes
> - The costs-service test rebuilt the full route module graph before
every test
> - Synchronous graph rebuilds caused long stalls under CPU load
> - This pull request loads the mocked graph once for each describe
block and keeps per-test mock setup
> - The benefit is a stable 17-test file without production code changes

## Linked Issues or Issue Description

**What happened?**

The costs-service route test rebuilt its full mocked module graph before
every test. Under CPU load, a rebuild sometimes stalled a test past the
15-second timeout.

**Expected behavior**

The test file should load its mocked route graph once for each describe
block while each test keeps isolated mock behavior.

**Steps to reproduce**

1. Run the costs-service route test under synthetic CPU load.
2. Repeat the file test 30 times.
3. Observe intermittent test timeouts before this change.

**Paperclip version or commit**

The test used the current master branch at the time of this change.

**Deployment mode**

Built from source.

## What Changed

- Add `hoistModuleGraph` to load the mocked route graph once for each
describe block.
- Keep per-test mock setup in `beforeEach` so test isolation stays
unchanged.
- Keep all 17 tests and their assertions.
- Remove the module graph rebuild from the per-test path.

## Verification

- Run `npx vitest run src/__tests__/costs-service.test.ts` from
`server/`.
- Confirm that the file reports 17 tests and zero skipped tests.
- Confirm that 30 runs under the same synthetic CPU load report 0.0%
failure after the change, compared with 10.0% before the change.
- Confirm that mutation checks still fail when each authorization guard
is broken.

## Risks

This change affects test setup only. The main risk is weaker test
isolation if a mock keeps state between tests. Each test still re-arms
its mock behavior in `beforeEach`, and the full assertion set remains.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. This bug fix does not add a
core feature.

## Model Used

OpenAI GPT-5. The model used tool calls and code execution. The exact
context window and reasoning configuration were not exposed by the
runtime.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs: #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have 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 (the submitting engineer
ran the file before handoff)
- [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-27 18:37:30 -07:00
Nicky LeachandPaperclip 036600d922 fix(db): close test database clients before the embedded Postgres cluster stops (#12335)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip uses database clients and embedded PostgreSQL test
fixtures
> - A fixture stopped its embedded PostgreSQL cluster while clients
still held connections
> - The postgres.js driver then scheduled a write on a stopped
connection
> - That write escaped the timer callback and caused a test process to
exit with an error
> - This pull request closes registered clients before the fixture stops
its cluster
> - The benefit is stable test teardown and clear failure reporting in
continuous integration

## Linked Issues or Issue Description

Refs: #10869

**What happened?**

An embedded PostgreSQL test fixture stopped its cluster while database
clients still held open connections. The postgres.js driver then
scheduled a deferred write on a dead connection. The write caused an
unhandled error after the test shard reported success.

**Expected behavior**

The fixture closes all live clients for its cluster before it stops the
embedded PostgreSQL cluster. Tests then finish without a deferred write
on a dead connection.

**Steps to reproduce**

1. Run the database regression test with the embedded PostgreSQL
fixture.
2. Stop the fixture while its database client still has an open
connection.
3. Observe the deferred write and the process exit status.

**Paperclip version or commit**

Branch base: bdd8f1bed. Change head:
93e85d2ba1.

**Deployment mode**

Local dev with the embedded PostgreSQL test fixture.

**Installation method**

Built from source with pnpm.

**Agent adapter(s) involved**

Not adapter-specific. This change covers database test infrastructure.

**Database mode**

Embedded PGlite.

**Additional context**

The change keeps client references weak and keys them by host and port.
It does not retain credentials. It also handles connection URLs that the
driver accepts when the URL parser rejects them.

## What Changed

- Add a registry for live database clients in the database package.
- Close registered clients before the embedded PostgreSQL fixture stops
its cluster.
- Add a regression test for the teardown race.
- Handle driver-compatible URLs that the standard URL parser rejects.
- Add cleanup for the shared route test harness.

## Verification

- Run the full `packages/db` suite.
- Run `tsc --noEmit` in `packages/db`.
- Run the server suite that uses `route-test-harness.ts`.
- Run the teardown regression test five times.
- Confirm that the negative control fails three times.
- Confirm that no shard reports green tests and exits with an error.

## Risks

The registry changes client cleanup for embedded test fixtures. Weak
references limit retained memory in long-lived processes. The registry
uses host and port only, so it does not retain credentials. No
migration, schema, API, telemetry, authentication, or cryptography
change exists.

## Model Used

OpenAI Codex, GPT-5, tool use and code review support, standard
reasoning mode. The implementing engineer supplied the code and
verification results.

## 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-27 13:39:42 -07:00
2ebc236b08 fix(server): accept parentIssueId alias in GET /issues (#4032)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents coordinate through the server API. They find sub-tasks by
filtering the company issues list by parent.
> - `GET /api/companies/:companyId/issues` accepts `?parentId=`. Many
callers send `?parentIssueId=` instead, which the handler never read.
> - The mismatch is silent. The filter is dropped and the full company
list comes back, so agents fetch everything and filter client-side.
Issue #3846 reports this.
> - `parentIssueId` is not an arbitrary spelling. It is the field name
the wakeup payloads in this same route file already use, so callers
expect it.
> - This pull request accepts `parentIssueId` as an alias for `parentId`
at the route boundary, on both the issues list and `issues/count`.
> - The benefit is that parent filtering works for both spellings, and
the list and its count cannot disagree.

## Linked Issues or Issue Description

Fixes #3846

Related: #3870 proposes the same alias for the list route.

## What Changed

- `server/src/routes/issues.ts`: `listFilters.parentId` in `GET
/companies/:companyId/issues` now reads `req.query.parentId ??
req.query.parentIssueId`.
- `server/src/routes/issues.ts`: `blockedCountFilters.parentId` in `GET
/companies/:companyId/issues/count` reads the same alias, so the list
and its count agree.
- `server/src/__tests__/issues-parent-id-alias.test.ts`: new regression
test for alias resolution, precedence, and absence.

## Verification

- Run `pnpm run test:run --
server/src/__tests__/issues-parent-id-alias.test.ts`.
- The test covers four query shapes: `?parentId=`, `?parentIssueId=`,
both present (short form wins), and neither present (filter unset).
- Existing callers are unaffected. The UI client `ui/src/api/issues.ts`
only sets `parentId`. Nullish coalescing falls back only when the
primary key is absent.
- The service layer applies the filter with `if (filters?.parentId)` in
`server/src/services/issues.ts`. This pull request does not change it.

## Risks

- Low risk. The change only widens accepted query input. Both spellings
resolve, and the short form still wins.
- `?parentId=` with an empty value stays falsy and unfiltered, exactly
as before.
- This route has no validation middleware, and these list filters are
not in the published OpenAPI surface. No contract needs an update.

## Model Used

- Claude Opus 5 (`claude-opus-5`), extended thinking with tool use, run
by the maintainer's triage agent. It rebased the original commit onto
current `master`, extended the alias to `issues/count`, and wrote the
regression test. @scokeepa authored the original one-line route change.

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

---------

Co-authored-by: josangmun <cmeia.ai02@cmeia.co.kr>
Co-authored-by: Andrew Aymeloglu <aaymeloglu@gmail.com>
2026-08-04 20:45:42 -05:00
Nicky LeachandPaperclip d51f42ed64 test(server): drain heartbeat runs to quiescence in sibling suite teardown (#10464)
## Thinking Path

> - Paperclip uses heartbeats to run work.
> - Test suites share heartbeat run state during teardown.
> - Late heartbeat work can race shared table deletes.
> - That race can deadlock or fail foreign key checks.
> - The primary suite already uses a drain helper to wait for
quiescence.
> - This pull request reuses that helper in the sibling suites that
share the race.
> - The benefit is stable teardown and fewer flake failures.

## Linked Issues or Issue Description

No public GitHub issue exists for this change.
Refs: #10450
This pull request reuses the quiescence drain from the primary suite.

## What Changed

- Added `server/src/__tests__/helpers/drain-heartbeat-runs.ts`.
- Reused the shared helper in `low-trust-red-team-routes.test.ts`.
- Applied the drain to the eight sibling suites that share the race.
- Kept the existing test intent unchanged.

## Verification

- `git log --oneline
origin/master..origin/test/heartbeat-teardown-quiescence-drain-sweep`
- `git diff --stat
origin/master...origin/test/heartbeat-teardown-quiescence-drain-sweep`
- Existing local test evidence in the handoff shows the primary suite
and the guarded suites pass.
- The handoff also records a stress loop with no `40P01` or `23503`
errors.

## Risks

- Low risk. The change touches test teardown only.
- The helper waits for active runs to drain. A new real background
execution path may need the same guard.

## Model Used

OpenAI GPT-5, tool-use and code 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 linked existing issues with `Fixes: #` / `Closes #`
/ `Refs #` or described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [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 no
docs update was required for this test-only 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 14:23:12 -07:00
4b1332b61c fix(openclaw-gateway): drop root paperclip params (#4416)
Fixes #5997, fixes #4081, fixes #4723, fixes #6625, fixes #3923

Refs #6606 — this PR removes the rejected root `paperclip` field, but
#6606 also requires the protocol v3→v4 bump, which is out of scope here;
referencing rather than closing it.

## Thinking Path

> - Paperclip is the control plane that wakes and coordinates agent
workers across company-scoped execution flows.
> - The `openclaw_gateway` adapter is part of that wake path, so its
outbound payload contract has to match the gateway's validated `agent`
schema.
> - `master` currently reintroduces a previously fixed regression by
sending a top-level `paperclip` property in `agentParams` (see #3923,
which reverts the original fix in #626).
> - The gateway rejects unknown root params, which means OpenClaw wakes
fail before the remote agent can start work.
> - The actual wake context already rides in the generated `message`, so
the extra root property is both redundant and harmful.
> - This pull request removes that leaked root property, adds a focused
regression test around param construction, and updates affected server
expectations/docs to the supported contract.
> - The benefit is that OpenClaw Gateway agents wake successfully again
without losing inline wake context.

## What Changed

- Removed the top-level `paperclip` field from OpenClaw Gateway
`agentParams` and extracted `buildAgentParams()` so the contract is easy
to test.
- Added a package-level regression test that proves
`payloadTemplate.paperclip` is stripped while explicit
`agentId`/`timeout` behavior stays intact.
- Updated server tests that inspect OpenClaw Gateway payloads to assert
wake data is delivered in `message` instead of a rejected root field.
- Updated the adapter configuration docs to state that wake context is
embedded in the generated message text, not sent as a top-level param.

### Rebase onto current `master` (conflict resolution)

This branch was opened against an older `master`; re-merging current
`master` required:

- Resolving conflicts in `execute.ts` — `master` hoisted
`configuredAgentId` and moved the agentId/timeout precedence inline;
this PR keeps the `buildAgentParams()` extraction that strips the
gateway-rejected root `paperclip`.
- Updating tests `master` added **after** this branch's base that assert
the old root-`paperclip` contract. These suites use the OpenClaw gateway
adapter purely as a delivery harness (`adapterType: "openclaw_gateway"`
+ a mock gateway) and observe wake content via the gateway payload, so
dropping the root field requires them to read wake context from
`message` instead:
  - `server/src/__tests__/heartbeat-comment-wake-batching.test.ts`
- `server/src/__tests__/low-trust-red-team-routes.test.ts` (redaction
guarantees preserved — sanitized body + `expectNoCanary` on the raw
canary)
- Replaced brittle JSON-substring assertions (flagged by Greptile) with
a shared `parseWakePayloadFromMessage()` helper + `toMatchObject`,
robust to serialization/key-order changes.

The strict contract is confirmed upstream: OpenClaw's
`AgentParamsSchema` is `Type.Object(..., { additionalProperties: false
})` with no `paperclip` field, so a root `paperclip` is rejected
(`invalid agent params: at root: unexpected property 'paperclip'`).

## Verification

- `pnpm --filter @paperclipai/adapter-openclaw-gateway typecheck` —
clean
- `pnpm --filter @paperclipai/server typecheck` — clean
- `pnpm exec vitest run --project @paperclipai/server
server/src/__tests__/openclaw-gateway-adapter.test.ts
server/src/__tests__/heartbeat-comment-wake-batching.test.ts
server/src/__tests__/low-trust-red-team-routes.test.ts` — 26 passed (7 +
11 + 8)
- `packages/adapters/openclaw-gateway/src/server/execute.test.ts` — 6
passed (run via a local temp vitest config because the root
`vitest.config.ts` does not include this package)

## Risks

- Low risk: this narrows the outbound payload to the gateway-supported
contract and keeps wake context in the already-supported `message`
channel.
- Any downstream consumer that incorrectly depended on a top-level
`paperclip` field from the gateway mock payloads would need to follow
the supported `message` contract instead.

> 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 via API authored the original change;
exact underlying model ID and context window were not exposed in that
environment.
- Rebase/conflict resolution and the test-assertion migration were done
with Claude Code (Claude Opus 4.8, 1M context).

## 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 the
related issues above
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [ ] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: serenakeyitan via breeze-runner <serenakeyitan@users.noreply.github.com>
Co-authored-by: Andrew Aymeloglu <aaymeloglu@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:32:15 -07:00
dottaandPaperclip 3c1ebed539 test(worktree): address embedded postgres helper review feedback
- probe host support on every platform instead of special-casing darwin
- re-export the db package helper from server and cli tests

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-26 11:56:05 -05:00
dottaandPaperclip c916626cef test: skip embedded postgres suites when initdb is unavailable
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-26 11:12:39 -05:00