Commit Graph
1850 Commits
Author SHA1 Message Date
DottaandPaperclip 45b67f1d93 feat: default new Apple Silicon Claude agents to Paperclip Runner (#15993)
## Thinking Path

> - Paperclip lets users choose an agent harness and account.
> - The server resolves the runner for new agents.
> - Claude still needs the same ordinary native-default journey as
Codex.
> - Existing agents must retain their runner, model and account.
> - This PR defaults new Apple Silicon Claude agents to Paperclip Runner
with Opus 5.5.
> - Users can connect and work without a runner override.

## Linked Issues or Issue Description

Refs #15683. This PR depends on #15994 and precedes #15997. Related
scope: #15422, #13978 and #15224.

## What Changed

- Resolve new Apple Silicon Claude agents to `paperclip_runner`,
`provider: acpx`, `acpxAgent: claude`. Keep explicit Legacy, models,
provider routing and saved execution.
- Use `claude-opus-5-5` for ordinary Claude defaults and retain explicit
overrides.
- Reuse existing API-key/subscription connections, credential storage
and checks. Generalize the shared Advanced runner control with Claude
branding.
- Carry configured effort into the shared v9 contract. Preserve
compatible permissions, instructions, skills, timeouts and session
behavior. Require Legacy for unsupported settings.
- Qualify a new immutable managed Claude target at explicit Connect
through the existing permission-gated probe. Use fresh scoped discovery
for test and hire. Discard stale results and require an explicit Connect
after settings change.
- Retain merged Codex onboarding recovery, auth preparation,
import/effort corrections and Grok Bot gates.
- Check the Claude first-task wizard's saved default directly. Update
configuration/runtime documentation and exact Opus 5.5 accounting.

- Align hire fixtures with the merged host-environment restriction.
Native agent-authenticated hires cannot inject host env settings; both
creation endpoints verify that no extra agent is saved.

## Verification

- Updated onto master `9179d8dcc3e908c217fde4f63c9d08ccf8132eeb` through
#15994. Native input v9 carries effort while preserving v7 home modes
and v8 Muse. Codex defaults remain unchanged.
- Focused local verification passed 285 server tests, 323 UI tests, 124
setup/registry tests, and two v9 permission-pin transport cases. Direct
server/UI TypeScript checks passed. An initial 30-second hook timeout
was resolved by serial verification with a longer hook budget: all 122
credential/permission cases and 232 snapshot/environment cases pass.
Direct server TypeScript checking also passes.
- Ordinary web creation with the experiment disabled saved native
Claude, Opus 5.5 and High effort without runner/model overrides. The
actual product task and follow-up both succeeded on integrated source
`b2c9fe43f9cd3bc5dd9d22552da0148845ba71a4` with the cloud-built daemon
from `04e0202ca81387b17cbe7fd094a8338648356fe9`. The final master
reconciliation also changes shared runtime source. Historical proof
retains its source identity; a final-source cloud qualification is
running before refreshing the preview daemon.
- Both actual browser downloads were checked: v1 has three sections/six
checkboxes (451 bytes); v2 preserves the original body and adds two
Rollback checks (612 bytes). The original attachment stayed
byte-identical. The follow-up records session resume and the same
provider session. Total estimated API usage: $0.518432800, with no
pending/unpriced usage in the successful fixture.
- Fixed the live-discovered setup incompatibility: native API-key
validation no longer depends on the global Legacy Claude CLI. The
existing provider endpoint verifies the key without a paid prompt;
subscription/custom routing probes remain intact.
- Fixed security review's native-hire credential redirection:
agent-supplied URLs, proxy/launch settings and other host environment
controls are rejected before inheritance. Native credential references
remain supported and partial edits use the saved harness. Added
create/hire/update regression coverage.
- Current-head cloud CI is green. All three stack PRs have fresh
Greptile 5/5 reviews and zero unresolved review threads. Required
typecheck, test and build gates ran in cloud CI; Docker work stayed
remote. Earlier failed checks remain in their original runs.
- Docker and native release builds ran in cloud infrastructure. An
inadvertent local Rust prerequisite was stopped; no local Docker build
was run.

- The final master merge preserves task-loading, permission,
skill-retention and OpenRouter changes. Pi uses a fresh combined profile
27, preserving both historical profile-24 declarations; Copilot remains
profile 22. Focused protocol checks passed 155 cases (one skipped), the
updated Pi attestation check passed 18 (one skipped), and 91
evaluation/catalog checks passed.

- Latest-application manual continuation passed in 37.942 seconds on
`695e5c005a85bddc8711d3fcddcaf6b7e1fb64d0`, with High effort, native
Opus 5.5, Anthropic API attribution, the same resumed Claude session, an
independently checked 635-byte file and persisted Done status. It uses
the earlier verified Mac daemon; the preceding-source package
qualification passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. That
package run predates the small TypeScript startup fix and is not
relabeled as qualification for it.
- Upgrade limitation: changed compiled sidecar identity rejected old
durable launch state and recovery hit session-open bounds before
eventually resuming. That attempt was operator-cancelled and retained;
the successful manual continuation does not qualify seamless upgrades.

- Local latency profile, Opus 5.5/High unchanged: three alternating
real-ACP loopback samples per variant reduce median provider-ready time
from 5.081s to 4.034s. The matched real API task startup improves from
5.533s to 4.348s, but total reply time changes from 17.933s to 20.221s
because agent work varies. This establishes a startup saving of about
one second, not a consistent total-reply speedup. A real candidate
follow-up passed in 20.146s and resumed the same saved session. The
loopback fixture makes no external model requests; failed initial probes
remain retained.
- The startup change passes 107 focused runtime/effort/lease tests, 53
profile checks (one skipped), TypeScript checking and the
TypeScript-only runtime build. Native hire fixture checks pass 70 tests;
their first local run retained a socket-hangup failure and stale
OpenCode expectation, both accounted for before the passing rerun.
Broader required checks run in cloud CI.

## Risks

- Missing packages, authentication rejection, unsupported settings and
unavailable models must fail explicitly. Existing agents retain saved
execution; explicit runner changes use existing revision/session
invalidation.
- Subscription follow-up remains unverified; remaining live acceptance
uses API keys per human steering. Historical accounting holds and the
separate $50 ceiling remain intact.
- The subscription acceptance limit remains explicit for review. No
Claude database migration is introduced.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution and browser testing. The exact serving model ID and
context-window size are 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
- [ ] Focused local tests and final cloud verification 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-10-19 13:58:52 -05:00
DottaandPaperclip 9e8a9f28d5 fix(github): recover long publications from durable receipts (#16883)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents publish GitHub reviews through governed tools.
> - GitHub can accept a publication before the caller receives its
result.
> - Exact retries must return the existing publication receipt.
> - The gateway compared a shortened audit hash with a complete request
hash.
> - Long reviews therefore failed the retry check even when their
content was unchanged.
> - This pull request checks the complete saved publication and returns
its current receipt.
> - Agents can confirm their work without another provider write.

## Linked Issues or Issue Description

Refs #16284, which added durable publication recovery. Refs #16275,
which extended the GitHub tool deadline.

**What happened?**

An exact review retry returned an idempotency conflict after GitHub had
published the review. The invocation hash uses an audit preview that
shortens strings to 500 characters and arrays to 50 entries. The gateway
compared that hash with the complete request hash. The earlier retry
tests used short assessments.

**Expected behavior**

An unchanged request returns its durable receipt. Changed content,
changed authority, or a missing publication must not cause another
write.

**Steps to reproduce**

1. Submit a review with a summary and rationale longer than 500
characters.
2. Let publication finish after a short caller deadline.
3. Repeat the exact request. Before this fix, the gateway returns an
idempotency conflict.

**Paperclip version or commit**

Reproduced on master at `c5226daf7a37559ddc007446681717791d80a223`.

## What Changed

- Use the durable publication's complete request check for GitHub
retries. Keep run, agent, task, connection, tool, and current authority
checks.
- Return the saved receipt through normal gateway validation and
bookkeeping. Leave pending provider work to the durable worker.
- Refuse retries without a saved publication. Keep existing invocation
keys and audit previews unchanged.
- Cover long reviews, comments, progress updates, text suffix changes,
nested coverage changes, pending receipts, missing publications, and
revoked access.
- Document the recovery contract and verification recipes.

## Verification

- Red: both long-review receipt cases failed on unchanged production
code with the expected idempotency conflict.
- Green: all 144 GitHub review workflow tests passed on the final
source. This includes long reviews, comments, progress updates, pending
and missing receipts, revoked policy, and the native assigned-tool entry
point.
- Server and workspace typechecks passed. The production build passed.
- Map checks passed. These are structural checks.
- The first broad run found an incorrect new fixture assumption: its
discovery query returned two review tools. The fixture now selects the
exact submission tool. An existing description-edit polling test also
timed out; it passed separately without a production change, then passed
in the complete 144-test rerun. Both earlier failures remain recorded.
- Final commit `7cdcdc3a1ac79cb4ed77510a32d795228e3315e8` passed all 55
CI checks. Two optional Storybook jobs were skipped. [Complete CI
run](https://github.com/paperclipai/paperclip/actions/runs/39304187397).
Greptile is 5/5 on this exact commit, with zero unresolved review
threads.
- The earlier local full-suite attempt was stopped after the fixture
correction. The final local full-suite attempt was stopped after
complete final-head CI passed. No complete local full-suite pass is
claimed; full-suite acceptance uses the current-head CI matrix.
- Provider responses are controlled fixtures. Native assigned-tool
coverage uses the production gateway and disposable PostgreSQL. No live
GitHub fault injection, deployment, or historical task recovery is
claimed.

## Risks

A pending receipt remains pending. It does not complete the task. Caller
retries no longer dispatch provider work; the durable worker retains
that responsibility. A missing durable publication returns a conflict
because the gateway cannot establish the original write's outcome.
Existing approval and revocation checks remain effective. No database
migration or audit hash change is required.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use, and code
execution. The session does not expose a more specific serving model ID
or context-window limit.

## 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-10-19 13:54:42 -05:00
DottaandPaperclip c5226daf7a fix(cloud): enable experimental toggles on staging (#16876)
Allow instance admins to change approved experimental feature controls on managed Cloud staging. Preserve production restrictions and managed access and execution policy.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-19 13:04:07 -05:00
Nicky LeachandPaperclip 194fc11406 feat(plugins): invalidate runtimes when tool definitions change (#16604)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Lifecycle plugins must refresh runtime preparation when tool
definitions change.
> - Standing assignments alone do not cover catalogs, profile entries,
or policies.
> - New journal hooks must preserve the order used by setup
finalization.
> - This pull request adds tool-definition invalidation and its required
writer guards.
> - It leaves credentials and provider access changes for the next
independent capability.

## Linked Issues or Issue Description

**What happened?**

Catalog, profile-entry, policy, gateway, and connection-configuration
changes do not request agent runtime synchronization. A new
profile-entry trigger also exposes a deletion/finalization deadlock if
the child row is changed before its parent is locked.

**Expected behavior**

Committed tool-definition changes advance runtime revisions without
polling. Bookkeeping does not. Entry changes and profile replacement use
a consistent parent/reference lock order and commit atomically.

**Steps to reproduce**

1. Change a catalog descriptor, profile entry, policy, or connection
configuration.
2. Expect committed runtime events for the affected agents.
3. Run profile-entry deletion concurrently with setup finalization while
both wait for an agent row.
4. Expect both operations to complete without PostgreSQL deadlock 40P01.

**Additional context**

Extracted from #16503. Catalog publication #16602 and standing
assignments #16603 are merged. This PR is rebased onto master and is the
active review. It addresses the original Apex profile-entry deletion
finding. Credential/access hooks #16605 remain a draft without review
requests.

## What Changed

- Add migration 0355 for application/connection configuration, catalog,
profile-entry, policy, and MCP gateway invalidation.
- Preserve transaction coalescing and ignore health bookkeeping and
trust-rule usage counters.
- Keep credential-only fields outside this migration's coverage.
- Preserve merged recipient scoping for bindings and installations.
Profile-entry edits resolve old/new standing profile bindings. Policy
edits resolve old/new agent selectors with their intersection/list
semantics.
- Lock old and new profile-entry references before parent profiles and
child mutations. Recheck the reference set under the parent lock, retry
changed snapshots up to three times, and merge unspecified fields from
the locked profile.
- Make entry add/edit/delete and profile replacement transactional,
including validation and profile reads on the reserved connection.
- Lock policy rows in ID order and change priorities in one statement so
scoped agent locks are ordered across the full set.
- Lock the managed profile before connection removal deletes its entries
in the same transaction.
- Update assignment tests whose old absence assertions are superseded by
expanded configuration coverage.
- Document the supported capability and the remaining credential/access
boundary.

## Verification

- Final head: `809fcb11794bfb12c545af0a2f96ab9bc2b570a2`. It is rebased
onto master with merged #16623. GitHub reports no merge conflicts. [CI
run
39293925136](https://github.com/paperclipai/paperclip/actions/runs/39293925136)
has 55 successful checks and two optional Storybook skips.
- Standard Greptile returned an independent 5/5. The final Apex review
returned 5/5 on this exact head at 17:47 UTC on 2026-10-19. Its summary
explicitly clears this PR for merge independently of draft #16605. The
security scan passed. All review threads are resolved.
- Two real-PostgreSQL negative controls reproduce `40P01` without the
old-reference guard or the concurrent-snapshot check. Both regression
tests pass with the final correction. Server typecheck, migration safety
and numbering, five-snapshot retention, journal history, feature maps,
and diff checks pass. The actual PR diff was scanned for secrets and
personal data before push.
- The final 15-suite local run passed 821/822 tests. The one failure was
in the unchanged runtime-delivery test: a startup callback changed its
global callback count during an independent transaction. The test-only
correction is isolated in #16871. That PR passes all 17 runtime-hook
tests, server types, hosted CI, and standard Greptile 5/5. Its
notification-disabled control fails at the independent event-delivery
assertion. No changes from #16871 are included here; this feature head
passes hosted CI independently.
- Earlier affected-suite runs passed 814 tests after rebase and 820
tests after recipient and whitespace corrections. Four affected suites
passed 514 tests before the second reference-contention regression was
added. Single-connection tests cover entry add, edit, delete, and
replacement. Validation and profile reads use the reserved transaction
connection.
- Review fixes have negative controls: the old code hangs with a
one-connection pool; parent-lock omissions deadlock entry deletion or
app removal against setup finalization; per-row policy reorder deadlocks
under contention; unscoped triggers journal unrelated peers; default SQL
trimming misses JavaScript whitespace. Corrected cases pass. Selector
tests cover all 25 ECMAScript whitespace characters. Recipient tests
cover repeated edits, old/new targets, ignored bindings, rollback,
coalescing, and company scope. The definition suite now has 28 cases.
- Earlier standard scores that depended on #16605 were not accepted as
independent clearance. The first Apex review returned 4/5 for
replacement versus application deletion. The final correction locks old
and new references, checks the reference set again under the parent
lock, and retries before any mutation. The final independent reviews
clear that correction.
- Preserve prior failures for acceptance: draft run 38975432017 had
failures whose causes were not re-investigated. Run 38990400765 exposed
the unrelated durable-resume watchdog race, fixed in merged #16623. In
run 39287657148, two jobs reported cancellation without a failed-test
summary; the cause remains unknown. Both passed on retry without source
changes. Initial local fixtures and SQL bindings also needed correction:
an internal helper name was replaced with public `archiveConnection`,
unchanged priorities were changed to exercise reorder, a driver
timestamp was bound as ISO text, and a superseded company-fanout
assertion was updated. These recovered checks do not establish a cause
for the unexplained CI failures.
- Local checks target the affected services and real database
boundaries. A full local build and repository-wide test run were not
performed. Hosted CI supplies the broader checks. Provider responses in
tests are controlled; live provider behavior was not qualified.

## Risks

Migration 0355 adds statement triggers without changing table schema.
Apply it through the normal migration flow. A tool-definition event can
advance a runtime revision without changing the bounded assignment
snapshot. Consumers still need authorized readers for definitions.
Credential-only changes, grants, secrets, and endpoints remain for the
access-hook migration. Profile replacement now rolls back as a unit if
any entry fails. Binding and install notifications retain scoped
recipients. Profile-entry changes use standing bindings, and policies
use old/new agent selectors. Unscoped policies, company-bound profiles,
and other conservative definition changes retain synchronous
transaction-atomic company-wide fanout: O(eligible company agents) locks
and journal storage, without a fanout ceiling or mutation quota. This
retains the accepted tradeoff from #16603 for company-wide changes.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository inspection, code
execution, and testing. The exact deployment model ID and context window
are 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 local checks; results and the isolated test failure are
recorded above
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [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-10-19 10:56:08 -07:00
Nicky LeachandPaperclip 4d8770f6dd test(plugins): assert runtime delivery by event identity (#16871)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Plugins receive committed runtime events without polling.
> - The delivery test checks that an independent writer is visible after
commit.
> - Startup baseline callbacks can still arrive during that transaction.
> - A total callback count mixes startup work with the event under test.
> - This pull request checks the transaction's specific event ID
instead.

## Linked Issues or Issue Description

**What happened?**

The runtime-delivery test failed during #16604 verification. It expected
one callback before an independent transaction committed, but received
two. The test waits for a total callback count derived before startup
baseline delivery is known to be complete. An older baseline event can
arrive during the transaction and fail that assertion.

The failing test and delivery implementation are unchanged from master.
This PR isolates the test-only correction from #16604.

**Expected behavior**

The event created by the independent transaction is absent from
delivered callbacks before commit. That exact event arrives after
commit. Other committed startup callbacks can arrive at any time.

**Steps to reproduce**

1. Start lifecycle delivery with startup events still pending.
2. Begin an independent agent update after the expected callback count
is first reached.
3. Let a baseline callback arrive before that transaction commits.
4. The old global-count assertion fails even though the transaction's
event is not delivered early.

**Additional context**

Scoped maintenance follow-up for #16604. No runtime behavior or feature
files change here. #16605 remains a draft without review requests.

## What Changed

- Read the new journal event ID inside the independent writer's
transaction.
- Assert that this ID is not delivered before commit.
- Wait for that same ID after commit and check its company, resource,
and type.
- Remove the total callback-count assumption.
- Wait for the company startup baseline, its acknowledgments, and
coordinator idleness. Flush earlier listener notifications with a
barrier, then wait for that barrier wake to settle before the
independent write.

## Verification

- The earlier full feature run passed 821/822 tests and failed this
exact count assertion with two callbacks instead of one. That failure
remains recorded in #16604.
- The failing test file is byte-identical on the reviewed feature head
and master. Neither the profile-replacement correction nor this PR
changes the delivery implementation.
- `pnpm exec vitest run
server/src/__tests__/agent-runtime-hooks.test.ts`: all 17 tests pass
with the event-ID assertion.
- `pnpm --filter @paperclipai/server typecheck`: passed.
- Standard Greptile initially returned 4/5: startup delivery could still
hide a missing independent wake. The correction adds observable startup
acknowledgment, listener flushing, and coordinator idleness. All 17
runtime-hook tests and server typechecking pass with it. A negative
control drops runtime notifications while forwarding the barrier and
fails the after-commit delivery assertion; startup work cannot mask that
loss.
- `git diff --check` and the full PR diff scan for secrets and personal
data passed.
- Full local build and repository-wide tests were not run for this
test-only correction. At `714a74bf0991617c9ad85ce17bae22c533d1ed22`,
hosted CI run 39295664656 passed: all 55 checks succeeded, with two
optional Storybook checks skipped. Standard Greptile returned 5/5, the
security scan passed, all review threads are resolved, and the branch is
mergeable against master. The tests use real PostgreSQL and controlled
plugin callbacks; live provider behavior is not qualified.

## Risks

Test-only change. The commit boundary assertion remains: the new event
ID must be absent inside the transaction and present after commit.
Existing startup callbacks no longer count as early delivery of a
different event. Runtime notification and retry behavior are unchanged.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository inspection, code
execution, and testing. The exact deployment model ID and context window
are 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
- [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-10-19 10:55:37 -07:00
DottaandPaperclip 985d3b12b6 fix(runner): explain rejected task monitor arguments (#16868)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use task monitors to resume work after a future check.
> - The runner rejects monitor arguments that fail the tool schema.
> - It returned a generic error with no field or repair guidance.
> - An agent could treat a repairable call as a scheduling outage and
block its task.
> - This pull request adds safe repair guidance and shows the nested
request shape.
> - Agents can correct the call and confirm a saved schedule before they
yield.

## Linked Issues or Issue Description

Refs: #15446, #16686.

**What happened?**

A rejected native `set_task_monitor` call returned `invalid_tool_call`
with only “Paperclip rejected this semantic tool call.” The agent could
not identify the invalid field. A retry could fail again and leave
unfinished work without a scheduled wake.

**Expected behavior**

Reject invalid arguments before any mutation. Give the provider bounded
schema locations and clear repair guidance. A corrected call must save a
monitor and allow one wake without duplicate effects.

**Steps to reproduce**

1. Call `set_task_monitor` with `idempotencyKey`, `nextCheckAt`, and
`notes` at the top level.
2. The schema rejects the call because scheduling fields belong inside
`monitor`.
3. Before this change, the provider received no guidance about the
required shape.

**Paperclip version or commit**

Reproduced against master `35c75b56d4` with a failing Rust regression.

**Deployment mode**

Source checkout. This affects the native runner tool bridge.

## What Changed

- Add monitor-specific repair guidance to the runner's existing safe
schema error path.
- Keep feedback within 512 bytes and omit submitted values and unknown
field names.
- Show the nested monitor request in the production tool description.
Refresh generated contracts and catalog identities.
- Test flat and nested invalid input, private value handling, and
unchanged authorization errors.
- Test rejection, correction with the same key, saved schedule and
audit, receipt replay, and one timer wake with real PostgreSQL and the
native tool authority.
- Update execution documentation and the task verification recipes.

## Verification

- Red/green: the Rust provider error regression failed on master because
monitor repair guidance was absent. It passed after the fix.
- Passed: 29 PostgreSQL monitor and scheduler integration tests. These
use the real tool authority and scheduler, with a no-op process agent
for wake delivery.
- Passed: the native Codex server vertical-slice test. It runs the
rebuilt Runner binary with a fake provider and checks durable results
and session resume.
- Passed: map structure checks, Rust formatting, and `git diff --check`.
- Passed locally: full repository `pnpm -r typecheck`, `pnpm build`, and
all 392 Rust library unit tests.
- Passed on commit `3b667ad24763c1828edd48f56ef7a10766aeb946`: [CI run
39290889768](https://github.com/paperclipai/paperclip/actions/runs/39290889768),
including all server, Runner, serialized, browser, typecheck, build, and
canary gates. Across the PR, 56 checks passed and four conditional
checks were skipped. No check remains pending or failed.
- Greptile: 5/5 on that exact commit. The check concluded success, with
no review comments or unresolved threads.
- The duplicate local `pnpm test:run` attempt did not complete. It was
stopped after the full CI suite passed; it is not counted as a local
full-suite pass.
- The first PostgreSQL attempt could not bind localhost inside the shell
sandbox. It passed with normal localhost access. The first broader Rust
attempt had 37 socket-permission failures and 355 passes; all 392 passed
with localhost access and no code change.
- Live model recovery was not run. Local execution policy did not
authorize an extra acceptance run through the signed-in provider
account. This PR does not include a deployment or recovery of an
existing task.

## Risks

- Error feedback must not reveal submitted values. Tests cover private
values, unknown keys, nested constraints, length bounds, and unchanged
generic authorization errors.
- This changes guidance only. It does not relax the schema, retry calls
automatically, or change scheduling authority.
- A new runner binary and refreshed provider contract must reach the
target instance before agents receive this guidance.

## Model Used

OpenAI Codex, GPT-6, with reasoning, tool use, and code execution. The
exact runtime suffix and context window size are 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
- [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-10-19 12:37:28 -05:00
DottaandPaperclip 3e5a9f5afe perf(ui): load recent tasks with bounded summaries (#16851)
Replace passive recent-task detail reads with bounded, authorized summaries. Keep account isolation, stored history, task actions, and live recovery behavior.

Overlap access checks with shell settings and avoid duplicate session and health reads on the first healthy socket opening. Retain domain reconciliation.

Add focused coverage and local performance evidence. Isolate the existing cache capacity test from entry expiry on slow CI runners.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-19 12:13:28 -05:00
DottaandPaperclip 23b2ceb0d1 feat(connections): add unified Google Workspace connector (#15545)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connected Apps supply governed tools to those agents.
> - Google services currently require separate connections or one broad
request.
> - Users need one account and control over which services it can
access.
> - A picker must change the OAuth request, not just the screen.
> - This pull request binds selected services to consent and tool
access.
> - The benefit is simpler setup without enabling unselected tools.

## Linked Issues or Issue Description

**Subsystem affected**

Connections catalog, OAuth grants, and the MCP tool gateway.

**Current behavior**

Google setup uses separate service profiles. A combined request alone
cannot express the user's choice before Google consent. Accumulated
Google grants can be broader than a new request.

**Proposed behavior**

Offer one Workspace connection. Let users choose Gmail, Drive (including
Docs, Sheets, and Slides), and Calendar. Start all three with read and
write access. Let users disable groups or choose read-only access. Do
not offer Chat, Contacts/directory, or cross-service Search in new
setup. Bind selected scopes to durable OAuth state. Cap effective tool
access to both the saved request and provider-reported consent.

**Reason and benefit**

Users can choose services without managing several accounts. Existing
company, identity, agent, and action-policy controls remain in force.

**Breaking changes**

No database migration. Existing service connections and grants remain
supported. New Workspace requests require the companion broker change in
https://github.com/paperclipai/paperclip-cloud/pull/823. Old brokers
reject narrowed requests safely.

Related work: #14740 reduced Google scopes; #14774 introduced the
earlier catalog hold. #15412 proposes a separate Gmail REST
implementation. This maintainer-requested change extends the existing
Connections and governed tool gateway paths. It does not replace them.

## What Changed

- Add one Workspace catalog entry and a namespaced action catalog.
Retain legacy definitions and saved accounts.
- Use the approved production service picker in Apps and task-hosted
setup. Keep dropdowns between names and toggles. Block empty selection.
- Derive exact scopes from a closed registry. Default selection requests
nine scopes. New requests exclude Chat, Contacts/directory, and Search
scopes.
- Bind selected scopes through managed and customer-owned OAuth state,
callback, claim redemption, and refresh.
- Cap accumulated Google grants to the saved selection. Recheck
grant-specific permission at discovery, listing, and dispatch, including
cached actions.
- Restore the current subject's saved request on reconnect. Block on
grant-load failure. Preserve draft selection on cancel and retry. Do not
create an account on picker cancellation.
- Preserve healthy services during partial outages, without combining
grants across identities. Keep writes from being automatically replayed.
- Preserve the original 21-scope legacy Workspace envelope contract as
individual profiles evolve.
- Add production-component Storybook stories, request validators,
consent regression tests, and rollout guidance. Integrate the stories
with the current feature catalog while preserving their IDs.

## Verification

- Integrated branch merges current master and has no merge conflicts.
- Full workspace build passed on the integrated checkout.
- Token gates passed. Storybook catalog structure check passed: 283
files and 2,750 stories.
- Final affected app suites: 914 passed. This includes 502
database-backed service/gateway tests and 412
UI/shared/validator/broker-handoff/governance tests. The production
picker tests cover defaults, identity-specific reconnect, and
failed-load recovery.
- Full workspace typecheck passed after adding required current-master
Storybook annotations. The final UI build also passed.
- The full repository suite is still running and includes the two
pre-fix retry assertions. Both were updated for the current gateway's
explicit-retry contract and pass in the clean 502-test database run. No
complete final-head full-suite pass is claimed.
- The initial local database startup failure came from missing
native-library symlinks in the fresh dependency install. The package's
postinstall repair fixed it; the clean database-backed run has no
skipped tests.
- Broker focused suite: 47 passed, including real signed session →
callback → claim redemption and wrong-scope rejection. Full broker suite
before the final test-only follow-up: 3,562 passed, 103 skipped.
- Real integrated-app walkthrough: Connectors → Workspace →
customer-owned app → service picker. Verified all three defaults,
empty-selection blocking, cancel/reopen with the selected read-only
access preserved, preserved form values, and zero saved connections
after cancel. Credentials were synthetic; no Google grant was made.
- Current-head CI and Greptile review remain pending. Previous-head
results are not treated as current.

## Risks

Ship the companion broker before app instances send narrowed requests.
Enable the intended Workspace client/profile separately on the target
broker. This pull request does not deploy a tenant app, start a fleet
rollout, alter Google Console, or upgrade the pinned reviewer stack.

The three-group picker is not proof of live provider access. Before
production, verify a real selected-service grant, reconnect, refresh,
allowed reads/writes, and denied unselected actions on the isolated
staging reviewer app. Google verification and preview enrollment remain
separate requirements.

Legacy service profiles stay compatible. New grant metadata keeps
provider scope evidence separate from requested scope evidence. Missing
or unsupported evidence fails closed. No scope union across user or
organization grants is allowed.

## Model Used

OpenAI Codex, GPT-5-based coding agent, with repository editing, code
execution, and browser tools. The exact serving model ID and
context-window size 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 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 issue
ID
- [ ] I have run all final-head 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 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-10-19 12:07:30 -05:00
18e9ca7277 fix(server): retry read-only delivery lookups after a pooled disconnect (#16859)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Execution workspaces have a close-readiness check. The board uses it
before it archives or cleans up a workspace. The terminal-workspace
reaper and workspace hydration use the same delivery assessment.
> - The delivery assessment reads the source issue tree and the pull
request work products of the source issue.
> - A pooled database connection can become stale. Then postgres.js
rejects the query with `write CONNECTION_CLOSED`.
> - The issue-tree read had no retry. One stale socket failed the full
close-readiness request with a 500.
> - The database client does not replay disconnects globally, because a
write can commit before the disconnect (#14773). Callers that know a
lookup is read-only opt in with `retryIdempotentDatabaseOperation`
(#14873, #15248, #15300).
> - This pull request wraps the two read-only delivery lookups in that
helper.
> - The benefit is that close readiness, hydration and the reaper
recover from one stale pooled socket.

## Linked Issues or Issue Description

Refs #14773, #14873, #15248, #15300 (same retry pattern for other
read-only lookups).

**What happened?**
A hosted staging server returned an error for an execution workspace
close-readiness request. The issue-tree query in the delivery assessment
failed with `write CONNECTION_CLOSED` through a transaction-mode
database pooler.

**Expected behavior**
A read-only lookup recovers after one transient pooled disconnect.
Persistent failures still propagate.

**Steps to reproduce**
1. Use a pooled PostgreSQL endpoint that closes idle client sockets.
2. Let a pooled connection go stale.
3. Request close readiness for an execution workspace that has a source
issue.
4. The first query on the stale socket fails and the request fails.

**Paperclip version or commit**
`master` at 9966f31.

**Relevant logs or output**
`Error: Failed query: select "id", "status", "completed_at",
"cancelled_at", "updated_at" from "issues" where ... WITH RECURSIVE
issue_tree ...` caused by `write CONNECTION_CLOSED`.

## What Changed

- `listWorkspaceIssueTree` now runs inside
`retryIdempotentDatabaseOperation`. It is a plain recursive SELECT.
- `listDeliveryPullRequestProducts` now runs inside
`retryIdempotentDatabaseOperation`. It is a plain SELECT.
- Both functions capture `sourceIssueId` before the retry callback. Each
attempt builds a new query.
- Two regression tests in the embedded PostgreSQL `getCloseReadiness`
suite:
- One transient disconnect on each delivery read gives the same
readiness result as a healthy database.
- Three disconnects on the issue-tree read propagate the last error. The
pull request read does not run.

## Verification

- `pnpm exec vitest run
src/__tests__/execution-workspaces-service.test.ts` (in `server/`):
80/80 tests pass.
- The two new tests fail without the service change. The first fails
with `write CONNECTION_CLOSED`. The second records one attempt, not
three.
- I did not run the full server typecheck or the full suite locally. The
sandbox has a 4 GB memory limit and the native `tsc` process was killed.
CI runs both.

## Risks

- Low risk. The change wraps two read-only SELECTs. It does not wrap
writes or transactions.
- A persistent outage adds up to about 150 ms of retry pauses before the
error propagates.

> 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 5.5 (`claude-opus-5-5`) in Claude Code, used as
an agent with tool use (shell, code editing, test execution) and
extended 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
- [ ] 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: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 09:51:45 -07:00
DottaandPaperclip d20cb69ce5 fix(heartbeat): preserve active retries when comments arrive (#16855)
## Thinking Path

> - Paperclip manages agents and their work.
> - Heartbeat retries preserve task ownership after a recoverable
failure.
> - The issue read model includes retries that are scheduled, queued, or
running.
> - The human comment route treated every retry in that model as parked
work.
> - A normal status comment could therefore cancel a running
continuation and return its task to Todo.
> - This pull request limits comment supersession to parked retries and
checks that state at the cancellation fence.
> - The agent can keep working when a person adds context. Explicit Stop
and Interrupt remain available.

## Linked Issues or Issue Description

**What happened?**

A Board comment on an in-progress task cancelled its running recovery
continuation. The handler read a live retry from
`getCurrentScheduledRetry` but did not check its status. The
cancellation also forced workspace recovery when copy-back did not
complete.

**Expected behavior**

A comment must preserve queued and running execution. Only a retry that
is still `scheduled_retry` may be superseded. If promotion wins the
race, the comment must keep the task in progress and follow the normal
wake path.

**Steps to reproduce**

1. Let a task retry advance from `scheduled_retry` to `running`.
2. Keep its retry reason and source run identity in the stored row.
3. Post a normal human comment, without an Interrupt request.
4. Observe the old handler cancel the run and move the task to Todo.

**Paperclip version or commit**

Reproduced on master base `9966f31bee`. The staging incident served
`f3cd3f4ea89539b68410841d39ec15a5c626007f`.

**Deployment mode**

Staging server with a remote runner. The defect is in the core comment
and cancellation path.

Refs #16835 and #16843. Those repairs cover runner health and workspace
preservation. This change prevents a normal comment from requesting the
wrong cancellation. Related #9732 promotes human wakes on parked
retries; it does not protect a retry that is already running.

## What Changed

- Check the live retry status in both comment routes: POST comments and
PATCH issue with a comment.
- Add an optional expected-status fence to cancellation. A concurrent
promotion or terminal outcome returns a no-op result.
- Make due-retry promotion honor a cancellation claim under its issue
and run row locks. A scheduler cannot promote work after cancellation
has won.
- Finish persisted cancellations of parked retries through the existing
startup and periodic recovery sweep. Preserve their original request and
retry a failed settlement without starting provider work.
- Keep the task active when guarded cancellation does not win. Do not
record a cancellation that did not occur.
- Add route regressions, real PostgreSQL race tests, and pending-retry
and explicit Stop safety coverage.
- Exercise both normal HTTP comment routes with real services, stored
Board membership, PostgreSQL, and a live child process. Assert that the
process can still perform work, the task keeps its original execution,
and no second executor starts.
- Document the comment supersession contract and update the task
feature/access maps with the local regression coverage and deployed
acceptance recipe.

## Verification

- Before the fix, all four POST/PATCH regressions cancelled queued or
running work.
- Before the fix, the real PostgreSQL race test cancelled a retry that
became running after lookup.
- The comment-route suite passes **103 tests**. The final dispatch,
cancellation, restart recovery and HTTP/live-process suites pass **119
tests**, for **222 affected tests** across these runs. They cover
comment delivery, both sides of the promotion race, concurrent terminal
outcomes, pending retries, explicit Stop, and a live process that can
continue work.
- Command: `node node_modules/vitest/vitest.mjs run
server/src/__tests__/issue-comment-reopen-routes.test.ts
server/src/services/heartbeat/run-control.test.ts`.
- The normal HTTP/live-process acceptance suite passes all **14 tests**,
including both comment endpoints with stored Board membership and
deterministic wakeup teardown.
- Review exposed a second race after the cancellation claim. Its new
PostgreSQL test failed before the dispatch guard with `promoted` and
passes afterward with `not_promoted`, followed by completed
cancellation.
- A real PostgreSQL constraint interrupts the terminal cancellation
write after its intent commits. The assembled recovery service failed to
settle that row before the repair. Afterward a fresh service settles it,
clears its task lock, cancels its saved wake, preserves the original
request and leaves unrelated parked retries alone. A repeated database
failure preserves the intent for a later successful sweep; a second
successful sweep adds no duplicate event.
- Full `pnpm -r typecheck` and `pnpm build` pass. Server typecheck and
build pass again after the final server-only review fix. A local
full-suite attempt started on `f8773bf` did not return an overall
result; its log is preserved and no local full-suite pass is claimed.
The new recovery change passes the focused suites and fresh server
typecheck/build. Latest-head CI on
`8f928adee67c089e1ac405d2ad3b169eedb8da27` is green: the full PR
workflow and commitperclip review passed; only the two optional
Storybook jobs skipped.
- Greptile reviewed final head
`8f928adee67c089e1ac405d2ad3b169eedb8da27` at **5/5**, with no
unresolved findings. All actual latest-head CI checks passed; the two
optional Storybook jobs skipped.
- `node scripts/check-maps.mjs` passes after the map updates (34 areas,
172 capability IDs); it checks structure only.
- Fixed-revision staging acceptance is pending deployment. The original
workspace remains held and its latest source checkpoint is backed up and
verified.

## Risks

- A promoted retry must keep its execution and ownership when a comment
arrives. The database status predicate and route no-op handling enforce
this at the race boundary.
- A cancellation intent must prevent promotion without leaving work
parked forever after a restart. The recovery sweep consumes at most 20
such intents per pass through guarded cancellation, and a failed
settlement keeps its intent for retry.
- A parked retry must still accept fresh instructions. Its existing
cancellation and wake behavior remains covered.
- Ordinary Stop and Interrupt calls omit the expected-status option.
Their cancellation authority is unchanged and remains covered by the
run-control suite.
- No schema migration or API request contract changes are required.

## Model Used

OpenAI `gpt-6.1-sol` in Codex, with extra-high reasoning, tool use, and
code execution. The session does not expose its context-window limit.

## 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-10-19 11:34:27 -05:00
36e4c6657f fix(sentry): report a native retry failure only when the retry ends (#16865)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server sends a Sentry `run_failure` event when an agent run
reaches a terminal failure.
> - A native run that waits for a same-run retry is stored as `failed`
with `nativePhase: "retryable_failure"`. That state is not terminal.
> - `reportRunFailure` reported that pending state. Runs that later
recovered, for example after a workspace copy-back retry, still sent a
run failure event.
> - These events make one catch-all Sentry group noisy and hide the real
terminal failures in it.
> - This pull request skips the pending retry state and reports once
when the retry ends as a terminal failure.
> - The benefit is that run failure events match runs that really
failed.

## Linked Issues or Issue Description

**What happened?**

Two staging runs had a workspace copy-back failure during settlement
(`Daytona syncOut tar command failed ... No space left on device`). The
executor stored each run as `failed` with `nativePhase:
"retryable_failure"` and `errorCode: native_session_interrupted`. Sentry
received a `run_failure` event for each run. About two minutes later,
the copy-back retry succeeded and both runs finished as `succeeded` with
`workspaceFinalizeStatus: "succeeded"`.

**Expected behavior**

A run that waits for a same-run retry must not send a terminal run
failure event. If the retry ends as a terminal failure, the server must
send one event at that time.

**Steps to reproduce**

1. Set `PAPERCLIP_SENTRY_RUN_FAILURES=unexpected`.
2. Start a native run that fails retryably. For example, make the
workspace copy-back fail once.
3. See the `run_failure` event in Sentry, and then see the run finish as
`succeeded` after the retry.

## What Changed

- `reportRunFailure` returns without a report for a native run that is
`failed` with `nativePhase: "retryable_failure"`.
- New `isNewTerminalRunFailure(before, after)`: a status change counts
as before. A failed run that leaves the pending retry state but stays
`failed` also counts.
- Three terminal writers can keep the status `failed` → `failed`. They
now use `isNewTerminalRunFailure`, so they still report once:
  - the resume reconciler's ambiguous-state write;
  - the restart recovery `blocked` write;
  - the committed-result projection (`projectCommittedRun`).
- Result-less retries already reset the run to `running` before they
start, so their terminal write still reports through the existing
status-change guard.
- `doc/observability.md` describes the new rule.

## Verification

- `pnpm exec vitest run
src/services/__tests__/run-failure-report.test.ts
src/__tests__/run-failure-sentry.test.ts
src/__tests__/native-session-resumption.test.ts
src/services/native-runtime/native-run-finalizer-telemetry.test.ts
src/services/native-runtime/native-runner-restart-recovery.integration.test.ts
src/__tests__/heartbeat-status-preserving-telemetry.test.ts
src/services/execution-control-reconciliation.test.ts` (from `server/`):
7 files, 363 passed, 9 skipped.
- New tests:
- `run-failure-report.test.ts`: a pending native retry does not report,
and a `terminal_failure` run does. Unit cases cover
`isNewTerminalRunFailure`.
- `native-session-resumption.test.ts`: a sweep that ends an unreported
pending retry sends one event.
- `native-run-finalizer-telemetry.test.ts`: a committed failure for a
pending-retry row sends one event, and a replay sends none.
- `native-runner-restart-recovery.integration.test.ts`: a restart
recovery `blocked` write for a pending-retry row sends one event.
- I removed each of the three writer changes one at a time. The matching
new test failed each time (`expected [] to have a length of 1` / `to
deeply equal [ [ ObjectContaining{…} ] ]`).
- I did not run the full server `tsc --noEmit` locally. The local
container has a 4 GiB memory limit, and the process was killed (exit
137). CI runs the typecheck.

## Risks

- A run that stays in the pending retry state and never resumes no
longer sends a run failure event. The run stays visible on the board as
failed with a scheduled retry. A later terminal write still reports it.
- The finalizer's `failed` + `retryable_failure` write for a failed
provider result also stops reporting. The terminal write that ends that
retry reports instead: retry exhaustion in `recordRetryableFailure`
reports unconditionally, and commit goes through `finalizeNativeRun` or
`projectCommittedRun`.
- A run that was reported in the pending state before this change can
report once more when it becomes terminal after deploy. This affects
only runs in flight during the upgrade.
- There are no schema, migration, or API changes. Run status, retries,
and recovery do not 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

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with
tool use (shell, code search, test runs) and a read-only code
exploration subagent. Context window: the standard window for that
model.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [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: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 09:29:50 -07:00
DottaandPaperclip 2cbca4ceb0 fix: retain channel tools across task continuations (#16806)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat channels give an agent tools for its assigned task.
> - Each later run must resolve the task and its accepted requester
again.
> - Some native runs store the task in a database column without the
older JSON fields.
> - Tool discovery read only the JSON fields. GitHub calls also required
a new inbound comment.
> - This pull request uses the durable task binding and accepted request
history.
> - Later runs retain their channel tools while current access checks
still apply.

## Linked Issues or Issue Description

**What happened?**

A GitHub task can find `begin_review` on its first run, then receive an
empty tool list on a later native run. If discovery is repaired alone, a
call can still fail because the later run has no new inbound comment.
Slack and voice tool access also read the older JSON task fields.

**Expected behavior**

A later run for the same task can find and call its assigned channel
tools. The current requester, task, company, agent, endpoint, and access
rules must still allow the call. Revoked access must fail.

**Steps to reproduce**

1. Start a GitHub task and accept its linked requester.
2. Confirm that the runtime can find `begin_review`.
3. Start a later native run with `nativeIssueId`, accepted parent
identity, and no JSON task ID or new wake comment.
4. Search for `begin_review` again. Before this change, the search
returns an empty list.
5. Repair discovery alone and call `read_pull_request`. Before the
request-history fix, the call fails with no active conversation
capability.

**Paperclip version or commit**

Reproduced in source tests before this patch. The branch includes master
at `fa50cab5685b9cdbb26ad9c610cc5b6c373d3ff4`.

**Additional context**

This is a core run-binding bug. The tests use PostgreSQL and synthetic
provider responses. They do not send live reviews, Slack messages, or
phone calls.

## What Changed

- Resolve run task IDs from durable columns, with legacy JSON fields as
a fallback.
- Use the same binding in the gateway, access policy, identity service,
and channel runtime preparation.
- Recover accepted channel request history across later runs. Keep
company, task, agent, and requester boundaries.
- Recover older wake sources through verified parent runs, including
after same-user board follow-ups. Clear the board message’s own legacy
wake fallback. Keep cycle checks without a fixed limit on valid task
history.
- Retain the GitHub origin after a board comment from the same accepted
user. Skip GitHub origin lookup results from other providers.
- Keep ordinary board tools available when the requester changes. Accept
legacy user comments without an author-type field. Still reject explicit
malformed task IDs.
- Prevent a later failure reply from replacing an earlier final GitHub
answer. Recheck this rule under the publication lease.
- Rotate the native tool contract to replace retained sessions with an
older tool list.
- Add continuation, publication, revocation, and boundary tests. Update
the access and feature maps.

## Verification

- Red: the later GitHub assigned-tool search returned an empty list
before the binding fix.
- Red: the later GitHub read failed with no active conversation
capability before the request-history fix.
- Green: runtime MCP discovery, GitHub read/begin/submit review, and
response publication pass for monitor and same-user board continuations.
- Green: Slack history, retained access controls, revocation, and voice
gateway continuation pass.
- Green: 35 channel, failure-publication, legacy-origin, long-history,
and provenance tests pass. Both review findings had failing tests before
their fixes.
- Green: 107 gateway, operation-credential, identity, and provenance
tests pass. These cover both first-run CI failures without changing
their tests.
- Green: 122 runtime, discovery-policy, and native-session tests pass; 2
unrelated tests are skipped.
- Map checks and whitespace checks pass.
- Updated to master in `cfcaba22628772d7fe1fb32b57ff7031c7072781`. The
sole conflict was two tests added at the same location. Both the
continuation test and the publication 403/401 test are retained.
- Current local verification: all 179 gateway, credential,
requester-identity, access-policy, runtime-context, and session-resume
tests passed. Repository typecheck and build passed. Map and whitespace
checks passed.
- The new review regression first returned no source for a same-user
board follow-up over legacy wake metadata. After the repair, all 27
provenance and channel cases passed. The combined GitHub
discovery/read/begin/submit path and revoked access are covered.
- The broader local channel run passed 176 cases and failed four
timing/setup cases: a 15-second Slack authorization timeout,
webhook-verification polling, a Slack acknowledgement deadline, and
Discord setup polling. All four passed in isolation without source,
assertion, or deadline changes. The earlier failure record is retained;
the exact load/order cause is not established. Full CI must pass on the
latest commit.
- Current head: `7b9a08dcbc7b8140b589742f136944270b0496bb`. Repository
typecheck and build pass on this commit. Greptile completed on this
exact commit with 5/5; all four review threads are resolved. The
final-head [CI
run](https://github.com/paperclipai/paperclip/actions/runs/39278921653)
passed: 55 checks passed and 2 intentionally skipped, with no failures
or pending checks. This includes the full sharded test matrix, browser
tests, typecheck, build, and Runner verification. Results were delayed
during the [GitHub Actions
incident](https://www.githubstatus.com/incidents/8tzbpcnl75jp). An
additional unsharded local full test run has not completed; the
completed full-suite evidence is CI.
- Earlier verification: the first PR commit failed two server suites.
Those failures were fixed and verified before this update. The original
4 GiB sandbox could not complete full local typechecking or tests; the
current checkout completed typechecking and build. The full test suite
runs through the CI shards. No full local test-suite pass or live
provider delivery is claimed.

## Risks

- Request history can restore the wrong authority if its scope is too
broad. The resolver checks each accepted parent against the task,
company, agent, and requester. Tests cover invalid and cyclic history.
- The native contract change starts a new provider session for older
contracts.
- No database migration or public API schema changes are required. Each
tool call still checks live access.

## Model Used

- OpenAI Codex, GPT-6 family. The runtime does not expose the exact
deployment model ID or context-window size. The agent used reasoning,
repository tools, code edits, and local 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-10-19 11:20:39 -05:00
Devin FoleyandClaude Opus 5.5 7fed88e78d fix(server): retry heartbeat run read checks after a dropped connection (#16857)
`canActorReadHeartbeatRun` now wraps the issue existence read and the `issue:read` authorization decision in separate `retryIdempotentDatabaseOperation` calls, so one pooled-connection drop (`CONNECTION_CLOSED`) no longer fails heartbeat run, activity, live-event and issue-source reads. Adds a regression test and a note in doc/DATABASE.md.

Refs #15248. Refs #15300. Refs #14773.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 09:17:35 -07:00
DottaandPaperclip 9179d8dcc3 fix: credit Paperclip for managed OpenRouter requests (#16850)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - AI connections choose credentials and routes independently of the
agent harness.
> - OpenRouter assigns app credit from the final request headers.
> - Harness defaults can assign Paperclip work to the underlying
harness.
> - This pull request applies one public Paperclip identity to managed
OpenRouter requests.
> - The benefit is consistent app credit across supported harnesses and
internal model calls.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

App attribution for existing OpenRouter connections and explicit
provider configurations.

**Current behavior**

Requests can omit attribution or carry the harness identity. Paperclip
does not receive consistent credit in OpenRouter rankings.

**Proposed behavior**

Use `https://paperclip.ing`, the title `Paperclip`, and the coding
categories `cloud-agent,programming-app` for managed requests to
OpenRouter. Keep credentials, routing, and unrelated providers intact.

**Reason and benefit**

The provider URL identifies the app across personal and shared API keys.
A search of public issues and pull requests found no duplicate
attribution work. This improves existing AI connections and does not add
a separate roadmap feature.

## What Changed

- Add a shared attribution policy and a parity-checked copy for the
standalone Runner.
- Apply it to managed Codex, Claude, OpenCode, and Hermes connections,
plus native Pi and explicit legacy provider configs.
- Preserve attribution across Codex config filtering, Claude environment
filtering, OpenCode proxy requests, and model-level overrides.
- Attribute direct fast-response and decision-model requests, including
custom connections to the OpenRouter endpoint.
- Add positive and negative regression tests and provider attribution
requirements to the connector playbook.
- Advance native Pi to profile 24, preserving historical identities and
binding the attribution source in its declaration and release checks.

## Verification

- Final head `6df282d2a58c2698e41127443903d6fc85b4b72f`: all CI/status
checks passed or were intentionally skipped; Greptile is **5/5**, with
zero unresolved review threads. [Final CI
run](https://github.com/paperclipai/paperclip/actions/runs/39274938069).
- Focused server/shared/config suites: 132 tests passed before the final
edge-case additions. Expanded adapter suites pass 48 tests; the final
OpenCode merge passes 15 tests; global/EU/US endpoint and policy-parity
suites pass 26 tests.
- Focused Runner suites: 85 tests passed, including model overrides and
recovery/config boundaries. Profile installation/environment/config
tests subsequently passed 72 tests (one optional distribution test
skipped); historical decoding passed 11 tests and updated recovery
coverage passed 27 tests. The Rust profile admission test and all five
native Pi launch/recovery tests passed.
- All 114 managed AI connection tests pass together. They include
custom-header preservation for legacy and native Claude runs, both
OpenRouter and other gateways, inherited headers, and unresolved secret
references.
- Actual requests from installed Codex 0.160.0, Claude Code 2.1.245,
OpenCode 1.18.34, Pi 0.74.0 and 1.0.0, and the managed Hermes runtime
carried all four Paperclip headers. A local endpoint used dummy
credentials and returned an intentional 401 after capture. Codex and
Claude retry requests retained attribution. This proves outgoing header
precedence; it is not a successful model-inference test. The first
Claude capture had an argument-separation error and sent no request;
correcting the command produced the captured requests.
- A live request through `fastResponseModel` completed with `attribution
verified`. OpenRouter recorded generation
`gen-1792420273-Ez1GUTCc7YuZ1FJMCGob` under app ID `3118063`, at a cost
of $0.00000375. The public app record maps that ID to
`https://paperclip.ing/`.
- Full `pnpm -r typecheck` and `pnpm build` passed, including a repeat
after the review fixes. The final server build stamp records commit
`6df282d2a58c2698e41127443903d6fc85b4b72f`. `pnpm check:token-gates`
passed.
- CI first caught the stale Pi source attestation; it is now a new
immutable profile. Greptile caught custom-header loss, now fixed and
covered by the complete managed-connection suite. The next CI run caught
the missing Docker allowlist entry for profile 24; the allowlist and
release smoke pins are now synchronized. Local Docker verification
cannot run because its daemon socket is absent; The exact Docker context
check passed in CI on the final head.
- The initial local `pnpm test:run` did **not** pass. It ran across
source/build edits, reported chat/tool-access collection failures, three
workspace-runtime failures, two new managed-header failures, one Dot
Runner readiness failure, and two native-session-resume failures, and
was interrupted after the final-head CI server coverage passed. Its
secrets suite also reported 91 cases skipped. The isolated tool-access
suite passed all 428 tests, and the complete managed-connection suite
passed all 114 tests. These retries establish recovery, not the cause of
the original local failures; no claim of a successful full local run is
made. Final acceptance uses immutable final-head CI plus the focused
local and live checks above.
- Final-head CI encountered one unchanged UI assertion in
`FileViewerSheet.copy.test.tsx` (missing “Copied link” feedback after
clipboard completion). That shard passed on the earlier head with
identical UI code, and all six clipboard tests passed locally. A timing
race around the asynchronous React update is suspected but not
conclusively established. The single CI retry passed, with no
product/test code changed for it. The earlier failure remains part of
this verification record.

## Risks

- Native Pi profile 24 requires a fresh provider session when
encountering a profile 23 identity; recovery tests cover that boundary.
- Harness upgrades can change header precedence. The playbook requires
actual request capture when changing provider paths.
- Externally managed agents, unmanaged harness settings, and gateways
that replace headers need separate qualification. This change does not
intercept arbitrary model calls made by task scripts.
- The existing OpenRouter entry for the Paperclip URL still displays an
old title, “PrettyFly Opus Testing,” and no categories on the final
public-page recheck. The live request received credit under that URL's
app ID. Public title propagation and leaderboard placement remain
controlled by OpenRouter.
- Global, EU, and US OpenRouter hosts are recognized explicitly; other
subdomains are not treated as OpenRouter. No database migration,
credential ownership change, or Paperclip telemetry event is involved.
Attribution contains public product constants only.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository editing, shell
execution, web research, and live API verification. The exact deployment
identifier and context-window size are 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 — the focused suites listed
above; the unsuccessful full local attempt is explicitly recorded, with
full final-head coverage supplied by CI
- [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-10-19 10:28:53 -05:00
DottaandPaperclip a7504784e5 perf(chat): avoid snapshot reads in native progress polls (#16845)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat connectors publish safe progress from native runs.
> - A recurring query joins each run to its conversation through JSON
context.
> - Large snapshots make repeated JSON reads expensive.
> - Issue-scoped runs already have a typed issue binding.
> - This pull request uses that binding and retains the legacy JSON
fallback.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The native chat-progress candidate query in
`enqueueSafeNativeChatProgress`.

**Subsystem affected**

`server/` database queries and chat publication.

**Current behavior**

The conversation join extracts `issueId` from each run's JSON snapshot.
A local plan probes the run repeatedly and reads a large snapshot for
each probe.

**Proposed behavior**

Use the run's typed `issue_id` when present. Read the JSON key when that
column is null. Keep the existing company, endpoint, event, publication,
cursor, and cadence conditions.

**Reason and benefit**

Avoid repeated snapshot reads for scoped runs. Related: #15802 changed
delivery queue scheduling; it left native progress projection on its
existing cadence.

## What Changed

- Change only the native-progress conversation join. Leave the separate
milestone query, which already uses its expression index, unchanged.
- Add a disposable PostgreSQL benchmark that captures the real service
SQL and compares complete rows on one shared fixture. It includes a
legacy null binding, unrelated tenants, 2,400 historical decoys, and 144
KiB of random bytes per snapshot (about 192 KiB after base64 encoding).
- Compare cardinality across independent fixtures. Their generated
conversation and event IDs are not deterministic.
- Add PostgreSQL regressions for a typed issue binding without the JSON
key and for the legacy NULL-column fallback.

## Verification

- Full-size paired local measurement: native baseline 57.67 ms median,
treatment 19.35 ms median, **2.98× faster**. Both return the same 41
complete rows. Five timed samples follow warmups, with baseline and
treatment alternated. The unchanged milestone query is a control.
- An independent full-size run also passed complete row equality and
measured 65.22 → 24.08 ms (2.71×).
- The small 1 KiB control passed the same 41-row equality check and was
neutral: 15.20 → 15.45 ms median. The improvement targets large
snapshots, not small payloads. A repeat of the final JavaScript entry
point also passed equality and measured 2.97× while the full test suite
was running; its wider timing spread is not the primary performance
result.
- Four PostgreSQL cases pass: typed issue scope without a legacy JSON
key, NULL-column JSON fallback, native-progress cadence, and
paused-endpoint no-replay behavior. The remaining tests in that file
were excluded by the name filter.
- Reproduce with `node --import ./cli/node_modules/tsx/dist/loader.mjs
scripts/benchmark-chat-native-progress.mjs --phase=baseline` before
applying the query change. Run the same command with `--phase=treatment`
after applying it. The tool stores SQL, parameters, plans, all samples,
and equality evidence under `.scratch/`.
- Full workspace typecheck and final server typecheck passed locally.
Four focused PostgreSQL cases passed. The duplicate unsharded local
full-suite run was stopped after the same commit passed all CI test
shards; the full local tests/build sequence was not completed. CI Build
and the aggregate verification gate passed on that commit.
- Current-head CI is green at `82c9ef9` (55 successful checks, two valid
skips). An unchanged runtime-supervision test failed in the first
attempt; its isolated local reproduction passed, and one failed-job
rerun passed on the same commit. The local reproduction runs on macOS
and does not exercise the Linux process-identity branch.
- Greptile reviewed `82c9ef9` at 5/5 with no unresolved threads.

## Risks

- The typed issue binding takes precedence when present; older rows
retain JSON fallback. Company and publication ownership checks remain in
the query.
- Measurements use local embedded PostgreSQL 18 with synthetic data. The
hosted motivation used PostgreSQL 17. Absolute timings and plans can
differ on other compute and data distributions.
- The milestone benchmark returns an empty candidate set and is a
performance control; the nonempty native comparison is the correctness
and performance target.
- No schema migration or provider network request is added. This PR does
not deploy a query change to a live database.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository inspection, tool
use, and code execution. The exact serving model ID and context-window
size are not exposed. Z-AI GLM 5.3 Prime through OpenRouter
(`openrouter/z-ai/glm-5.3-prime`) assisted the initial query treatment
and benchmark. Codex repaired the comparison, narrowed the production
change, and ran the full-size proof.

## 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-10-19 10:20:32 -05:00
DottaandPaperclip 06c5bc471d fix(skills): unblock retention for legacy run selections (#16852)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent runs can select saved skill versions.
> - The server keeps those files in a cache that must protect active and
unresolved runs.
> - Older runs can lack the newer pin map even when their saved
execution input records the full selection.
> - Finished interrupted runs can also keep a company blocked after all
execution and cleanup have settled.
> - This pull request uses existing selection evidence and recognizes
settled interruptions so safe cache expiration can resume.

## Linked Issues or Issue Description

Related: #16433.

**What happened?**

Skill cache retention reports `unknown_run_pins` for a whole company
when it finds a finished interrupted run without pins, or an older
native run whose complete selection is stored only in its execution
input. Old cache directories cannot expire.

**Expected behavior**

Release pins from fully settled interruptions. Preserve exact versions
from valid saved native selections. Continue to block cleanup when
selection evidence is missing, invalid, or belongs to another run.

**Steps to reproduce**

1. Materialize an old, restorable skill version and let its idle grace
period expire.
2. Add a finished interrupted run with settled ownership and cleanup, or
an unresolved native run with a valid saved execution input but no
modern pin map.
3. Run the retention service. Before this change, it skips the company
with `unknown_run_pins`.

## What Changed

- Treat `interrupted` as terminal only when the existing finish,
controller, finalization, and environment cleanup checks allow it.
- For native runs with no modern pin-map field, parse the saved
execution input with the existing recovery parser. Validate its digests
and company, run, agent, and issue binding.
- Keep captured version IDs protected. Unversioned skills use separate
captured asset bundles. Do not replace a malformed modern map or write
any recovery records.
- Add database regressions and document the fallback. Remove an unused
status list that no longer represented the actual eligibility query.

## Verification

- Passed 41 focused tests: `skill-version-cache.test.ts`,
`skill-version-retention.test.ts`, and
`skill-version-retention-config.test.ts`.
- The tests perform real PostgreSQL reads, directory eviction, and
restoration from saved bytes with upstream unavailable. They cover
leases, unfinished cleanup, invalid digests, invalid versions, and
mismatched identities.
- Passed `node scripts/check-module-boundaries.mjs` and `git diff
--check`.
- A read-only evaluation of the candidate selector against existing
legacy data cleared the unknown-pin blocker while retaining exact
version pins.
- Passed `pnpm -r --workspace-concurrency=2 typecheck` and `pnpm build`.
The full remote CI suite passed, including all server, workspace,
Runner, and end-to-end shards. The full local test command remains in
progress; its focused cache suites passed as recorded above.
- Greptile reviewed this head at 5/5 with no actionable comments or
unresolved threads.
- Initial local database attempts did not run the cases: sandbox access
prevented a listener, then an install with scripts disabled lacked
PostgreSQL library symlinks. After running the package's symlink setup,
the binary started and all focused tests passed.

## Risks

The main risk is releasing a cache still in use. The existing ownership
and cleanup checks remain in force. The native fallback applies only
when the modern field is absent and the saved input passes the same
parser used for recovery. Invalid or missing evidence still blocks the
company. Current versions and explicit agent pins stay protected. Saved
version rows and runtime asset bundles are not deleted. There is no
migration.

The selector reads execution inputs only for legacy native runs that
need the fallback. Normal runs still load only their pin maps and
binding columns. A representative read-only selector check completed in
98 ms; this is a sample, not a latency guarantee.

## Model Used

OpenAI Codex, GPT-6 family, with tool-assisted coding and 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 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-10-19 10:10:49 -05:00
DottaandPaperclip 9966f31bee fix(chat): keep permission failures scoped to the rejected operation (#16847)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - External channels deliver agent replies through a durable
publication queue.
> - A provider can reject one operation while other operations remain
allowed.
> - The shared error classifier treated generic 403 and permission
errors as failures of the whole connection.
> - Failure handlers then changed the user's enabled setting and removed
all assigned channel tools.
> - This pull request limits permission failures to the rejected
operation and preserves connection intent during authentication
failures.
> - Unrelated work can continue, while confirmed authentication failures
still stop endpoint traffic.

## Linked Issues or Issue Description

Refs #16137. Follows #16138, which distinguishes local authorization
errors from provider errors. This change also narrows provider
permission failures. Related #16806 handles a separate task-continuation
tool-binding defect.

A provider 403 or missing-scope response currently disables a connection
that may still support other operations. The expected behavior is a
visible operation failure with unrelated work preserved. Confirmed
authentication failures must stop sends without changing the user's
enabled setting.

## What Changed

- Classify generic 403, adapter permission errors, and Slack
missing-scope/no-permission responses as failed operations.
- Preserve rate-limit retries, known destination quarantine, and
confirmed authentication failures.
- Preserve connection status and enabled intent when publication,
provider-reply, or form-open authentication fails. The endpoint still
enters attention and its runtime stops.
- Add GitHub regressions for retained discovery and successful later
publication after 403, and no further sends after 401.
- Mark authentication health failed and fence persistent receiver
startup, background reconciliation, and receiver callbacks. Keep signed
GitHub lifecycle events available during an authentication stop. Verify
Discord reconciliation and Photon restart preserve the stop, while
transient Discord disconnects still recover.
- Update provider, publication, and modal regression expectations and
the execution contract and verification maps.

## Verification

- Red: five new classifier cases returned endpoint attention before the
repair. The signed-installation-removal regression also reproduced a
blocked lifecycle event after a 401 before narrowing the receiver guard.
- Green: all 35 classifier tests pass.
- Green: 19 PostgreSQL-backed cases pass through the production channel
services, including GitHub discovery/publication, Slack provider replies
and question modals, Telegram credential/destination failures, rate
limiting, and Discord/Photon authentication-stop persistence.
- Map structural checks and `git diff --check` pass.
- `pnpm -r typecheck` and `pnpm build` pass. All CI gates are green on
`7e379bcd98aa8363e42efe7f8a4b2589b7111ae6`; Greptile is 5/5 on that
exact commit with no unresolved findings.
- The monolithic local `pnpm test:run` was started, then stopped after
its revision passed the full CI matrix and was superseded by the
authentication-stop repair. Final full-suite verification passed in CI
shards; all 19 final local provider regressions pass.
- The tests run from this source checkout on macOS arm64 with isolated
PostgreSQL and controlled provider failures. They do not prove live
GitHub recovery or deployment. No live connection settings were changed.

## Risks

- Permission failures now leave unrelated work available. The rejected
operation remains failed and is not automatically replayed. Provider
authorization still applies to every request.
- Keeping a connection enabled must not bypass an authentication stop.
GitHub verifies blocked tool discovery and later sends; Discord and
Photon verify background reconciliation and restart cannot clear the
stop. Failed connection health is an execution gate while the endpoint
requires attention.
- Explicit disable, disconnect, signed installation revocation, and
existing destination-specific denial handling remain unchanged. No
migration or API schema change is required.
- Previously disabled connections are not automatically re-enabled
because an upgrade cannot safely infer the user's intent.

## Model Used

- OpenAI Codex, GPT-6 family. The runtime does not expose the exact
deployment model ID or context-window size. Used reasoning, shell tools,
repository edits, 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-10-19 09:54:22 -05:00
DottaandPaperclip 016e40d532 fix(recovery): preserve shutdown export ownership through finalizer drain (#16843)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Legacy adapters must save sandbox files before Paperclip releases
their source.
> - Graceful shutdown gave each adapter a shared 30-second settlement
wait.
> - When that wait ended, cleanup could stop the sandbox while the
adapter still exported files.
> - That race created a restore failure and blocked the next turn.
> - This pull request keeps export ownership through the finalizer drain
and renews its cleanup fence.
> - A successful late export can release its source and schedule one
bounded continuation.

## Linked Issues or Issue Description

Refs #15857. This corrects the timeout path introduced by the shutdown
settlement fence.
Refs #16478. That repair clears verified historical holds; this change
prevents an active export from losing its source.
Refs #16835. That merged fix handles remote native runner ownership.
This change handles legacy shutdown settlement.

## What Changed

- Keep a late adapter settlement in the shared execution finalizer set.
Wait for it before lease release, recovery classification, and retry
scheduling.
- Renew the exact owned settlement fence every 10 seconds. Use a
30-second lease, one renewal in flight, a one-second database lock
timeout, and a five-second statement timeout. Report bounded failure
categories without raw database errors or credentials.
- Refuse ordinary cleanup while the local adapter still owns settlement.
Preserve the explicit owner stop-and-retain path.
- Give the finalizer drain a further shared 30-second wait after the
initial shutdown drain.
- Document the ownership rule, the acceptance recipe, and the
controller-loss limit.

## Verification

- Red before the repair: the database-backed expired-wait regression
expected cleanup denial but received permission to stop the still-owned
source.
- Green on `615a4382c5`: all 526 tests in `recovery.test.ts`,
`legacy-workspace-restore-recovery.test.ts`, `shutdown.test.ts`, and
`heartbeat-process-recovery.test.ts` passed.
- The assembled heartbeat regression passed. It verifies no early
release or retry, joining the late owner, successful cleanup, one
durable scheduled continuation, and no duplicate after service reload.
- Safety coverage includes other-controller fencing, controller loss,
exact source retention, stop-only cancellation, completion winning the
status race, and real database lock contention during renewal.
- `pnpm -r typecheck`, `pnpm build`, and `node scripts/check-maps.mjs`
passed on the final source revision.
- A broad local `pnpm test:run` crossed the rebase and reported eight
companion supervision failures. It was stopped and its log retained. The
complete companion file then passed all 753 tests on current source.
This is not a passing full local suite; current-head CI covers the
complete repository checks.
- The 34 recovery tests include real lock-timeout classification and
credential-shaped error redaction.
- Current-head CI: 53 checks passed; two optional Storybook checks
skipped. Greptile is 5/5 on `615a4382c5`; no unresolved review threads.
- Live sandbox acceptance remains unverified. Three disposable
local-controller/Daytona attempts used legacy Codex ACP, `gpt-6-astra`,
API-key authentication, and the verified image
`ghcr.io/paperclipai/paperclip-daytona-runner@sha256:a2bd08cefb68d9217bdd75cf87a6b51f1705b18a4796eff3f97b2726a548b8fb`.
ACP initialization exited before model execution on macOS Node 26.4.0
and again on Node 24.21.0; one attempt exposed a local process-session
socket `ECONNRESET`. That does not establish the transport failure's
root cause. No attempt reached the delayed export or second turn, so
this PR remains draft pending faithful live acceptance. Probe setup
defects were retained separately from product failures, and all
test-owned sandboxes were cleaned up.

## Risks

- Shutdown can spend up to 30 more seconds joining finalizers. The
shipped Compose stop grace remains 90 seconds.
- Renewal adds at most one database operation per owned run every 10
seconds during shutdown. Lock and statement deadlines bound database
contention. The local adapter still protects its source if renewal
fails.
- Controller death or an export that outlives the whole process still
needs retained-source repair. This change does not reconstruct a legacy
export after process death or clear historical failed-restore holds.
- No schema or public API changes. Native restart ownership, approval
gates, and retry limits retain their existing behavior.
- This PR has not been deployed. It does not recover an existing
retained sandbox by itself.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository inspection, code
execution, and test tools. The exact backend model identifier and
context window were not exposed 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-10-19 09:19:09 -05:00
DottaandPaperclip 9077748894 Remove the Pipelines experiment and preserve its data (#16834)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Pipelines was an unused experiment with its own UI, API, CLI, and
automation.
> - Keeping it leaves unsupported product surfaces and extra task-detail
queries.
> - Removing the experiment must preserve data that users already saved.
> - This pull request removes the feature and keeps its database schema
and migration history.
> - Cases and Routines remain available as separate features.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Remove the unused Pipelines experiment across the application.

**Current behavior**

The experiment includes pipeline boards, stage settings, case
automation, review queues, learnings, permissions, and CLI commands.
Task detail also queries pipeline links.

**Proposed behavior**

Remove all these product surfaces and their implementation. Preserve
existing tables, records, and documents. Ignore the retired boolean in
older managed configurations so upgrades still start.

**Breaking changes**

Pipeline URLs, API endpoints, CLI commands, and `pipelines:write` are
removed. Task detail no longer includes the old `linkedCases` field. The
independent Cases API remains available. No database migration or
cleanup is included.

Related feature work: #7907, #9110, #10905, #11375, #13004, #14671,
#16133. Related issues: #9663, #10310, #10312. This removal supersedes
the feature; it does not implement those pending enhancements or delete
their saved data.

## What Changed

- Remove Pipeline UI pages, navigation, gates, clients, query keys,
helpers, and unused design tokens.
- Remove Pipeline REST routes, services, automation dispatch,
task-detail queries, and OpenAPI discovery.
- Remove the CLI commands, shared contracts, experimental flag, catalog
entry, and permission defaults.
- Remove feature-specific tests, tutorials, smoke scripts, maps, and
Storybook examples.
- Preserve database schema, migration history, and the reserved document
key used by old records.
- Keep Cases routes independent and cover obsolete stored and managed
settings.

## Verification

- Passed: `pnpm build` and `pnpm -r typecheck`.
- Passed: targeted settings, managed configuration, sidebar, settings
UI, routing, and feature-catalog tests. A first sidebar run caught a
shared Workspaces icon import; the import was restored and the sidebar
rerun passed.
- Passed: 40 tests covering Cases routes, OpenAPI discovery, retained
Pipeline table constraints, and schema snapshot drift.
- Passed: token gates, map validation, generated API metadata check,
Storybook catalog validation, and 28 map/catalog tests.
- Passed: isolated local browser verification of navigation and
Experimental settings with Pipelines absent; Cases and Routines still
open normally. Live GET/POST requests to retired Pipeline endpoints
return 404, and the retired setting is absent. CLI help has no Pipeline
commands.
- Passed: 22 access-service and agent-default-grant tests after
restoring unrelated permission assertions flagged in review.
- Local full run: `pnpm test:run` reported one failure in the unchanged
workspace-runtime port-allocation test. That test passed in an isolated
rerun. The long local run was stopped after full CI passed; it is not
reported as a complete local pass.
- Passed: all 56 checks on `def9181f3a4491d95fca1d38e9739f5b821aae3e` (2
conditional checks skipped), including build, typecheck, test shards,
and browser suites. Eleven interrupted CI jobs reported “The operation
was canceled”; their one-time retry passed. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/39255211006).
- Greptile: 5/5 on the final commit, with the only review finding fixed
and resolved.
- Sandbox socket restrictions affected the first build/API test
attempts. The same commands ran with local sockets available.

## Risks

- Existing Pipeline clients must stop using the removed endpoints and
commands.
- Existing data remains in the database and backups, but the removed UI
no longer displays it.
- Historical boolean `enablePipelines` values are ignored. They cannot
restore the feature.
- Cases and Routines must retain their separate behavior. Targeted route
tests cover this boundary.

## Model Used

OpenAI Codex, GPT-6, with repository inspection, editing, shell
execution, and browser verification. The exact deployed model ID and
context-window size are 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
- [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-10-19 08:09:46 -05:00
Dotta c6a0cf4bce test(server): retire duplicated resolveShell darwin fallback row (#16639)
<!-- 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.
> - The server prepares task workspaces in `workspace-runtime.ts`. One
helper, `resolveShell()`, picks the shell that workspace commands use.
> - `resolveShell()` computes its fallback with one two-arm ternary:
`"sh"` for win32, else `"/bin/sh"`. There is no separate darwin arm.
> - The tests for this helper had three unset-SHELL fallback rows:
linux, win32, and darwin. The darwin row repeated the linux row. It
observed the same ternary arm and asserted the same value through the
same code.
> - This pull request removes the duplicated darwin row. The linux row
keeps the non-win32 arm pinned.
> - The benefit is one less repeated registration per suite run and a
smaller platform matrix to maintain. No wall-time saving is claimed.

## Linked Issues or Issue Description

- No public GitHub issue exists for this cleanup. The underlying
problem: the `resolveShell` fallback tests registered two cases that
could not fail separately. Any change to the non-win32 fallback arm
breaks both rows at the same assertion. One row is enough to protect
that arm. The audit receipt in
`doc/plans/2026-10-17-workspace-runtime-resolveshell-test-audit.md`
records the full decision table, the deferred candidate, and the
retained rows.

## What Changed

- Deleted `falls back to /bin/sh on darwin when SHELL is unset` from the
`resolveShell (shell fallback)` describe in
`server/src/__tests__/workspace-runtime.test.ts` (6 test lines).
- Kept the win32 row (the only observation of the `"sh"` arm), the linux
row (the only needed observation of the `"/bin/sh"` arm), the
empty-string and whitespace-only rows (missing versus invalid input;
whitespace-only also pins the trim-before-check order), and the
missing-absolute-path row (the only observation of the `existsSync`
guard).
- Added the audit receipt
`doc/plans/2026-10-17-workspace-runtime-resolveshell-test-audit.md` with
evidence, commands, and the deferred candidate.
- Corrected the receipt's mutation-control record (head d99284b): the
`/bin/bash` control fails three retained rows, not one. See
Verification.
- Changed zero production lines, zero lockfile lines, and zero workflow
lines.

## Verification

- Focused owner run: `pnpm --filter @paperclipai/server exec vitest run
-t "shell fallback" src/__tests__/workspace-runtime.test.ts` (vitest
5.0.3, Node 25.9.0).
- Baseline before the edit: 9/9 passed.
- Candidate after the edit: 8/8 passed.
- Control (re-verified on head d99284b): the production fallback arm was
temporarily changed to `"/bin/bash"`. Exactly three retained rows then
failed with the same assertion (`expected '/bin/bash' to be '/bin/sh'`):
the linux unset row (the deleted darwin row's keeper), the empty-`SHELL`
row, and the missing-absolute-path row. The win32 rows and the
set-`SHELL` rows still passed (3 failed, 5 passed). This proves the
retained row carries the deleted row's failure sensitivity, and the
shared fallback value keeps two more independent guards. Production was
restored byte-exact (sha256
`335fd5332b4242ab0ff2a565323e27db48a69ddfb7bbd8d913e5148f79ff961b`
before and after), and the focused run passed 8/8 again.
- The full `workspace-runtime.test.ts` suite and the repo-wide
typecheck/test/build were not run locally; the isolated container cannot
finish the git-fixture cases inside their 15-second budgets (three
unrelated reconciliation cases time out at 15,000 ms on this host both
before and after the change). PR CI runs those lanes.
- PR CI on head d99284b: all 57 checks green (workflow run 39022073948;
the only non-success conclusions are conditional skips).

## Risks

- Low risk. The change is a six-line deletion inside one describe block,
plus a receipt correction. The only theoretical loss is a
darwin-specific fallback change, which does not exist today: darwin and
linux share the single non-win32 ternary arm. If a darwin-specific arm
is added later, that arm needs its own row and its own contract
decision.
- Open PRs #12658, #11753, and #16213 also touch
`server/src/__tests__/workspace-runtime.test.ts`, in different regions
(pnpm provisioning case, restart scoping, and worktree lock work). This
change edits only the `resolveShell` describe, so the hunks do not
collide.

> 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 be redirected — check the roadmap first. See
[`CONTRIBUTING.md`](CONTRIBUTING.md).

## Model Used

- GLM, a large language model from Z.ai. Exact model ID: `z-ai/glm-5.3`
served through OpenRouter (`openrouter/z-ai/glm-5.3`). Context window:
the session that produced this change. Capabilities used: repository
file search and read, shell command execution, vitest runs, and a
production mutation control. No model context-window size beyond the
session is asserted because it was not disclosed 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
- [ ] 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
2026-10-19 07:28:35 -05:00
DottaandPaperclip 51c81d0129 feat(sentry): link run errors to task and run pages (#16803)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators use Sentry to inspect run and server failures.
> - Reports identify the run and task, but the existing links open API
records.
> - Operators need a direct path from an error to the normal task and
run pages.
> - This change adds navigation links through the shared server Sentry
hook.
> - Saved company and task records determine the links. A failed lookup
preserves the error report.

## Linked Issues or Issue Description

Related work: #16300 added saved run API references.

**What existing behavior does this improve?**

Sentry event context for run failures, Stop timeouts, and server errors
from an authenticated agent run.

**Current behavior**

Reports show task and run UUIDs. The existing run URL opens an API
record. The operator must find the normal task page separately.

**Proposed behavior**

Add `task_url`, `run_url`, and `task_identifier` tags when saved run
metadata is available. Add `taskUrl` and `runPageUrl` to the event
context. Use the company prefix and saved task identifier in normal
board URLs.

**Reason and benefit**

An operator can open the task or run directly from the error report.

## What Changed

- Add a shared Sentry hook for events with a known run identity.
- Read only the saved company prefix, task identifier, and run identity.
Keep the lookup within the recorded company and agent.
- Include authenticated run identity on request errors. Use the existing
run identity on Stop errors.
- Bound optional lookups to one second and eight unfinished reads.
Preserve the original event on failure.
- Keep the existing API references and error grouping.
- Document the fields and add SDK, timeout, and company-boundary
coverage.

## Verification

- Passed: `pnpm -r typecheck` and the final server TypeScript check.
- Passed: `pnpm build`.
- Passed: 332 tests across the affected server suites, plus 25 final
link and real Sentry SDK tests after review fixes. The SDK test checks
outgoing event envelopes for run failures, request errors, and Stop
errors. It checks that unrelated errors receive no links. The database
test verifies saved metadata and company boundaries. It passes with
embedded PostgreSQL and with an explicitly configured disposable test
database.
- Passed in CI on `bec0cdac853efdef71041d59a66261941827653e`: the full
test matrix, typecheck, build, Runner checks, browser suites, and the
real Sentry SDK contract. All 56 active checks pass. Two Storybook jobs
are skipped.
- The full local `pnpm test:run` attempt first failed because PostgreSQL
library links were missing. The package setup script repaired the
install. The affected database suites then passed. The repaired full
local run was stopped after all CI test jobs passed; it did not complete
locally.
- Greptile: 5/5 on the final commit. All three review threads are
resolved.
- Read-only browser inspection confirms that Sentry displays context URL
values with an Open link control.
- No live test event was posted. Validation uses the real SDK with an
in-memory transport.

## Risks

- A slow or unavailable database can prevent optional links. It does not
discard the error. At most eight unfinished lookups can remain active.
- Missing or unsafe public origins omit the links. URLs longer than the
tag limit remain in context.
- This change applies to newly captured events. It does not update
existing Sentry events.
- The change adds no schema, permission, or first-party Telemetry
contract change.

## Model Used

OpenAI Codex, `gpt-6.1-sol`, xhigh reasoning, with tool use and code
execution. The exact context window is not exposed in the session
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 (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-10-19 06:47:47 -05:00
Devin FoleyandPaperclip 2f6ad2226a fix(heartbeat): reconcile stranded running agent status (#16791)
Serialize agent completion status updates with new execution starts. Repair stranded running flags through existing recovery after durable work and cleanup settle. Share exact failed-lease cleanup proof with idle sleep, bound recovery work, and keep repair failures from blocking unrelated recovery.

Verified with 54 successful CI checks, 292 affected regressions after review fixes, workspace typecheck/build, and Greptile Apex 5/5 with no unresolved comments on the merged head.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-18 22:20:41 -07:00
DottaandPaperclip 1a79c8bdc7 fix(runtime): honor provider startup budgets on sandbox resume (#16802)
## Thinking Path

> - Paperclip manages AI agents and their execution environments.
> - Follow-up runs reuse saved sandbox computers to keep their
workspace.
> - Starting a stopped or archived computer can take more than one
minute.
> - Acquisition already uses the provider's startup budget, but reuse
imposed a separate one-minute deadline.
> - This pull request gives resume the configured or declared provider
startup budget.
> - The benefit is that a healthy slow start can continue on the same
computer.

## Linked Issues or Issue Description

**What happened?**

A follow-up run failed during setup with `ReusableSandboxResumeError`.
The saved computer became ready just after the host stopped waiting. The
environment had no explicit timeout. Its provider declared a five-minute
startup default, which the resume path ignored.

**Expected behavior**

Resume must honor the configured startup budget or the provider's
declared default. It must retain the same lease. Failed or uncertain
resumes must keep the saved computer.

**Steps to reproduce**

1. Use a reusable sandbox provider with a startup budget longer than one
minute.
2. Retain its lease and start a follow-up run.
3. Make provider resume finish after 61 seconds, within that budget.
4. Observe that the old host rejects at 60 seconds.

**Paperclip version or commit**

Reproduced on `aaeff418cf72341c674ff3393cd94f40dc4855f6`.

**Deployment mode**

Hosted sandbox execution. The regression uses a local isolated
PostgreSQL database and controlled worker RPC timers.

Searched open and closed PRs and open issues for sandbox resume and
timeout fixes. No duplicate fix was found. Related acquisition timeout
handling already exists on the base branch.

## What Changed

- Use the provider's declared acquisition timeout when no explicit
startup timeout exists.
- Apply the resolved RPC budget to the shared resume/retry deadline
instead of 60 seconds.
- Add two deterministic 61-second resume regressions for declared and
explicit startup budgets. Assert exact RPC budgets, including the
30-second margin, and check that the same lease remains active without
replacement.
- Document the timeout behavior, provider-author contract, and
verification recipe.

## Verification

- Red: both new cases failed before the production change with
`ReusableSandboxResumeError`, caused by `Plugin RPC timed out`.
- Green: `pnpm exec vitest run --fsModuleCache
server/src/__tests__/environment-runtime.test.ts` passed all 163 cases.
The final review follow-up also passed both slow-resume cases with exact
RPC-budget assertions (330 seconds by declaration; 150 seconds by
explicit config).
- An earlier full run passed the 161 existing cases but timed out in the
two new tests because their fake clock also captured database
scheduling. The corrected test restores real timers before lease
persistence. The complete rerun then passed.
- `node scripts/check-maps.mjs` passed.
- `pnpm -r typecheck` and `pnpm build` passed locally.
- Started `pnpm test:run`, then stopped the duplicate serial run in
favor of complete parallel PR CI. The repository timing data totals
about 126 minutes for server suites alone. Full parallel CI passed on
the final head.
- CI attempt 1 had one unrelated failure:
`FileViewerSheet.copy.test.tsx` expected the asynchronous `Copied link`
confirmation before React rendered it. That test and component are
unchanged from the base branch. All six cases passed unchanged locally.
A single rerun of the failed shard passed; attempt 2 of the full
workflow succeeded. The timing-race diagnosis is an inference from the
test helper, not a claim that this PR repairs that UI test.
- Greptile scored the final head 5/5. Both review findings are fixed and
both threads are resolved.
- The consequential assumption is that provider startup may exceed one
minute. The test preserves the RPC timeout race with controlled timers
and uses real lease persistence. Read-only provider evidence also showed
the retained computer ready just after the failed run ended. The patch
has not been deployed to that instance.

## Risks

- A slow or unavailable provider may hold setup for its configured
startup budget instead of one minute. Retries still share one finite
deadline. Providers with no explicit or declared timeout keep the
one-minute default.
- Lease identity, company scope, backup validation, and replacement
decisions use the existing paths. No schema or dependency changes are
required.

## Model Used

- OpenAI Codex, GPT-6. This session supports reasoning, tool use, code
editing, and test execution. The exact runtime variant and
context-window size are 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-10-18 22:04:23 -05:00
DottaandPaperclip b85a69b334 test(server): record observer load in native event replay (#16800)
Record observers and polling in synthetic native replay measurements, with zero-viewer controls and correctness checks.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-18 21:58:32 -05:00
DottaandPaperclip 023f4a5d0c fix: preserve repository cache negotiation refs (#16687)
## Thinking Path

> - Paperclip manages agent work and its execution environments.
> - A fresh repository task needs an independent checkout before its
runner can start.
> - The object cache from #16487 should reduce repeated network
transfer.
> - The cache kept Git objects but dropped remote-tracking refs during
its bare clone.
> - Git needs those tips to negotiate which objects it already has.
> - This pull request preserves the tips in a versioned mirror cache and
records explicit cache outcomes.
> - The benefit is less repeated transfer and clearer evidence when a
cache does not help.

## Linked Issues or Issue Description

Refs #16487 and #16454. No duplicate cache-negotiation fix was found in
the public PR search.

**What happened?**

A valid object cache could make a fresh clone slower. A controlled
staging probe took 45.87 seconds and received 184.39 MB even though the
reference already held the objects. An earlier probe took 52.33 seconds.
An uncached clone took 20.94 seconds.

`git clone --bare` copied the pristine checkout's objects, local
branches, and tags, but omitted its remote-tracking refs. The source had
about 1,200 remote branches. Git could not use the missing tips to
negotiate those objects.

**Expected behavior**

Keep the pristine reference's negotiation tips. Each task must still
authenticate online, use the current remote refs, and end with
independent Git objects.

**Steps to reproduce**

1. Clone a repository with many remote branches into a fresh checkout.
2. Publish a reference with `git clone --bare --no-hardlinks` from that
checkout.
3. Clone the remote with `--reference-if-able` and `--dissociate`.
4. Compare with a reference that retains the remote-tracking tips. Use
Git Trace2 and count received pack bytes.

**Paperclip version or commit**

The staging runtime was `27ab902d3db2770ada79c9f42a9c06e1d346f34b`, with
Git 2.47.3. The cache implementation was unchanged from #16487.

**Deployment mode**

Docker on a persistent application volume. The probe used the
application file owner and the public Paperclip repository. It did not
start agent tasks or alter the application cache.

## What Changed

- Publish pristine object caches with `--mirror` to retain
remote-tracking tips.
- Put cache format version 2 in the key and receipt. The first checkout
builds a new generation. Existing generations stay under the current
storage limits.
- Keep the existing online authentication, current remote refs,
credential and company isolation, independent objects, quotas, and
fallback behavior.
- Add closed Honeycomb cache outcomes and a boolean that states whether
a reference was supplied to clone.
- Document that a lookup hit or supplied reference does not prove Git
avoided transfer.

## Verification

- Controlled staging component experiment: a disposable reference copy
held exactly the same 210,057 objects as the original. It added 1,187
advertised branch tips whose commits were already in those objects.
- Before: 45.87 seconds and 184.39 MB received, one sample in this
comparison.
- After: 12.20 and 14.58 seconds; median 13.39 seconds. Received pack
sizes were 1.99 and 1.95 MB.
- All comparison clones used the same current remote HEAD and ended
without an alternates file.
- The remaining repack took 9.72–9.81 seconds. Checkout file writing
took 0.86–0.96 seconds.
- The staging experiment restored tips on a disposable cache copy. It
did not deploy this patch or measure complete agent latency.
- Confirmed both staging scratch locations were empty afterward. The
original cache timestamps stayed unchanged. The temporary operator SSH
key was revoked and its local files removed.
- TypeScript 5.9.3 transpilation reported zero syntax diagnostics across
the four changed TypeScript files. `git diff --check` passed.
- The new negotiation regression fails with the old `--bare` publisher
and passes with the mirror publisher.
- Focused Vitest suites: 26 tests passed across repository-object-cache
and execution-preparation-timing. These cover independent objects,
current refs, unavailable/revoked remotes, scope separation, invalid
storage, tracing isolation, and endpoint-off behavior.
- The first full focused run passed 24 tests but failed its existing
localhost HTTP fixture because the sandbox denied `listen` on
`127.0.0.1`. The rerun with local loopback permission passed all 26
tests.
- Server semantic typechecking passed with `tsc -p server/tsconfig.json
--noEmit` after building the required workspace declarations. Initial
attempts lacked generated dependency outputs; the completed dependency
build and rerun passed.
- A full application build was not run locally. CI passed: 55 checks
passed and two optional checks were skipped. Greptile is 5/5 on the
current head, with both findings resolved.

## Risks

- Version 2 causes one cold cache rebuild. Old cache generations retain
their disk usage, and the existing quota can prevent publication.
- A cache still needs a full repack to produce an independent task
checkout. This PR does not remove that cost.
- The component experiment establishes the negotiation effect on
staging. It does not establish an end-to-end agent speedup or the
under-30-second goal.
- The new trace fields remain behind the existing OTLP gate. Their
values are closed enums or a boolean. They export no refs, paths, URLs,
cache keys, credentials, or error text.

## Model Used

OpenAI Codex, GPT-6 family, with code and tool use. The exact serving
model ID and context window are 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
- [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-10-18 21:28:20 -05:00
Devin FoleyandPaperclip 1558d9962c fix(idle): exclude completed feedback history from background work (#16764)
Allow private feedback history and acknowledged uploads to stop blocking idle sleep. Pending, failed, unfamiliar, and inconsistent delivery records remain blocked; preserve all other work and cleanup gates.

Verified with 220 idle-safety tests, workspace typecheck/build, full CI, and Greptile Apex 5/5 on the reviewed head. Local full-suite limitations and isolated rechecks are documented in the PR.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-18 13:56:08 -07:00
Devin FoleyandPaperclip 5dced3c766 perf(tools): narrow profile and attention catalog reads (#16761)
Read only the catalog, connection, and invocation fields needed by profile summaries, reviews, and attention counts. Preserve company scope and response contents while reducing query payloads.

Verified with 445 affected service tests, workspace typecheck/build, full CI, and Greptile Apex 5/5 on the reviewed head. Local full-suite limitations and isolated rechecks are documented in the PR.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-18 13:56:04 -07:00
DottaandPaperclip 1678aae862 fix: expire unused bases with generated repository ignore metadata (#16695)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Finished tasks can release Git caches that Paperclip can restore
later.
> - Nested repository preparation adds an ignore entry to the base
repository.
> - Base cleanup currently treats this generated entry as custom
metadata.
> - This pull request accepts the exact generated entry and keeps other
metadata protected.
> - Unused private bases can then expire with their workspaces and
return on demand.

## Linked Issues or Issue Description

Refs #16691. Related #15404 and #14443 change repository preparation or
sync, not base expiration.

**What happened?**
A finished workspace with a nested project repository expires, but its
unused private base remains with `custom_git_metadata`. Normal
preparation added `/.paperclip-repositories/` to the stock Git exclude
file.

**Expected behavior**
Cleanup removes a verified, unused base with this generated entry.
Custom metadata still prevents base deletion.

**Steps to reproduce**
Create an isolated workspace with a nested repository through normal
preparation. Finish the task, wait for the retention period, and run
expiration. The workspace disappears but its private base remains.

**Paperclip version or commit**
790b729086.

## What Changed

- Accept stock `info/exclude` bytes or stock bytes plus the exact single
entry produced by Paperclip.
- Verify base deletion and restoration of both repository commits and
settings after upstream advances.
- Preserve custom patterns, comments, extra bytes, duplicate entries,
and symlinks.

## Verification

- Captured a failing lifecycle baseline: the workspace expired but the
base remained with `custom_git_metadata`.
- Both new real Git/PostgreSQL lifecycle cases pass. Restoration returns
main and nested commit A after upstream moves to B, preserves settings
permissions, and permits a subsequent commit.
- Six focused metadata controls pass. The retained baseline fixture
passes the storage check without edits to its files.
- Server typecheck passes. Full local build passes. Required CI is
tracked on this PR.
- Independent review found no actionable findings. Staging reclamation
and product reopening remain deployment acceptance checks.

## Risks

This expands a deletion allowlist. Matching is byte-exact and limited to
the generated suffix. Other ownership, authenticated fetch, consumer,
file, and Git history checks remain required. No schema or retention
changes.

## Model Used

OpenAI Codex (GPT-6), with code execution and independent agent review.

## 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-10-18 04:40:05 +00:00
DottaandPaperclip 2befcd9a0a Harden Board CLI approval and native verification fixtures (#16482)
Preserve governed Board CLI authority and strict verification fixtures on the Muse stack.

Keep approval/cancel ownership, current membership/key authority and durable first-change audit atomic. Bound Retry-After scheduling within the original challenge; never automatically resubmit consent. Retain descriptor ownership until identity-based cleanup and close it on success and error. Keep strict Git-origin and synchronized provider-entry fixture assertions.

Related public work: LukeAbell's existing PR #13919 proposes the same production descriptor-lifetime fix. This independently measured local integration retains the original tests and adds real-descriptor coverage. Do not treat this local integration as ownership of that contribution.

Carry actual merged UI source 896f3c7f3b through a normal forward merge, preserving canonical workspace recovery, Muse authority and existing migration bytes. Current-head CI and substantive review remain merge gates. Complete qualification of the final immutable canonical source and actual provider acceptance remain separate.

Refs #16482, #13919.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-17 23:22:57 -05:00
DottaandPaperclip 7c7d2d8d2c fix(runtime): continue from saved sources after workspace loss (#16690)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The runtime must preserve saved work and prevent duplicate
execution.
> - Older cleanup could destroy a sandbox before its workspace export
finished.
> - The existing recovery controls require either the original sandbox
or recovered original files.
> - Surviving attachments can support a rebuild, but they do not prove
that missing edits were recovered.
> - This pull request adds an explicit reconstruction decision and one
fresh continuation through the normal execution gates.
> - Operators can continue useful work while the original failed run
remains truthful.

## Linked Issues or Issue Description

**What happened?**

A historical failed export can have an accepted result, a prepared
workspace descriptor, and a confirmed destroyed sandbox. Its notice can
also say `new_source_execution_path` and disappear. The task then has
neither a truthful original-file repair path nor a supported
reconstruction path.

**Expected behavior**

Keep the missing-file obligation visible. Let an authorized operator
choose surviving task attachments and record lost work and external
action outcomes. Start one fresh continuation after current execution
checks. Keep the old result and failed export intact.

**Steps to reproduce**

1. Seed a failed native export with a prepared descriptor and an exact
destroyed-lease receipt.
2. Resolve its notice with the historical `new_source_execution_path`
bookkeeping value.
3. Read the task. The baseline hides the hold even though no source
reconciliation exists.
4. With this change, choose **Continue from saved sources** and submit a
reconstruction decision.

Related public work: #16451 preserves healthy warm sessions. #16583
prevents destructive cleanup of unexported work. This change handles
historical source loss that those fixes cannot undo. Searches of open
and closed work found no equivalent reconstruction endpoint.

## What Changed

- Add a board-only reconstruction endpoint with `runtime:manage` and
task visibility checks.
- Validate the exact run, result, descriptor and destroyed lease. Reject
active copyback, competing owners, newer work, stale task status, and
foreign attachments.
- Record attachment hashes, missing work, and external action outcomes.
Preserve the original failed run, accepted result, prepared descriptor
and terminal failure.
- Hold other continuation paths until the durable reconstruction intent
admits its successor. Record that successor in the same transaction and
preserve the retry count.
- Add an operator control that distinguishes reconstruction from
original-file recovery. Update the recovery runbook and capability maps.

## Verification

- Exact baseline source returns no blocker for the destroyed-source
fixture. The same fixture returns a required recovery hold with this
change.
- New real PostgreSQL and assembled API/heartbeat suite: 25/25 pass. It
covers duplicate submissions, lost acknowledgement, context reset,
source identity, task ownership, concurrent execution attachment scope,
later human blocks, deleted sources and agent pause.
- Existing export retry, explicit continuation and recovery-action
suites: 386 cases pass. One new-fixture constraint error in the combined
run was corrected; the full new suite then passed.
- UI recovery suites: 46/46 pass across three files. They cover disabled
actions, loss acknowledgement, failure retention and runtime authority.
- `pnpm -r typecheck` and `pnpm build` pass. The first sandboxed
typecheck attempt could not open the TypeScript IPC socket; the
authorized rerun passed.
- Module boundaries, map checks, token gates and diff whitespace checks
pass.
- OpenAPI route coverage: 21/21 pass. The first CI head exposed a
missing endpoint registration; this head adds the registration and the
focused suite passes.
- Review identified a missing dispatch-time check and an isolated
attachment cache. Both are fixed. Claim and final handoff recheck the
exact successor, sources and current execution gates. A controlled
post-claim operator block prevents the assembled heartbeat from entering
the provider. The shared attachment cache refreshes uploads and removes
deleted selections.
- Final focused run: 180/180 pass across six suites, including
reconstruction, existing dispatch/stale-queue contracts and UI recovery.
- A second review reproduced cancellation by an already satisfied
historical connection card while the task was `todo`. Read-only
connection availability now works before checkout; active-task mutation
checks remain strict. The baseline failed two cases; after the fix all
74 connection and reconstruction tests pass, including revoked access,
pending questions and pending approvals.
- All current-head CI gates pass on
`9d197236da11fa24f1ceadf5589cb2b81179d824`, including general/serialized
tests, Runner, build and browser gates. Greptile is 5/5 for that exact
head with no unresolved threads. The full local `pnpm test:run` is still
running its serial server group; no full local pass is claimed. Live
staging recovery is pending deployment.

## Risks

- Reconstruction cannot restore missing bytes. The operator must
identify surviving sources and actions that must not be repeated. The
agent must verify those attachments before rebuilding.
- This path is limited to exact, confirmed destroyed remote sources with
an accepted result. Retained or uncertain sources keep their existing
repair path.
- No schema migration, credential change, budget increase or
warm-session policy change is included. Normal pause, ownership, budget,
approval and dispatch gates still apply.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use and code execution.
The session does not expose an exact backend 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)
- [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 (focused suites; full local
run limitation recorded above)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [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-10-17 22:57:10 -05:00
DottaandPaperclip 790b729086 fix: restore nested project repositories and settings after expiration (#16691)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use isolated Git workspaces with managed project repository
copies.
> - Finished workspaces can expire when Git can reproduce their
contents.
> - The saved recipe records the main commit but omits nested commits
and local settings.
> - Reopening can therefore use newer nested code and lose merged user
settings.
> - This pull request saves and restores those contents before workspace
provisioning.
> - It also permits verified FETCH_HEAD metadata so ordinary fetches do
not block safe expiration.

## Linked Issues or Issue Description

Refs #16457, #16586, #16621. Related performance work: #16579.

**What happened?**

After a finished workspace expires, its nested project checkout can
reopen at the current upstream commit instead of its previous commit.
Cleanup also treats local Claude settings as disposable, although that
file can contain user settings. Ordinary linked-worktree FETCH_HEAD
metadata prevents otherwise safe cleanup.

**Expected behavior**

Restore the main and nested repositories at their saved commits.
Preserve local settings bytes and permissions. Skip files and Git state
that cannot be reproduced. Permit standard fetched metadata only when
its commits remain recoverable.

**Steps to reproduce**

1. Prepare a managed nested project repository at commit A and add
ignored local settings.
2. Advance upstream to B, finish the task tree, and expire its workspace
and base.
3. Reopen the workspace through the normal service path. Before this
fix, nested preparation selects B.

## What Changed

- Extend the existing restoration recipe with exact nested commits,
branches, source identity, and encrypted local settings. Keep the schema
compatible with older recipes.
- Restore nested repositories and settings before provisioning. Recheck
company/project source access and preserve conflicting files on retry.
- Recheck recorded contents under cleanup locks before deletion. Persist
lock ownership before atomic publication so process exits recover safely
and foreign locks stay intact. Preserve changed or unsupported contents,
including tracked settings.
- Keep saved project repository selections through normal preparation.
Checkpoint restored contents before provisioning so failed setup can
retry without overwriting later edits.
- Accept bounded linked-worktree FETCH_HEAD records only after local
ancestry or fresh upstream proof. Preserve local-only fetched commits.
- Add real Git/Postgres lifecycle cases and focused content, access,
publication-retry, and fetched-state controls. Document the behavior.

## Verification

- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- The original real Git/Postgres experiment failed with nested B instead
of A. The same path passes with this change.
- The integrated lifecycle suite passed 42 cases in 91.66s. Related
preparation, credential, content, and Git metadata controls passed 46
cases in 24.41s. The final heartbeat checkpoint persistence case passed
separately in 8.17s.
- Coverage includes exact main/nested commits, encrypted settings and
modes, upstream failure and retry, provisioning order, concurrent
reopening, changed unique files, tracked settings, malformed metadata,
and company boundaries.
- Exact-head CI passed the implementation, typecheck, build, security,
and test matrices. One browser shard passed on a single rerun after an
unrelated fixture teardown raced an activity-log write; its feature
assertions passed in the initial attempt.
- The broad local test run was stopped after about 12 minutes of
unrelated serial tests. Full parallel CI is required before merge; no
local full-suite pass is claimed.
- Single-workspace deployment, real-backlog reclamation, and ordinary
product reopening remain required acceptance work after merge.

## Risks

- Expired Git repositories still depend on upstream access. A failed
restoration returns the existing retryable error and never substitutes
the default branch.
- Saved settings use the existing local encryption provider. Recovery
requires that encryption key to remain available.
- Unsupported files, tracked settings, unknown sources, and unverified
Git state remain on disk. This can reduce reclaimed space.
- No database migration, recovery-retention change, public API, or
fleet-default change is included.

## Model Used

OpenAI Codex, GPT-6 family, with tool use, code execution, and an
independent agent review. The runtime does not expose a more specific
model identifier.

## 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-10-17 22:54:28 -05:00
DottaandPaperclip e6dcc6b095 Connect personal Muse through secure native execution and Vault OAuth (#16448)
Add company-scoped Muse native control, OAuth, wake receiver and recovery.

Recheck current authority after waits and before effects or receipt replay. Preserve task-read scope, assignment expiry, independent holds, nonblocking reassignment and truthful cleanup provenance.

Retain source trust on progress comments and verify current Muse V8 authority through real signed-JWT HTTP requests. Preserve the upstream trimmed ordinary authentication lookup.

Refs #16448.

Preserve captured canonical queue recovery and concurrent environment preparation while retaining the scoped Muse V8 exclusion. Normal migration 0354 and existing Muse SQL remain unchanged. Fresh current-head Greptile review is 5/5 with the project-write finding addressed. Required CI and independent technical review gate the merge; maintainer override is reserved for formal approval rules.

Recheck current Muse project-write authority after all receipt/task/run/admission waits, before creation or replay. Real PostgreSQL regressions reproduce four late effects/replays on the old route; the repaired three-file treatment passes 354 cases with no skips, and the scoped server typecheck passes. Ordinary/Dot behavior is preserved.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-17 22:44:36 -05:00
Devin FoleyandPaperclip 63fbb714e6 fix(server): release idle tracking after aborted static UI files (#16685)
## Thinking Path

> - Paperclip runs work for AI agents.
> - Hosts must prove that accepted work has finished before idle sleep.
> - HTTP request tracking keeps unfinished writes active after a client
leaves.
> - Static file middleware has no returned completion promise.
> - An aborted UI download can leave its request active forever.
> - This PR completes only a matched file response and keeps other work
tracked.

## Linked Issues or Issue Description

Refs #15522. Found while qualifying #16679. A search found no duplicate
static-download idle fix.

**What happened?**

Closing a client during a static UI download leaves one tracked request
active. The response has closed, but the file middleware never calls the
wrapped response end method. The instance cannot report idle after that
request.

**Expected behavior**

A closed, matched static file response must not leave a permanent work
hold. Unfinished application writes must remain tracked. A missing file
must keep the normal fallback and error paths.

**Steps to reproduce**

1. Serve a large local file through the static UI middleware with idle
admission enabled.
2. Start the download over HTTP.
3. Disconnect the client after its first data chunk.
4. Observe that the tracked request remains active with the original
middleware.

**Paperclip version or commit**

Reproduced on the behavior in
`d30648dee89720358271c276b9fc28cf83f18be7`. This branch starts at
`cfa9dce295970a85b3d8ee14cab0eccf50bc72e2`.

## What Changed

- Mark the completion of a known read-only response without dropping
pending middleware promises.
- Wrap static UI file serving. A successful file match is required
before a closed response can complete its tracking. A late match
rechecks an already closed response. Missing files keep the normal
fallback.
- Use the wrapper for hashed assets, other static UI files, and public
development files. Preserve caller headers and cache options.
- Test both HTTP abort timings, nested routers, conservative
mounted-application holds, parent writes, mutating GET fallbacks, and
callback-only work.
- Update the idle contract and its verification map. Correct the
paused-message recipe from hosted qualification: an explicit Pause
cancels older queued work, so test new accepted input after the pause
and await the normal resume lifecycle.

## Verification

- The original two real stream-abort regressions fail with the original
Express static behavior.
- Three review regressions fail on
`e260f4694afab8447b0cb203f439cb3ccad254e8`: a client closing before file
lookup, an unfinished parent in a mounted application, and an unfinished
parent in a root without installed handler tracking. Fixed sources were
restored byte for byte after the comparison.
- Two focused suites: 16 passed. They cover nested routers, both abort
timings, hidden parent writes, late missing-file fallbacks, contents,
HEAD, conditional responses, and caller headers.
- Module and map checks pass. Map checks are structural only.
- `pnpm -r typecheck` and `pnpm build`: passed on
`f242ee739344484995d3addf81635512370778c8`.
- Full CI matrix: 54 successful checks and 2 intentional Storybook
skips.
- Apex: 5/5 on the exact current head, with zero unresolved threads.
- Full local maintained test groups are still running before final
handoff.
- The initial local broad run was stopped before changing source for the
P1 review findings. Two file-mode fixture failures in that run came from
the scratch runner's inherited `0077` mask; the same suite passes with
the normal child test mask `0022`, without source or host configuration
changes. The replacement run uses `0022` for test children and
command-scoped `init.defaultBranch=master` for existing Git fixture
assumptions.
- This PR has not been deployed to a hosted environment.

## Risks

Only a matched file served by the admitted application with installed
handler tracking can complete this way. Routers share that scope.
Mounted Express applications and roots without handler tracking keep the
existing conservative response hold; this change does not claim their
hidden writes are tracked. An unfinished tracked parent promise still
blocks sleep after a file client disconnects. Redirects, missing files,
application callbacks, and other GET requests retain their guards. No
authentication, company scope, provider cleanup, or scheduling gate is
removed. No schema or API response changes.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, source editing, and shell
tools. The session does not expose a more specific serving model ID or
its 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-10-17 20:28:57 -07:00
DottaandPaperclip 1f27427ffd perf(server): batch retained workspace reader identities and policies (#16683)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task startup checks who can read each physical workspace.
> - A shared root retains the identities of earlier runs.
> - The service reloads the same agents, tasks, projects and run
policies for each reader.
> - Database round trips grow with the retained run history and hold the
company provenance lock.
> - This pull request batches these reads within each guarded operation.
Each run keeps its own identity and policy.
> - The benefit is less task preparation time while current access
checks remain in place.

## Linked Issues or Issue Description

Refs #16424.

**What existing behavior does this improve?**

Workspace admission, repository publication and batched read
authorization.

**Current behavior**

A synthetic shared workspace with 64 retained readers makes 680 SQL
calls during a publication check. The same principals are loaded
repeatedly.

**Proposed behavior**

Load retained identities and saved policies in batches of at most 500
IDs. Load project settings once per guarded operation. Reload records
and permission grants on the next operation.

**Reason and benefit**

The local service benchmark with an injected 4 ms loopback round trip
changed from about 7.0 seconds to 0.5 seconds and from 680 SQL calls to
47. This measures synthetic PostgreSQL data, not hosted response
latency.

## What Changed

- Extract retained-reader identity loading and acquisition trust checks
into a focused service module. Select only the identity and trust fields
used by these checks.
- Batch company-scoped run, agent and task lookups. Keep each run's task
binding, responsible user and policy checks.
- Batch saved run-policy reads in read authorization. Keep company and
agent identity checks and ordinary lookup behavior for noncanonical IDs.
- Reuse project settings within one root authorization operation.
- Add query budgets, identity failures, batch-boundary coverage, policy
comparisons and grant-revocation tests.
- Document snapshot lifetime and query scope.

## Verification

- PASS: 197 focused workspace and authorization tests.
- PASS: `pnpm -r typecheck`.
- PASS: `pnpm build`.
- PASS: all current-head hosted CI test groups, Runner checks, E2E
shards, security checks and builds (55 successful checks; two unrelated
Storybook jobs skipped). The local monolithic `pnpm test:run` was
stopped after all equivalent hosted CI groups passed. It has no complete
local result; the hosted matrix supplies the full-suite proof.
- Synthetic real-PostgreSQL benchmark: 383 workspaces and 64 retained
readers; 4 ms simulated loopback round trip. Publication check: 680 ->
47 SQL calls; 7.0-7.1 s -> 0.48-0.51 s. Three concurrent checks:
20.0-23.1 s -> 1.52-2.12 s. Setup and provider execution are excluded.
Live reply timing remains unverified.
- Regression coverage compares complete batched and ordinary
authorization decisions. It checks distinct saved policies for the same
principals, missing identities, company mismatch, task mismatch,
responsible-user mismatch, revoked project grants and changes after the
first operation.
- No new schema, API or UI contract.

## Risks

- A batch must not combine different runs' identities or policies. Each
lookup and policy decision retains its run, company and agent checks.
- Snapshots last for one guarded operation. Later admissions and
publications reload data. No authorization cache survives the operation.
- Restricted project trust checks keep their existing per-run validation
path. Hosted latency remains an acceptance gate.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with xhigh reasoning, code execution
and tool use. The runtime does not expose the configured 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-10-17 21:52:08 -05:00
Devin FoleyandPaperclip e30550ef39 refactor: remove code comments added by recent PRs (#16681)
CONTRIBUTING.md says PRs add no code comments, but #16485, #16586, #16621 and #16672 added some. This removes the 215 comment-only lines git blame on master attributes to those merge commits, across 12 code files, plus one blank line the removal left doubled. Rewritten (not added) comments in scripts/assert-cloud-image-sentry.mjs and comments in .github workflows are left alone. No code changes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-17 18:55:39 -07:00
Devin FoleyandPaperclip bebeb389f1 perf(server): do not watch bundled plugins for file changes (#16677)
Bundled sandbox-provider plugins are installed from local paths inside the image, so production started a chokidar dev watcher for each of them over files that never change. createPluginDevWatcher now takes unwatchedRoots (compared in resolved and real-path form), and the app passes the bundled plugin catalog root; plugins installed elsewhere are watched as before, and a plugin moving into an unwatched root closes its old watcher and cancels any pending restart.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-17 18:39:11 -07:00
Devin FoleyandPaperclip 391dd15ff2 fix: recover deferred messages and completed unblock waits (#16673)
Recover accepted deferred messages through the latest finished issue run and
recognize exact completed agent unblock notifications as passive idle waits.

Preserve assignment handoffs, pause and Stop, failed outcomes, and cleanup
ownership. Honor local and SSH release contracts and atomically settle cleanup
claims. Add PostgreSQL recovery, concurrency, and interruption regressions.

Validation: recursive typecheck and build pass; 678 focused tests pass; full CI
passes; Apex review is 5/5 with no unresolved findings.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-17 16:53:29 -07:00
Devin FoleyandPaperclip 27ab902d3d perf(docker): start the server from a precompiled runtime bundle (#16672)
The production image started the server through the tsx loader, which resolved about 3,100 modules and transpiled about 1,200 workspace TypeScript files on every boot (7.6-20 s before listen on a live instance). A build:runtime step now bundles server/dist/index.js with esbuild, compiling in the workspace packages, and the image starts node server/dist-runtime/index.mjs. Server dependencies stay bare so runtime resolution (including the cloud image's optional peers) is unchanged; each module keeps its original import.meta location; dynamic imports stay split; the entry presents the original dist/index.js as argv[1]. The avatar worker loads through tsx's API when the main thread has no loader, tini runs as a subreaper (-s), and PR CI boots the bundle with scripts/server-boot-smoke.sh.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-17 16:22:35 -07:00
Devin FoleyandPaperclip 4415665d67 fix(server): allow proved idle waits and verify historical cleanup (#16633)
## Thinking Path

> - Paperclip manages agents, task continuations, integrations, and
their execution resources.
> - Automatic idle sleep needs durable evidence that accepted work and
provider cleanup are settled.
> - Response-driven questions, passive board escalations, and completed
connection receipts currently look like unfinished work.
> - Legacy ephemeral leases and terminal image sessions need actual
deletion proof before their history can become idle.
> - This PR adds narrow evidence-based exceptions and read-only provider
verification while preserving queues, outcomes, and ownership fences.
> - Idle instances can sleep without losing responses, automatic
reconciliation, or cleanup obligations.

## Linked Issues or Issue Description

**What happened?**

Instances with no executable work can remain awake because pending human
responses, passive recovery records, outbound integration configuration,
or completed delivery history are counted as background work. Older
failed ephemeral leases and finished setup sessions also lack the
evidence needed to distinguish retained resources from deleted
allocations.

**Expected behavior**

Permit idle sleep only for proved response-driven waits and settled
history. Continue blocking real queued work, inbound integrations
without a wake contract, unfinished accounting/retries, retained
resources, and uncertain provider cleanup.

**Steps to reproduce**

Finish an issue's producing run, leave a pending question or
confirmation, and request an owned scheduled idle report. Separately
retain a processed connection receipt or a failed ephemeral lease whose
provider allocation has already been deleted. The old checks keep those
instances awake even after executable work has finished.

Related public groundwork: #15522, #15599, #15761, #15897, #15907, and
#16325. Searched existing public idle-sleep PRs; this addresses
additional blockers in the current predicates.

## What Changed

- Recognize supported response-driven waits and passive board recoveries
without changing task state, response audiences, or continuation
policies. Bind passive issue generation into routine-only alarms too.
Keep automatically polled merge-confirmation cards awake.
- Treat processed events, delivered intents, disabled drafts, and
outbound MCP configuration as history/configuration where proved safe.
Preserve pending deliveries, downstream wake requests, and inbound
GitHub bindings.
- Permit only pristine Slack setup drafts with a matching disabled
channel connection, no provisioning registration, and no prior provider
identity/activity. A saved slash-command name remains inert
configuration.
- Repair missed routine execution-issue status hooks in bounded
awake-only maintenance. Lock and re-read exact owners, apply existing
completion/transient-failure rules, and preserve normal continuation
after an issue resumes.
- Allow human-only connection setup to wait only when no reusable active
connection of its purpose exists; available access reblocks sleep for
reconciliation. The delivery worker shares this proof, releases its
local idle hold, and retains maintenance only while already awake.
Passive-only ticks pause before admission during an owned drain,
allowing slow backups to finish; new producer notifications still
reconcile and invalidate the backup.
- Add optional `environmentInspectLease` SDK discovery/dispatch and
read-only Daytona/fake-provider implementations. Old workers remain
conservative. Daytona status inspection uses a fresh provider GET
without reconnecting or poisoning unused-worker eligibility.
- Bind historical credential reads to an unrotated initial secret
version and its immutable resolved-value hash; reject ambiguous
histories and ambient Daytona credential/API-endpoint fallbacks before
querying provider state.
- Verify bounded rotating batches of historical resources on
already-awake Cloud instances, outside readiness. Store host-owned
deletion evidence bound to exact row identity/version and reject
concurrent ownership changes. Preserve failure outcomes, cleanup/export
intents, and run continuation authority.
- Preserve cancellation provenance, defer contended routine rows
individually, and cap actual inspection RPCs across caller timeouts and
worker exits. Add database, SDK, provider, configuration-scope, and race
regression coverage and update idle protocol documentation.

## Verification

- `pnpm -r typecheck` and `pnpm build` passed on `24fd1c0f5ec`; server
typecheck/build passed again after the final coordinator-only fix in
`60f23e6e4b6`.
- Final server regressions: 258 sleep-safety/connection cases and all 17
coordinator cases passed. Earlier focused checks also covered 331
combined idle/cleanup cases, 34 custom-image cases, 39
credential/cleanup cases, 39 connection-history cases, and 80 existing
routine cases. Counts overlap and are not additive.
- SDK: 153 passed. Daytona: 406 passed with 14 existing opt-in skips.
The provider implementation also typechecks against the locked SDK used
by the Cloud wrapper.
- Dependency boundaries were exercised with real child workers holding
provider inspection replies beyond caller timeouts, a real PostgreSQL
row lock delaying one routine owner, and real connection creation →
queue notification → worker hold release → resumption after access is
enabled without another notification. A controlled six-second backup
goes through the real coordinator, task drain, work signals, and
idle-safety generation checks; maintenance permits completion, while a
new committed transaction invalidates it.
- Full local `pnpm test:run` completed its general-server phase with
21,122 passing, 29 failing, and 109 skipped tests; later phases did not
run. That long run spanned source edits and is not a final-revision
pass. The affected Slack draft assertion passes on current source.
Restoring `/usr/sbin` for `lsof` produced 233 passing tests and two
Git-fixture failures across the other five files (3 existing skips).
Both remaining assertions pass with command-scoped
`init.defaultBranch=master`; this host defaults to main and leaves both
branches in their fixture. No source/global Git setting changed for that
comparison. Original failure logs are retained.
- A parallel typecheck/build attempt raced generated Runner outputs and
failed an import. Running the build sequentially passed with no source
change.
- Local database checks use the maintained test-constructor seam with
native PostgreSQL 16.14 because bundled PostgreSQL 18 is unreliable on
this host. No database assertions were skipped in the focused runs. An
interrupted combined run was superseded by the separate passing
coordinator and safety/connection runs; no owned test database processes
remain running.
- Apex reviewed final head `60f23e6e4b615a08591e19d86443a6c35c091ce1`:
**5/5**, zero unresolved threads. All current-head CI gates are green,
with expected policy skips. The branch is conflict-free and GitHub
reports a clean merge state.
- Current-head CI initially failed `plan-task-fixture.spec.ts:66` during
fixture deletion: the final company DELETE hit
`activity_log_company_id_companies_id_fk` after the feature assertions
completed. The deletion path is unchanged here; the final diff only
changes drain-gated passive maintenance. The preceding revision passed
this shard. Failure evidence is retained in [the original CI
job](https://github.com/paperclipai/paperclip/actions/runs/39006936642/job/117321244396);
the targeted retry passed on the unchanged commit ([retry
job](https://github.com/paperclipai/paperclip/actions/runs/39006936642/job/117322535013)).
This shows recovery, not that the underlying company-deletion race is
resolved.
- These checks do not claim staging/production deployment or live
provider cleanup proof. Provider tests simulate responses. Full Cloud
staging verification requires a compatible Core/private-plugin
composition after the Core revision is on master.

## Risks

Sleep eligibility changes require the existing owned drain, final
generation validation, local-work checks, and plugin drain. Unsupported
states fail closed. Queued agent input and routine execution remain
blocked. Outbound MCP exemptions exclude inbound GitHub grants; other
unsupported inbound integrations remain awake.

The inspection RPC is optional and requires a matching live worker
method. Its actual outstanding calls are capped at two across workers
even after the caller times out. Historical lease inspection requires
its recorded plugin/config; setup inspection requires an unchanged
recorded config fingerprint. Not-found under replacement account
credentials is not historical deletion proof: ambiguous/rotated secret
histories defer verification, and initial-version reads must match their
recorded value hashes. Missing provenance (including legacy image
sessions without a recorded config fingerprint), live/stopped resources,
provider authorization failures, and concurrent changes defer
verification. Routine repair replays existing
completion/transient-failure behavior and timestamps at reconciliation
time; it does not execute or discard deferred comments. No migration or
destructive provider operation is added. The new marker does not grant
run-resume authority. Full Cloud staging validation requires a
compatible Core/private-plugin composition; no production deployment is
included.

## Model Used

OpenAI GPT-6 Codex, with repository/tool access and code execution.
Exact model identifier and context-window size are not exposed by 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 relevant tests locally; passing focused checks and
full-run limitations are documented above
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [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-10-17 07:01:32 -07:00
Devin FoleyandPaperclip 5555817c2b fix(server): let Git expiration verify public commits without a run identity (#16621)
Git expiration created its auth provider with only the issue ID; with a managed GitHub connection that provider throws outside a run ("No managed GitHub identity is available for this run"), so every upstream commit proof failed and was logged as inspection_failed. Expiration now falls back to anonymous access when the provider throws: public repositories verify, private ones stay kept. Upstream verification failures are reported as upstream_commit_unverified, and a managed checkout whose upstream cannot be reached or authenticated as managed_checkout_upstream_unavailable; local proof-store failures keep their own error.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 20:54:30 -07:00
DottaandPaperclip 669d329f25 perf(slack): avoid unused catalog revision scans (#16630)
Slack catalog discovery now checks live task, user, endpoint and credentials without calculating an unused compatibility revision. Full authority callers retain the unchanged revision and search-token path.

Validation: 44 affected cases, full repository typecheck/build, current-head full CI/E2E and security checks, Greptile Base 5/5 with no unresolved findings. Identical production catalog output with revision statements reduced from two to zero in real-PostgreSQL comparisons. Hosted latency acceptance remains pending.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 22:21:03 -05:00
Nicky LeachandPaperclip 5f5602bba7 feat(plugins): synchronize standing connection assignments (#16603)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Lifecycle plugins prepare agent runtimes outside the control plane.
> - They need committed connection assignment changes without polling.
> - A reader and its revision hooks must cover the same fields.
> - This pull request adds a bounded standing-assignment snapshot and
its matching hooks.
> - Plugins can react to assignment changes while execution keeps its
existing access checks.

## Linked Issues or Issue Description

**What happened?**

The agent runtime reader does not expose standing connection
assignments. Changes to connection installs, active profiles, and
connector feature switches do not request synchronization. Adding
company-wide invalidation also exposes lock inversions in assignment
writers and AI adoption.

**Expected behavior**

The owning lifecycle plugin can read a bounded assignment snapshot.
Every committed change to its stored fields advances the runtime
revision. Rollback removes both the change and its event. Assignment
writers finish without a lock-order cycle.

**Steps to reproduce**

1. Install a connection or bind an active profile to an agent.
2. Read its runtime inputs through the owning lifecycle plugin.
3. Rename or disable the connection, revoke the assignment, or switch
connector features.
4. Expect a committed runtime event and an updated snapshot without
periodic polling.

**Additional context**

Extracted from #16503. Catalog publication #16602 and the separate test
maintenance PRs #16601 and #16610 are merged. This PR now targets master
and is the active review. Tool-definition hooks #16604 and
access/credential hooks #16605 remain drafts without review requests.

## What Changed

- Add SDK types and an owning-plugin runtime snapshot for installed
connections, active profile IDs, and effective connector feature
switches.
- Reject more than 512 connections or 128 active profiles instead of
returning partial data.
- Add migration 0354 for the exact stored fields used by the snapshot,
with transaction-coalesced invalidation. Agent-targeted bindings and
installs notify only their old/new target agents;
project/routine/issue/gateway bindings are outside the snapshot and
produce no notification.
- Use ordered agent locks that are compatible with foreign-key
references and exclude runtime readers. Prelock complete old/new target
sets before replacing assignments or restoring managed profiles.
- Record one company baseline at delivery startup for process-managed
feature overlays.
- Lock assignment inputs before install saves, task completion, and
email assignment. Setup finalization reads the locked connection state
and prelocks company agents before activating, re-enabling, or reviving
a profile.
- Make profile binding and reassignment writes transactional and lock
parent profiles first. Keep target validation and profile/detail reads
on the reserved transaction connection, including with a one-connection
pool.
- Lock company agents in order before validated AI adoption. Keep
adoption and shared configuration writes at `FOR NO KEY UPDATE`,
avoiding an upgrade that can deadlock foreign-key inserts during gateway
creation. Configuration fields cannot change agent identity; lifecycle
transitions and deletion retain their existing locks.
- Document supported coverage and the inputs reserved for later PRs.

## Verification

- Thirteen affected suites passed: 757 tests covering runtime
hooks/assignments/skills, concurrent skill publication, tool
access/catalog, task connection intents, lifecycle delivery, email, AI
accounts, migration histories, snapshot drift, and the agent lifecycle
module. This includes the merged catalog PR's OAuth and
overlapping-refresh regressions.
- The assignment suite passes all 24 cases, including bounded snapshots,
company/agent isolation, rollback, health-field no-ops, process-start
feature overlays, and real lock contention.
- Four one-connection PostgreSQL regressions reproduce the earlier
helper-read hangs before the correction; bind, unbind, delete, and
reassign complete with it. The earlier adoption/gateway probe exposed
both lock upgrades: changing only validation still deadlocks in shared
configuration. Current scoped coverage verifies adoption with
agent-targeted binding writes; gateway-only bindings no longer
invalidate this snapshot.
- The original ordered-adoption regression reproduces PostgreSQL `40P01`
without ordered company-agent locking. Scoped-recipient tests reproduce
unrelated-peer journaling before the trigger correction and verify
repeated bind/unbind operations leave peers untouched, ignored binding
types produce no events, both reassignment recipients are reached, and
coalescing remains intact.
- Six replacement contention cases cover installs, existing setup,
activation, re-enabling, profile revival, and profile reassignment.
Negative controls reproduce `40P01` without the corresponding
target/company prelocks; all cases pass with the guards. Activation
decisions use the connection row reread under lock.
- An initial contention fixture failed because its settings connection
lacked an MCP URL. Supplying the fixture URL and controlled lookup
corrected that test setup error.
- Server typecheck, database migration numbering/safety, five-snapshot
retention, feature-map structural validation, and `git diff --check`
passed. Migration metadata preserves historical journal entries and adds
no schema change. The complete diff was reviewed for secrets and
personal data before push.
- Earlier hosted PR CI runs 38983440861 and 38985530069 passed; the
superseded promotion run 38983440470 was cancelled. Superagent
acknowledged the recipient fix and accepted the documented company-wide
cost at `359b5b2f30a8a0248177367e458663d5379810d1`. Its two standard
Greptile summaries were conditional on a later setup correction and were
not counted as independent acceptance; the setup correction is now
included here.
- At `7da246aab46274db1a120a0546abbb404c5427c7`, hosted PR run
38986958988 passed: all 55 checks succeeded, with two optional Storybook
checks skipped. Superagent passed, all review threads are resolved, and
standard Greptile independently returned 5/5 with no blocking findings
(review completed 2026-10-17 00:40 UTC). Apex independently returned 5/5
with no actionable findings (completed 2026-10-17 00:50 UTC). CI was
rechecked after Apex and remains green; the branch is mergeable against
master. Full local build and repository-wide tests were not run.

## Risks

Migration 0354 adds database functions and triggers without changing
table schema. Apply it through the normal migration flow. Agent-targeted
bindings and installs only notify their affected agents. Explicit
company-wide assignments, connection metadata, profile
activation/removal, and connector feature switches retain synchronous,
transaction-atomic company fanout. Each such transaction takes ordered
row locks and inserts up to one connector runtime event per eligible
company agent: O(number of eligible agents) work and journal storage,
with no company-size cap or cross-transaction mutation quota. This
remains an intentional scope tradeoff for this PR; deferred fanout is
not implemented. Many of these conservative changes can request
preparation even if an individual snapshot stays unchanged. Snapshot
limits fail closed. This PR provides desired assignments, not
credentials or task authorization. Later PRs must add mutation coverage
before consumers can rely on immediate synchronization of tool
definitions or credentials.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository inspection, code
execution, and testing. The exact deployment model ID and context window
are 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
- [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-10-16 17:55:47 -07:00
Nicky LeachandPaperclip 190080642e perf(tools): publish catalog refreshes in bounded chunks (#16602)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - MCP discovery publishes tools that setup and access profiles use.
> - Large catalogs currently write one row at a time.
> - Repeated page entries can produce duplicate results, and profile
writes can partly commit.
> - This pull request publishes tools in bounded chunks and makes
profile synchronization atomic.
> - The result supports large catalogs before connector runtime hooks
are enabled.

## Linked Issues or Issue Description

**What happened?**

Catalog refresh performs one database write per tool. Repeated tool
names across discovery pages appear more than once in the result.
Default-profile synchronization uses separate statements, so failure can
leave a profile without its binding. OAuth callbacks also acquire
connection/application locks in the reverse order from publication and
setup, allowing a concurrent refresh to deadlock.

**Expected behavior**

Publish at most 500 tools per catalog statement. Keep one result per
tool name, using its last descriptor. Preserve existing IDs, first-seen
timestamps, disabled actions, and unchanged review decisions. Commit or
roll back default-profile changes together. OAuth persistence must
acquire application then connection locks before secret or connection
writes.

**Steps to reproduce**

1. Refresh a synthetic MCP catalog with 2,500 tools.
2. Return the same tool on two discovery pages with different
descriptions.
3. Fail the profile-binding insert during default-profile creation.
4. Overlap personal, organization, or managed OAuth persistence with
setup finalization or discovery of a new tool.

**Additional context**

This is the first feature extracted from #16503. The separate test-only
maintenance PRs #16601 and #16610 are merged. This PR now targets master
and is the active review. Standing assignments #16603, tool definitions
#16604, and access/credential hooks #16605 remain stacked drafts without
review requests.

## What Changed

- Deduplicate discovery results by tool name and keep the last
descriptor.
- Upsert catalog rows in transactions of at most 500 tools.
- Preserve row identity and operator-disabled status on conflict.
Determine default-access candidates from the rows read under each
publication lock, so an overlapping refresh cannot restore an action
turned Off after another refresh finishes.
- Lock the application before the connection during publication, setup
finalization, removal, and all three OAuth persistence paths. The OAuth
ordering fix is included here so this PR is independently safe; it does
not depend on #16605.
- Synchronize the managed default profile, its entries, bindings, and
managed policies in one transaction.
- Add PostgreSQL publication tests and document partial-failure
recovery.
- Target the existing callback failure injection at profile creation
instead of a transaction ordinal.

## Verification

- `pnpm exec vitest run
server/src/__tests__/tool-catalog-publication.test.ts
server/src/__tests__/tool-access-service.test.ts`: 436 tests passed with
the OAuth and overlapping-refresh corrections on top of the merged
#16610 fix.
- The new tests exercise real PostgreSQL with 250 and 2,500 tools,
repeated discovery pages, preserved choices, lock contention, and
failures between chunks and during profile creation.
- Four selected regression cases fail with the production source
restored to the parent commit. The implementation was then restored and
rechecked.
- Six additional real-PostgreSQL regressions cover personal,
organization, and managed OAuth persistence against both setup
finalization and new-tool discovery. All six reproduce PostgreSQL
deadlock `40P01` with the OAuth ordering fix removed; all six pass with
it restored. Discovery uses synthetic credential headers to isolate
publication locking from credential rotation.
- Apex initially returned 3/5 on
`0d6013a9649388041975406fe4b0247cd0e695aa`, identifying an
overlapping-refresh permission race. Two new PostgreSQL regressions
cover both absent and quarantined tools; both prove an agent goes from
deny back to allow without the correction, and remains denied with it.
The test pauses one refresh after its initial catalog snapshot,
completes another refresh, turns the action Off through the service, and
resumes the stale refresh.
- `pnpm --filter @paperclipai/server typecheck`: passed.
- `node scripts/check-maps.mjs`: passed (structural validation only).
- `git diff --check`: passed.
- Reviewed the complete diff for secrets and personal data before push.
- Earlier hosted run 38975428064 failed the maximum-size newline
skill-audit watchdog; other interrupted jobs reported runner
shutdown/cancellation. The original watchdog failure did not identify
whether startup or auditing timed out, so its exact cause remains
unknown. The separate merged #16610 isolates the audit deadline from
module startup and preserves the audit hang guard. This branch is
rebased onto that fix.
- Full local build and repository-wide tests were not run. At the
previous head `0d6013a9649388041975406fe4b0247cd0e695aa`, all 55 hosted
checks succeeded (two optional Storybook checks skipped), and standard
Greptile returned 5/5 before Apex identified the permission race above.
At corrected head `dc120d2bc879c54c14347db30e74c753bcff61e6`, all 55
hosted checks succeeded (two optional Storybook checks skipped), and a
fresh standard review returned 5/5 with no open findings. The second
Apex review also returned 5/5 on that exact head (successful Apex check
completed 2026-10-16T23:36:44Z). Both earlier findings are addressed,
there are no open review threads, and the branch is mergeable against
master.

## Risks

Each successful catalog chunk remains committed if a later operation
fails. A retry completes publication. Provider discovery occurs outside
database locks. Default-profile changes commit separately from the
catalog chunks and roll back together on failure. Tests use a controlled
MCP response; they do not qualify a live provider. There is no schema
migration or new plugin API in this PR.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository inspection, code
execution, and testing. The exact deployment model ID and context window
are 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
- [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-10-16 16:40:12 -07:00
DottaandPaperclip dc499ae02b perf(server): reject shared Git cleanup paths before history scans (#16614)
Check the existing global execution/project shared-path veto before scanning retained run contexts. Preserve the full unshared-path query, lifecycle locks and all deletion-phase rechecks.

Verify with 35 focused real PostgreSQL/Git cases, full repository typecheck/build, exact-head full CI/E2E and Greptile Base 5/5. A read-only same-snapshot query pair retained the false verdict while reducing round trip from1089ms to9.4ms; this is not a full-agent latency result. The first security scan was inconclusive after an infrastructure checkout failure; one actual rescan passed.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 18:17:15 -05:00
Nicky Leach 564d4e1bce test(skills): separate audit deadline from process startup (#16610) 2026-10-16 15:52:54 -07:00
Nicky Leach c0ac2772b0 test: stabilize migration and recovery fixtures (#16601) 2026-10-16 15:19:11 -07:00
Devin FoleyandPaperclip 73659c6b27 fix(server): let Git expiration discard Paperclip-managed checkouts (#16586)
Reconstructable Git expiration rejected nearly every terminal worktree with unique_ignored_files, because Paperclip writes two ignored paths into every worktree itself: .claude/settings.local.json and the managed project checkouts under .paperclip-repositories/. Expiration now accepts the settings file, and accepts a managed checkout only through a prover the expiration worker supplies. The prover maps the checkout back to its project workspace row and proves it reproducible against that row's repository URL: worktree and stock-storage checks, no linked worktrees, no unreachable objects, and every ref, reflog and HEAD commit reachable from upstream refs fetched fresh into a proof store. Every inspection Git command now runs with core.fsmonitor disabled.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 14:31:06 -07:00
DottaandPaperclip 3db33c131e perf(slack): overlap endpoint preparation and narrow credential reads (#16593)
Prepare Slack endpoints in pairs with a per-call concurrency limit of two, and resolve only the current bot token for live tool authority. Preserve candidate-order errors, active-sibling settlement, credential rotation and authorization revocation.

Verified with real PostgreSQL regression controls, full repository CI/E2E, security checks and current-head Greptile Plus5/5 with no unresolved findings.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 16:05:46 -05:00
Nicky LeachandPaperclip d1463fb79e Preserve saved delivery deadlines across clock ticks (#16589)
## Thinking Path

> - Paperclip manages AI agent work and message delivery.
> - Delivery workers restore saved retry and maintenance deadlines.
> - The coordinator converts each future deadline to a delay and back.
> - A clock tick between those reads can move the deadline.
> - This pull request keeps the saved future timestamp.
> - A deterministic test covers the clock tick.

## Linked Issues or Issue Description

Refs #16503. This separate fix addresses an unrelated CI failure found
during its review.

**What happened?**

The unchanged delayed GitHub publication restart test intermittently
reports a wake deadline one millisecond after the saved timestamp. The
coordinator subtracts one clock reading from the deadline, then adds the
delay to a later reading.

**Expected behavior**

Keep a future saved deadline exactly. Preserve the current retry
behavior for expired deadlines during idle reconciliation.

**Steps to reproduce**

Register a task with a future `nextRunAt` timestamp. Advance
`Date.now()` by one millisecond on each read. The old coordinator
reports `nextWakeAt()` one millisecond after the saved timestamp. The
new unit test forces this sequence.

## What Changed

- Let the internal scheduler accept the existing absolute future
deadline.
- Keep relative retry and immediate wake scheduling unchanged.
- Add a deterministic advancing-clock regression. Keep the chat
integration assertion unchanged.

## Verification

- Based on `origin/master` at `c91f7a6e5f`.
- Coordinator suite and the unchanged delayed GitHub publication restart
case: 16 passed, 1346 unrelated cases skipped.
- The new regression fails against the original coordinator with the
exact one-millisecond offset.
- Server typecheck passed.
- On head `d2db3e15d6dfafd390bab59529474abebb19d09c`, all 55 hosted
checks passed, with 2 expected skips. This includes all server/chat
shards, Runner checks, build, canary dry run, security checks, and
end-to-end tests.
- Standard Greptile and Apex are both 5/5 on that exact head, with no
review threads. Apex completed after green CI; final CI verification
remains fully green and the branch is mergeable.
- `git diff --check` and the pre-push secret/PII scan passed.

## Risks

Low risk. The change keeps the saved future timestamp. Existing tests
cover retry, idle drain, preemption, and shutdown behavior. No schema or
API change is required.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository inspection, code
execution, and testing. The exact deployment model ID and context window
are 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 references)
- [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 (no
public contract changed)
- [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-10-16 12:09:38 -07:00
DottaandPaperclip 2cc7992369 Share the external Runner lifecycle and add strict Muse contracts (#16444)
Add the external Runner foundation with distinct Dot/Grok V6, canonical home-mode V7 and Muse V8 contracts.

Keep generated schemas and profiles synchronized. Bound default question-answer command IDs in a disjoint namespace while preserving existing IDs and durable replay. Preserve canonical migration history and add normally generated, replay-safe Muse schema milestones with literal preview-history fixtures.

Refs #16444.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-16 13:46:50 -05:00