Commit Graph
78 Commits
Author SHA1 Message Date
DottaandPaperclip 042051904d fix(codex): deliver configured service secrets to shell tools (#17216)
## Thinking Path

> - Paperclip lets operators assign tools and credentials to agents.
> - Legacy Codex starts provider processes and builds a separate shell
environment policy.
> - Both ACP and CLI removed every variable whose name contained KEY,
SECRET, or TOKEN.
> - This also removed service credentials that the operator explicitly
assigned, such as SLACK_BOT_TOKEN.
> - This pull request uses the resolved configuration to admit assigned
service secrets by name.
> - Every Codex launch keeps a bounded shell allowlist, including
launches without an agent identity.
> - Assigned scripts can use their credentials without adding unassigned
host secrets to shell tools.

## Linked Issues or Issue Description

Related: #16255. That PR fixes project-level exclude patterns. This PR
fixes the removal of explicitly assigned service secrets and the
fallback to an inherited policy when no agent identity is present.

**What happened?**

A Codex task could not run a Slack posting script. SLACK_BOT_TOKEN was
present in its resolved launch environment, but Paperclip removed its
name from shell_environment_policy.include_only. A live removal check
also showed that an identity-free launch without an explicit policy
could inherit an unassigned host token.

**Expected behavior**

An explicitly assigned service credential reaches shell commands.
Removing that binding removes its shell access on the next launch.
Unassigned host credentials stay outside the allowlist. Codex login
credentials and observability headers keep their separate provider
paths.

**Steps to reproduce**

1. Configure a Legacy Codex agent with a synthetic SLACK_BOT_TOKEN
value.
2. Run a shell command that checks whether the variable exists without
printing its value.
3. Before this fix, the variable is absent. Repeat through ACP and CLI.
4. Remove the binding and run a second turn. Check that neither the
removed token nor an unassigned host token reaches the command.

**Paperclip version or commit**

Reproduced in the executor regressions before the fix on master at
4dfcb4c9b8. The final change is rebased on 25f2d05282.

**Deployment mode**

Source checkout. Local macOS arm64 provider acceptance with Codex CLI
0.160.0 and Codex ACP 1.6.2, gpt-5.6-sol, and an existing ChatGPT login.

## What Changed

- Added one shared Codex shell-name policy for Legacy ACP and CLI
execution.
- Admit explicitly resolved service-secret bindings. Keep Codex login
keys, observability credentials, and private runtime transport tokens
outside that opt-in.
- Reject glob-shaped environment names so one configured name cannot
match other credentials.
- Always emit the bounded policy. Do not fall back to host inheritance
after a binding is removed.
- Updated executor regressions, the identity contract, and the paired
verification maps.

## Verification

- Red before the fix: executor regressions failed because
SLACK_BOT_TOKEN was absent in ACP and CLI, with and without agent
identities.
- Green: 267 tests passed across the two executor suites and the shared
shell-policy suite. Coverage includes host/provider isolation,
unresolved and removed bindings, glob names, identity delivery, and
names-only metadata.
- The complete Codex adapter source suite passed after the CI follow-up:
571 tests passed, 1 skipped across 31 files. Its typecheck also passed.
- The first CI run caught four stale expectations in ACP config and SSH
launch tests. Those now assert the bounded policy and the existing
command/resume behavior. No production code changed in that follow-up.
- Live CLI and ACP acceptance: run a Python presence check through each
real adapter, remove the synthetic Slack binding, and run again. The
assigned token was present only on the first turn. The unassigned host
token and OpenAI API key were absent on both turns. CLI retained its
session; ACP correctly invalidated its session after the configuration
changed. Workspace proof files persisted.
- An earlier live CLI check failed after binding removal because the
no-policy fallback exposed the synthetic host token. The final change
removes that fallback. Both live checks then passed.
- Full pnpm -r typecheck and pnpm build passed. The changed packages
were compiled again after the safety correction.
- node scripts/check-maps.mjs and git diff --check passed.
- The local pnpm test:run attempt reported failures in native
warm-session tests and was interrupted. That full-suite result is not a
pass; PR CI must establish the final repository-wide gate. One named
native failure passed alone, and the complete native executor file then
passed separately (774 tests). The original broad-run failure cause
remains unconfirmed.
- After rebase, one Gemini skill-root case timed out at five seconds
while the broad run was active. The case passed alone, and the full
focused set then passed again at the PR head (267 tests). The earlier
timeout remains part of the verification record.
- An initial broad adapter run failed because sandbox restrictions
denied loopback listeners. Running the same suites with loopback access
passed.

## Risks

- Explicitly assigned service secrets now reach shell commands. This is
the intended behavior change: assigning a credential authorizes the run
to use it, and a model-directed command can read it. This is not a
broker that hides assigned credentials from the model. Operators must
assign only credentials and service permissions authorized for the run.
Configuration and secret-access authorization remain with their existing
owners.
- Superagent initially flagged this intended assigned-credential
exposure as a P2. The inline reply records the trust-model rationale and
the documentation states it explicitly. The security scan on the final
documented revision passed without any check override.
- The launch policy contains names, not values. Log redaction remains in
place. Provider login credentials and observability headers remain
excluded from the service-secret opt-in.
- Identity-free Codex runs now also receive a bounded policy. This
removes reliance on the operator's inherited shell policy.
- Existing explicit project exclude patterns retain their behavior;
#16255 addresses that separate case.
- The change has not been deployed to a shared instance.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, and code
execution. The exact served 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
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run the focused tests locally and they pass; the full-suite
limitation is 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-22 18:17:34 -05:00
b448710986 fix: derive startup warmth from per-layer reuse evidence (#16908)
## Thinking Path

> - Paperclip helps people manage AI agents and inspect their work.
> - Agent startup can reuse a lease, workspace, Runner, process, or
session.
> - A session ID can remain the same when other resources are new.
> - The old cold/warm label did not show these separate decisions.
> - This pull request records closed reuse receipts and derives labels
from them.
> - Reports now show partial reuse and missing evidence.

## Linked Issues or Issue Description

Refs #11685. That issue tracks a specific ACPX fingerprint repair. This
change records reuse evidence across startup resources. It does not
repeat that repair.

**What existing behavior does this improve?**

Startup labels in the operator trace and Product E2E reports.

**Current behavior**

A cached runtime or a continuous session can suggest a warm startup even
when workspace staging or provider launch work occurs.

**Proposed behavior**

Record each layer's reuse decision and a closed reason. Record observed
provider launch counts. Use `warm`, `cold`, `partial_reuse`, or
`unknown` from those receipts. Keep old runs unknown when they have no
receipts.

## What Changed

- Add local run-log receipts for the lease, workspace, Runner, provider
process, and provider session.
- Count physical ACPX launches, including respawns. Preserve the reason
for a new process.
- Reuse native workspace adoption and session lifecycle evidence. Keep
native and bridged remote provider-process reuse and launch counts
unknown where physical evidence is absent.
- Show the per-run summary in retained results and the dashboard. Keep
missing legacy values explicit.
- Set the legacy trace boolean only for fully evidenced cold or warm
startup. Keep the operator OTLP gate. Add no first-party Telemetry.
- Test full reuse, workspace invalidation, two direct provider launches
with session continuity, and report generation.
- Start the final diagnostic write without waiting for persistence. Keep
lease cleanup independent of a stalled event sink.
- Keep remote provider evidence unknown after runtime setup fails or the
host relay starts twice.
- Align a stale Pi support-test expectation with current master profile
28 and its suite fingerprint. Keep the qualification rules unchanged.

## Verification

- Passed: all 319 runtime, startup-timing, reuse-summary, and native
workspace-history tests. Disposable local Git tests used the native Git
binary.
- Passed on the current commit: all 2,768 Runner E2E support tests
across 128 files. This includes report and history tests for generated
HTML and normalized JSON.
- Passed: `pnpm --filter @paperclipai/adapter-utils typecheck`.
- Passed on `df60f8dbdbfcb6d80c84cd3bf563f8d58b2f9f03`: all PR CI gates,
including repository typecheck and build, all test shards, and browser
tests. Both automated reviews are 5/5. GitHub reports 55 successful
checks, one neutral review, and two skipped Storybook checks.
- The first server shard run failed because an unchanged
workspace-runtime fixture did not accept health connections within 10
seconds. Its isolated local test and the single failed-jobs rerun both
pass. This establishes recovery; the cause of the first timeout remains
unknown.
- Passed in the hosted source run on this exact commit: recursive
typecheck, token gates, the large Runner E2E typecheck, Runner E2E unit
tests, and build. The retained `source.txt` matches this PR head.
- The extra unsharded `pnpm test:run` reached its 60-minute limit (exit
124). It has no complete verdict. The broad workflow therefore reports
failure. No assertion-failure marker appears in the retained partial
log. Full-suite acceptance uses the passing canonical PR CI partitions.
A read-only inventory check found no gaps across 1,023 general server
files, 161 serialized suites, and 20 workspace projects. The separate
chat/native Runner lanes cover the excluded server files. No tests or
timeouts were weakened. The local environment has 4 GiB of memory. Use
CI for the large Runner E2E typecheck.
- The initial report tests failed because the harness could not resolve
package imports from the repository root. Relative source imports fixed
that failure.
- The first broad local run had timeouts from the environment Git
bridge. Native Git resolves the ancestry timeout and all runtime tests
pass. The added report fixture lacked its required screenshot; the
corrected report tests pass. A stale master assertion expected Pi
profile 27, while the generated profile is 28. Updated its expectation
and exact suite fingerprint; all 78 targeted support tests pass. The
clean full support run passes all 2,768 tests.
- The three review regression cases failed before repair. They showed
remote counts of zero and two, and a completed run that waited for the
final diagnostic sink. They now pass. The stalled-sink case keeps
persistence pending while the run returns, both bridge stops run once,
and the staging lock map becomes empty.
- Hosted evidence for this commit: [source
verification](https://github.com/paperclipai/paperclip/actions/runs/39335475416),
[retained command logs and status
table](https://github.com/paperclipai/paperclip/actions/runs/39335475416/artifacts/12228829282).
All listed commands exited zero except the incomplete unsharded test
command described above.
- The physical-launch test drives the executor's spawn callback twice.
The native workspace test uses real Git repositories and verifies reuse
and invalidation. These are deterministic tests, not a paid provider
qualification campaign.

## Risks

- Consumers must handle `partial_reuse` and `unknown`. Partial evidence
no longer produces a legacy cold/warm boolean.
- Native and remote bridged provider process evidence is still
unavailable on some paths. The report shows unknown values for those
paths.
- Receipt emission is best effort. Missing receipts reduce confidence in
a label and must not change execution or settlement.
- No schema migration, first-party Telemetry event, or endpoint default
changes are included.

## Model Used

OpenAI Codex, based on GPT-6, used reasoning, repository tools, and code
execution. The exact provider model ID and context window are not
exposed to this session. The existing implementation checkpoint was
preserved from the earlier agent run.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
2026-10-19 21:52:57 -05:00
DottaandPaperclip ac9459bae3 feat: configure company agent observability (#16874)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Companies use several agent harnesses and execution environments.
> - Operators need one place to select where native agent logs and
traces go.
> - An inference proxy would add a dependency to the agent request path.
> - This pull request supplies native OpenTelemetry settings to managed
Codex and Claude Code processes.
> - Company secrets protect destination credentials. Export failure does
not change the task result.

## Linked Issues or Issue Description

**Subsystem affected**

Company settings, shared contracts, database, server, adapters, and
runner.

**Problem or motivation**

An operator cannot configure a company destination for native agent logs
and traces. Manual harness configuration is hard to apply across local
and remote execution.

**Proposed solution**

Add one company destination: Braintrust or a custom OTLP HTTP/protobuf
endpoint. Apply a transient snapshot when execution preparation starts.
Keep credentials out of API reads, task environment manifests, recovery
files, and command arguments. Replace a warm process when its export
settings change and preserve its conversation.

**Alternatives considered**

Multiple destinations can use a user-operated collector for fan-out.
This change does not add a collector, an inference proxy, or transcript
scraping.

**Roadmap alignment**

This extends company settings, secret management, and support for
multiple harnesses. The maintainer requested this implementation.
Searches for observability and Braintrust found no duplicate company
destination feature. Related infrastructure tracing work in #16236 has a
separate content-free contract.

## What Changed

- Add strict schemas, revision checks, encrypted secret storage,
activity records, and board-only settings routes.
- Add explicit synthetic logs and traces tests with a bounded HTTP
request and sanitized results.
- Supply native Codex configuration and Claude Code environment values
through local and remote launch paths.
- Preserve Codex login refresh through the existing managed credential
link. Retain unsaved drafts across background reads. Require complete
custom header re-entry when the endpoint origin changes.
- Separate process export compatibility from conversation identity.
Isolate generated Codex configuration and preserve resumable sessions,
including remote home refresh after export changes.
- Advance the immutable Pi/Copilot source attestations for shared
environment and sidecar code changes. Keep their provider payloads
unchanged and retain prior identities for decoding.
- Redact destination credentials throughout launch diagnostics and HTTP
logs.
- Add the production settings form, Storybook states and journey,
documentation, and feature/access map entries.

## Verification

- Real managed local Codex 0.160.0 and Claude Code 2.1.286 tasks
exported to Braintrust. API readback and the Braintrust UI showed the
test records. A real remote Daytona Codex task exported through the
legacy `exec` path.
- Live tests exercised content capture off, export disabled, warm
conversation reuse, and a destination that accepted connections but
never replied. Agent work succeeded and export requests stopped at the
configured three-second timeout. The UI connection test returned “Test
payload accepted”; the saved API key stayed masked after reload.
- All current-head CI test lanes, typechecks, packaging/build checks,
and required aggregates passed on
`71e994b2be9c8fb6d6e938a4ad7cf4c95fdafe31` ([CI
run](https://github.com/paperclipai/paperclip/actions/runs/39319194318)).
Greptile completed on that exact commit at 5/5, with zero unresolved
review threads. The additional optional Paperclip Review check remains
queued waiting for its assigned agent.
- Local workspace typecheck and build passed. Focused verification
included 239 combined runner tests, 789 API/native-session tests, 107
Codex home/ACP/sandbox-site tests, 204 feature/privacy tests, and the
affected Rust suites. Migration, token, map, Storybook catalog, and
Storybook build checks passed during acceptance. These checks ran at the
relevant implementation or merge boundary; the current-head CI is the
complete final gate.
- Managed AI credential projections now receive enabled and disabled
company export settings; genuine caller-owned Codex homes remain
untouched. Two regressions reproduced the skip before the repair. All
276 engine/lifecycle tests and adapter-utils typecheck pass afterward.
The launched TOML retains provider/MCP settings, credential continuity,
and redaction.
- Settings saves, removal, and the real company-deletion owner acquire
secret mutation ownership before database locks. PostgreSQL NOWAIT
probes cover all three paths; concurrent save/rotation/removal/deletion
requests settle correctly. The affected suites passed 137 tests,
followed by all 32 service/connection cases after expanded deletion
coverage. Server and Codex adapter typechecks pass.
- Codex source profiles use the effective CLI argument list. A spawned
fixture CLI reproduced both ignored-argument failures; all three
precedence/fallback cases now pass.
- Real tar staging reproduced remote conversation loss in both API-key
and subscription modes before the repair. Both now pass: changing
managed settings preserves sessions, archives, native indexes, and
refreshed subscription credentials. A corrupt upload preserves the prior
config and conversation.
- Preserved failure evidence: initial CI caught stale Pi/Copilot source
attestations, a missing test-harness helper, and packaging fixture/probe
mismatches; those were corrected and covered by focused checks.
Superseded heads had intermittent attachment-composer timeouts despite
successful uploads; [the original trace and screenshot remain
available](https://github.com/paperclipai/paperclip/actions/runs/39309701089/artifacts/12215109203).
The same attachment case passed on the final head: [25/25 tests in shard
3](https://github.com/paperclipai/paperclip/actions/runs/39319194318/job/118288637051).
- A connection-fault fixture also exposed a stale pooled socket after
its hang case; closing fixture responses isolated scenarios and the full
affected suite passed.
- The broad local test run was not clean: database resource failures,
timeouts, an older cached module graph, and a stale optional-resource
manifest assumption were recorded. Focused checks passed after the
documented fixes. This does not establish a clean full local pass.
- Native remote Codex, remote Claude, and the full ACPX Codex bridge
remain unqualified. The direct Codex resume test does not establish full
bridge acceptance.

## Risks

- Native exporters perform network requests from each execution
environment. A server connection test does not prove remote
reachability.
- Prompts, assistant responses, and tool content are enabled by default
when supported. Native caps and harness-specific controls still apply.
- Caller-owned Codex homes are unsupported for automatic configuration
and remain untouched.
- Native harnesses and their tool processes can inspect export
credentials. The settings form and documentation advise using
ingestion-scoped credentials. Retained headers remain bound to their
saved scheme, host, and port; changing origin requires fresh values or
removal.
- Migration 0357 adds a company-scoped row and secret reference. It is
safe to reapply. Secret removal and company deletion use the existing
secret lifecycle.
- Slow or unavailable destinations must not block task settlement.
Export settings take effect at the next execution preparation boundary.

## Model Used

OpenAI Codex, GPT-6, with reasoning, tool use, code execution, and
browser verification. 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
- [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 15:36:04 -05:00
aaeff418cf fix(acpx): add a positive control to stalled-tool permission evidence (#16769)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The ACPX engine runs Claude agents. A watchdog ends a turn when a
pending tool call gets no update for 30 minutes.
> - #16688 added a field to stalled runs. The field records if the
stalled call's permission request reached Paperclip.
> - Recent stalled runs show `acpStalledToolPermissionRequested: false`.
We can read this as "the call stopped before its permission request".
That reading is correct only if calls of the same kind usually send a
request.
> - We have no data that shows if finished calls of that kind sent
requests. Thus we cannot tell if the missing request is a real signal.
> - This pull request records a positive control: the number of finished
calls of the stalled call's kind, and how many of them sent a permission
request.
> - The benefit: the next stall event tells us if the missing request
locates the stall, or if it gives no information.

## Linked Issues or Issue Description

Refs #16688

**What happened?**
Runs stop with the stalled-tool watchdog error. The diagnostics show
that the stalled call sent no permission request. The diagnostics do not
show if finished calls of the same kind sent requests.

**Expected behavior**
The stalled-run diagnostics contain enough data to show if a missing
permission request is a real signal.

**Steps to reproduce**
A pending tool call gets no ACP update for 30 minutes. The watchdog ends
the turn. The run result contains the stalled-tool fields.

## What Changed

- `packages/adapter-utils/src/acpx-engine/execute.ts`: when the watchdog
fires, count the finished calls of the stalled call's kind, and count
how many of them sent a permission request. Write the counts to the run
result as `acpSettledSameKindToolCount` and
`acpSettledSameKindToolPermissionRequestedCount`.
- `server/src/services/run-failure-diagnostics.ts`: allow the two new
fields as non-negative safe integers. Other values are dropped.
- `doc/observability.md`: explain how to read the two fields with the
existing permission-request field.
- Tests: extend the existing stalled-tool tests in `execute.test.ts` and
`run-failure-diagnostics.test.ts`.

## Verification

- `pnpm exec vitest run src/acpx-engine/execute.test.ts` in
`packages/adapter-utils`: 244/244 pass.
- `pnpm exec vitest run
src/services/__tests__/run-failure-diagnostics.test.ts` in `server`:
115/115 pass.
- Mutation check: remove the kind filter, or count every finished call
as "requested". Each mutation makes the stalled-tool test fail.
- `tsc --noEmit` passes in `packages/adapter-utils` and in `server`.
Note: the full `server` `typecheck` script did not run locally, because
the runner vendor build step failed in this sandbox. I ran `tsc
--noEmit` directly.

## Risks

- Low risk. The change only adds two counts to the run result after the
watchdog fires. It does not change the decision to stop the turn, or any
permission decision.
- The fields hold only counts. They contain no tool titles, inputs, or
identifiers. This is the run-log and run-result path. It is not
Telemetry. The fields reach Sentry through the existing allowlist in
`run-failure-diagnostics.ts`.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, used through Claude
Code with tool use (shell, file edits, test runs).

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [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-18 13:59:16 -07:00
63306f6660 fix(acpx): record whether a stalled tool call's permission request arrived (#16688)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Hosted `claude_local` runs use the ACPX engine. Claude can start
background subagents, and those subagents call the runtime MCP tools
that Paperclip attaches.
> - #16671 added a stalled-tool watchdog. It ends a Claude turn when a
pending tool call gets no ACP update for 30 minutes. That PR said the
most likely cause of the stall is a lost ACP permission round trip, but
it could not prove it.
> - A staging run tripped the watchdog. Two background subagents started
12 MCP calls. ACP reported each call as `pending`, and no call got
another update. The MCP gateway logs show the 9 earlier calls from the
parent agent, but no request from the 12 subagent calls.
`MCP_TOOL_TIMEOUT` (15 minutes) did not end them. So the calls stalled
before Claude sent them to the MCP server.
> - The run record cannot say if the permission request for a stalled
call reached Paperclip. Without that fact, the next stall gives no new
evidence about the cause.
> - This pull request records, for a stalled run, whether the stalled
call's permission request reached Paperclip, and how many pending calls
had a permission request.
> - The benefit is that the next stall tells us which side of the
permission round trip stopped, so the real fix can go to the correct
layer.

## Linked Issues or Issue Description

- Refs #16671 (the stalled-tool watchdog; this PR tests the cause that
PR suspected)
- Refs #16360 (the MCP client deadline that cannot reach a call that was
never sent)

**What happened?**

A hosted staging `claude_local` run started two background subagents.
Each subagent started six `execute-sentry-tool` MCP calls. ACP reported
all 12 calls as `pending`. None got a result, an update, or an error.
The MCP gateway received no request for them. The parent turn finished
its answer but stayed open for the subagents. After 31 minutes the
watchdog ended the turn with `acpx_tool_stalled`. A single background
subagent with six parallel calls to the same tool did not stall in a
later test.

**Expected behavior**

When a tool call stalls, the run record shows if the call's permission
request reached Paperclip. Then the stall can be put on the agent side
or on the relay side of the round trip.

**Steps to reproduce**

1. Start an ACP `claude_local` run in a sandbox that uses two background
subagents to call runtime MCP tools.
2. Wait until a subagent's tool calls stay `pending` with no further ACP
update (in staging this happened without a known trigger).
3. See that the watchdog fails the run with `acpx_tool_stalled`, but the
record has no evidence about the permission round trip.

**Paperclip version or commit**

`master` at 1f27427.

## What Changed

- The ACPX engine passes an `onPermissionRequest` hook to the ACPX
runtime. The hook records the tool call ID of each permission request
and returns `undefined`. ACPX then uses its permission mode to decide
the request, the same as before.
- When the watchdog fires, it records `permissionRequested` for the
stalled call and counts the pending calls that had a permission request.
- A stalled run's result has two new fields:
`acpStalledToolPermissionRequested` (boolean) and
`acpPendingToolPermissionRequestedCount` (non-negative integer). The
`[paperclip]` stderr line also says if the request reached Paperclip.
- The server run-failure diagnostics allowlist the two fields. They
accept only a boolean and a safe non-negative integer.
- `doc/observability.md` describes the fields. It also says that a
background subagent's Task call completes when the subagent starts, so
the watchdog watches the subagent's own calls.

## Verification

- `npx vitest run src/acpx-engine` in `packages/adapter-utils`: 21
files, 423 tests pass.
- Engine tests:
- The existing stall test now sends a permission request for the Task
call only. The run records `acpStalledToolPermissionRequested: false`
and a count of 1. The hook returns `undefined`. The log line says the
request did not reach Paperclip. No tool title or ID appears in the
diagnostics.
- A new test sends the permission request after the relay saw the
stalled call. The run records `acpStalledToolPermissionRequested: true`.
- Mutation check: when the hook does not record the ID, both tests fail.
- `npx vitest run
src/services/__tests__/run-failure-diagnostics.test.ts` in `server`: 115
tests pass. Invalid values for the new fields are dropped.
- `npx tsc --noEmit` passes in `packages/adapter-utils` and in `server`.
- Runtime dependency assumption: the hook must not change permission
decisions. I called the real patched `acpx@0.12.0`
`AcpClient.handlePermissionRequest` with and without the hook in
`approve-all`, `approve-reads` and `deny-all`. The responses and the
permission stats were the same in each mode, and the hook saw each
request. The hook only adds an ID to an in-memory set for the run, so it
adds no remote call and no blocking work.
- Limits: the tests mock the runtime, so they do not prove the hook runs
in a real sandbox relay. The acpx source passes the hook to the client
on every runtime path (`runtime.js`), and the real-client check above
covers the decision path.

## Risks

- Low risk. The hook only observes. If ACPX ever treats a host hook as
the decision owner, the check above would show a different decision.
That is not the case in the pinned `acpx@0.12.0`.
- The set holds one string per permission request for the length of one
run. That is bounded by the number of tool calls in the run.
- This PR does not fix the stall. It gives the evidence for the next
occurrence.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) through Claude Code, with tool use
and code execution. It read the run log, the gateway logs, and the ACP
agent and client code, ran reproduction probes, edited the code, and ran
the tests.

## 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-17 21:05:43 -07:00
938a441944 fix(acpx): end Claude turns whose pending tool call stops receiving updates (#16671)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Hosted `claude_local` runs use the ACPX engine. Paperclip sends
runtime MCP servers to Claude, and Claude can start subagents (the Task
tool) that call those MCP tools.
> - #16360 set `MCP_TOOL_TIMEOUT` for Claude. That bound works: in a
local test with the same Claude binary, a direct MCP call and a subagent
MCP call to a server that never answers both ended at the bound.
> - A hosted run still hit the 4h sandbox timeout on a release that has
#16360. Its run log shows a subagent that started four MCP calls. ACP
reported the four calls as `pending`, and they never got another update.
About 40 other MCP calls in the same minutes finished in 3–25 seconds.
So the four calls most likely never reached the MCP server, and
`MCP_TOOL_TIMEOUT` did not apply to them.
> - The subagent's Task call got an `in_progress` heartbeat every 30
seconds for the full 4 hours. The turn looked active, so no existing
bound stopped it.
> - This pull request adds a stalled-tool watchdog to the ACPX engine.
It ends the turn when a pending tool call gets no update for 30 minutes
and no other tool call finishes in that time.
> - The benefit is that a stalled run fails in about 30 minutes with a
clear error code, not after 4 hours with a general timeout.

## Linked Issues or Issue Description

- Refs #16360 (MCP client deadline; this PR covers the stall that the
deadline cannot reach)
- Refs #15962 (stop-time diagnostics that showed the pending tools and
their age)

**What happened?**

A hosted `claude_local` run gave lookups to two subagents. One subagent
started four MCP tool calls. ACP reported each call as `pending`. No
call got a result, an update, or an error. The other subagent finished
in 3 minutes. The stalled subagent's Task call got a heartbeat every 30
seconds, so the last-event age at stop was only 28 seconds. The oldest
pending tool was 3h58m old. The sandbox execution timeout ended the run
after 4 hours.

**Expected behavior**

A tool call that never gets a result ends the turn after a bounded time.
The run fails with an error that names the stall.

**Steps to reproduce**

1. Start an ACP `claude_local` run that uses a subagent to call runtime
MCP tools.
2. Make one of the subagent's tool calls stay `pending` with no further
ACP update (in production this happened without a known trigger).
3. See that the run continues until the adapter execution timeout,
because the Task heartbeats keep the turn active.

**Paperclip version or commit**

`master` at 4415665.

## What Changed

- Add `ACPX_STALLED_TOOL_TIMEOUT_MS` (30 minutes),
`ACPX_STALLED_TOOL_MARGIN_MS` (15 minutes), the check interval, and the
`acpx_tool_stalled` error code in `acpx-engine/constants.ts`.
- Add `resolveStalledToolTimeoutMs()`. Claude turns use 30 minutes, or
`MCP_TOOL_TIMEOUT` / `BASH_MAX_TIMEOUT_MS` plus 15 minutes if that is
longer. Other agents are not watched. The adapter config field
`stalledToolTimeoutSec` overrides the bound for any agent, and 0
disables it. The bound is not part of the session fingerprint.
- The engine records the time of the last update for each tool call, and
the time a tool call last reached a final status.
- During a turn, the engine checks the pending tool calls every 60
seconds. If a pending call has had no update for the bound, and no tool
call reached a final status in that time, the engine:
- records the stop-time activity (the same fields as a timeout or an
operator stop),
- writes a `[paperclip]` stderr line with the closed tool kind and the
silent time,
- cancels the turn, and starts the existing fail-fast cancel deadline
that the duplex-loss path uses. The deadline helper is now shared by
both paths.
- Finalization reports the stall as a failure: `errorCode:
"acpx_tool_stalled"`, `resultJson.status: "failed"`,
`acpStalledToolKind` (one closed ACP `ToolKind` label or `unknown`), and
`acpStalledToolSilentMs`. A timeout or a duplex loss still takes
priority. A turn that completed anyway keeps its success.
- The server Sentry diagnostics allowlist the two new fields. It drops
the kind if it is not one closed label.
- Document the watchdog in `doc/observability.md` and the
`stalledToolTimeoutSec` field in the `claude_local` config notes.

## Verification

- `npx vitest run src/acpx-engine` in `packages/adapter-utils`: 21
files, 422 tests pass.
- New engine tests:
- A silent pending call next to a Task call that keeps getting
heartbeats ends the turn with `acpx_tool_stalled`, the closed kind, and
the silent time. No tool title or ID appears in the diagnostics.
- An agent that ignores the cancel: the fail-fast deadline closes the
stream and the run fails with `acpx_tool_stalled`.
  - A long tool that keeps getting updates is not cancelled.
- A queued call that waits behind slow calls that keep finishing is not
cancelled.
- `stalledToolTimeoutSec: 0` disables the watchdog, and only the
wall-clock timeout ends the turn.
- `resolveStalledToolTimeoutMs()` defaults, env bounds, other agents,
and config override.
- Mutation checks: with the watchdog disabled, the two stall tests time
out (the same hang as production). Without the "no tool finished" guard,
the queued-call test fails.
- `npx vitest run
src/services/__tests__/run-failure-diagnostics.test.ts` in `server`: 115
tests pass.
- `npx tsc --noEmit -p packages/adapter-utils`: passes.

## Risks

- A legitimate tool call that gets no ACP update for 30 minutes while no
other tool call finishes now fails the run. Claude's own tool bounds
(MCP 15 minutes, Bash 10 minutes by default) end healthy calls before
that. If an operator raises `MCP_TOOL_TIMEOUT` or `BASH_MAX_TIMEOUT_MS`
in the env, the bound moves up with it. Operators can also set
`stalledToolTimeoutSec` or disable the watchdog with 0.
- A long sync subagent stays safe while its Task call gets heartbeats.
Only a call that is itself silent can trip the watchdog.
- The run fails instead of continuing. The failure uses the normal
failed-run recovery, and it reports to Sentry under its own error code,
not under the generic timeout.
- This PR does not find why the four calls never got a result. Claude
runs with `--permission-mode default`, so each MCP call makes an ACP
permission round trip, and the ACP stream goes through the remote
process-session relay. A lost request or response on that path is the
most likely cause. The new diagnostics show how often the stall happens
and for which tool kind.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) through Claude Code, with tool use
and code execution. It read the run log and the ACP agent and client
code, edited the code, and ran the tests.

## 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-17 14:51:49 -07:00
DottaandPaperclip 25b16e65fc fix(observability): detail workspace and connector preparation (#16454)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server prepares a repository, sandbox workspace, and connector
access before an agent can reply.
> - Existing traces measure large preparation phases but leave important
work inside those phases unclear.
> - Repository source materialization and Browser Use discovery can do
more work than their callers suggest.
> - New detail must preserve access checks, run ownership, and the
existing work order.
> - This pull request adds fixed OpenTelemetry spans inside those
operations.
> - Operators can use one deployed trace to select the next performance
fix.

## Linked Issues or Issue Description

Refs: #16419, #16425, #16428.

**What existing behavior does this improve?**

Startup traces for server workspace preparation, native sandbox
synchronization, and connector assignment resolution.

**Current behavior**

Workspace and connector aggregate spans can take many seconds. The trace
does not separate private source cloning, seed reuse, archive work,
progress persistence, or each connector resolver. Browser Use resource
selection builds the full authorized tool catalog. The configuration and
native backend can each resolve connector assignments.

**Proposed behavior**

Show the awaited work as fixed child spans. Separate discovery queue
wait from catalog construction. Preserve the initiating run context when
another run releases a scheduler slot. Add no new lifecycle event writes
for workspace detail callbacks.

**Reason and benefit**

Operators need evidence about the hosted critical path before another
performance change. These spans distinguish filesystem work, provider
transfer, authorization, transaction entry, locks, and reporting
overhead.

**Breaking changes**

None. Authorization, query order, transaction ownership,
synchronization, existing progress events, and task results retain their
contracts. The change adds opt-in Observability spans under the existing
OTLP endpoint gate.

## What Changed

- Trace private source directory setup, Git credentials, clone,
requested ref, source identity, and checkout publication.
- Trace sandbox source capture, seed cache/replay, shallow clone and
archive, overlay copy/archive, verification, upload, warm stamps, and
descriptor persistence.
- Separate existing awaited progress reporting from useful workspace
work. Keep new detail callbacks trace-only.
- Trace each connector resolver and Browser Use catalog/grant work.
Split discovery queueing, descriptor sources, and policy evaluation.
- Trace Slack authority, credential reads, catalog synchronization,
transaction entry/settlement, and advisory locks.
- Update the real filesystem staging trace expectations and the
Honeycomb investigation guide.
- Add a real scheduler regression for a queued job released by another
run. Assert run ownership, parent spans, and exactly one completed queue
span.

## Verification

- Passed: server and adapter-utils TypeScript checks (`pnpm --filter
@paperclipai/server exec tsc --noEmit` and `pnpm --filter
@paperclipai/adapter-utils exec tsc --noEmit`).
- Passed: 252 checks across 9 focused files. These cover real filesystem
staging, native workspace synchronization, trace ownership, endpoint
gating, and workspace preparation.
- Passed after review: 26 trace-context, tracing-failure, and
discovery-scheduler checks across 3 files (these overlap the first run).
The new queued-discovery regression fails when context binding is
removed and passes after restoration. An initial submillisecond
timestamp assertion was replaced with explicit span-completion order to
avoid SDK clock precision assumptions.
- Passed on implementation commit
`0e68968a4bd61001893d833f281f12bb110edbe1`: `pnpm -r typecheck` and
`pnpm build`. The later commit updates only an engine test expectation.
- The first CI workspace lane found an old engine trace-tree
expectation. It expected the earlier span set. The updated assertion now
checks the new detail spans, their parents, and single completion. Its
targeted executor check passes.
- The full test suite, build, release registry, and end-to-end gates
pass in CI on final head `40e37d89ef679109d60a96bb5731a0616efeaa43`: 55
passing checks and 2 optional Storybook skips. The full suite was not
duplicated locally after the focused run.
- Greptile reviewed the final head at 5/5. No unresolved review threads
remain.
- After deployment, filter Honeycomb by the hashed run ID and verify
`service.version`. Inspect `heartbeat.prepare.workspace`,
`runtime_selection.workspace_sync`, and the connector assignment
parents. The guide in `doc/observability.md` explains each new family
and the nested intervals.
- No hosted run has used this new instrumentation yet. Local checks
cannot establish hosted latency improvement.

## Risks

- Tracing adds spans when an operator configures an OTLP endpoint.
Detail remains capped at 16 spans per phase per execution attempt.
- Parent and child durations overlap. The documentation explains how to
avoid counting them twice.
- A discovery job can start in another run's scheduler continuation. The
bound callback preserves the initiating async context.
- New spans export fixed names and the existing hashed run ID. They add
no paths, repository URLs, connector resource IDs, credentials, tool
schemas, or exception text.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The exact served 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-15 12:21:32 -05:00
DottaandPaperclip f64d05adf4 test: consolidate repeated ACPX startup metadata scenarios (#16068)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-14 23:02:09 -05:00
DottaandPaperclip 422728fc36 test: retire seven repeated ACPX trace executions (#16061)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-14 22:50:25 -05:00
3935e300dd fix(acpx): bound Claude MCP tool calls when runtime MCP servers attach (#16360)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Hosted `claude_local` runs use the ACPX engine. Paperclip gives each
run its runtime MCP servers (for example the `paperclip-assigned` tool
gateway) as ACP `mcpServers` entries.
> - Claude's default MCP tool timeout is far longer than a run. ACP
`mcpServers` entries have no per-server timeout field. So the agent
waits on an MCP call until the call answers.
> - Hosted error reports show runs that end with "Run exceeded the
adapter execution timeout (sandbox)". The stop-time diagnostics from
#15962 show the problem: the agent went silent about 50 seconds into the
run, three tool calls of ACP kind `other` stayed pending, and nothing
ended them until the 4h sandbox backstop.
> - The gateway bounds the remote provider call (10s default, 60s max).
But other steps on the gateway `tools/call` path have no deadline: DB
queries, row locks and pool acquisition, the credential steps before the
provider timer starts, and the stdio child exit wait. One stuck step
holds the agent turn for hours.
> - This pull request gives the agent's MCP client a deadline:
`MCP_TOOL_TIMEOUT` for ACP Claude runs that receive runtime MCP servers.
> - The benefit is that a stalled gateway call becomes an MCP error that
the model can see. The turn continues and does not spend the full 4h
execution budget.

## Linked Issues or Issue Description

- Refs #15962 (diagnostics that identified the silent turn with pending
tools)
- Refs #15448, #15456, #15850 (related gateway timeout and
connection-health work; this PR does not overlap with them)

**What happened?**

A hosted `claude_local` run sent parallel MCP tool calls. No call
answered. The run stayed silent for about 4 hours. Then the sandbox
execution timeout ended it with "Run exceeded the adapter execution
timeout (sandbox)".

**Expected behavior**

A stalled MCP call ends with an error after a bounded time. The agent
sees the error and continues.

**Steps to reproduce**

1. Start an ACP `claude_local` run that has runtime MCP servers.
2. Make the gateway `tools/call` request stall (for example, hold a lock
that the request needs).
3. See that the run stays silent until the adapter execution timeout.

**Paperclip version or commit**

`master` at 976cdc7.

## What Changed

- Add `ACPX_CLAUDE_MCP_TOOL_TIMEOUT_MS` (15 minutes) in
`acpx-engine/constants.ts`. The value has wide headroom over the
gateway's longest legitimate wait (60s provider calls, 2 minutes of
approval preparation, and the 10-minute connection cap proposed in
#15850).
- The ACPX engine sets `MCP_TOOL_TIMEOUT` in the agent env for Claude
when the run has runtime MCP servers. If the adapter `env` already sets
`MCP_TOOL_TIMEOUT`, the engine keeps that value. Other agents and runs
without MCP servers do not change.
- Add an engine test for the bound, the no-server case, the user
override, and a non-Claude agent.
- Document the client-side deadline in `doc/MCP-RUNTIME-OPERATIONS.md`.

## Verification

- `npx vitest run src/acpx-engine/` in `packages/adapter-utils`: 21
files, 423 tests pass.
- The new test fails without the env assignment (`expected undefined to
be '900000'`), and passes with it.
- `npx tsc --noEmit -p packages/adapter-utils`: passes.
- The env reaches Claude through the same per-session env path as
`ANTHROPIC_MODEL`. `claude-agent-acp` merges this env into the Claude
SDK env.

## Risks

- A legitimate MCP call that takes longer than 15 minutes now fails. No
gateway path is designed to wait that long. Operators can set
`MCP_TOOL_TIMEOUT` in the adapter `env` to change the value.
- The value also applies to other MCP servers in the same Claude
session, for example servers in user settings. The same override is
available.
- Warm sessions get the env when the agent process starts again. The env
is not part of the session fingerprint, so this change does not reset
resumable sessions.
- This PR does not fix the server-side step that stalls. It bounds the
effect on the run. Server-side deadlines on the gateway `tools/call`
path (DB lock and statement timeouts, a request-level deadline, SIGKILL
escalation for stdio children) are possible follow-ups.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) through Claude Code, with tool use
and code execution. It read the repository, traced the gateway path,
edited the code, and ran the tests.

## 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 <devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:01:42 -07:00
4b766b8729 fix(acpx): record turn activity at the moment a stop fires (#15962)
Record stop-time ACP turn diagnostics (last-event age, oldest pending tool age, pending tool kinds) so wall-clock timeout events show whether the turn was stalled. Diagnostics only.

Co-Authored-By: Paperclip <Paperclip-Paperclip@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 12:33:59 -07:00
DottaandPaperclip 1e0cfcb4fc test: retire redundant suites and consolidate owner coverage (#15978)
Retire duplicate ACPX and Codex proof after migrating unique assertions to their behavioral owners. Consolidate repeated fixtures and exact case matrices while preserving lifecycle, protocol, company, credential, approval, and ordering contracts. Remove the unused runtime-controls compatibility path and document test ownership and preservation evidence.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-12 10:44:02 -05:00
1b4c803816 fix(costs): preserve usage attribution and explain unavailable run costs (#15948)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The cost ledger records usage and controls agent budgets.
> - Some runs lose the selected model or API billing category before
their usage reaches the ledger.
> - The dashboard reports missing costs but does not identify the
affected runs or the available actions.
> - This pull request preserves usage attribution and adds a compact
view of cost gaps grouped by agent.
> - Operators can inspect runs, open agent settings, and record saved
costs without starting new agent work.

## Linked Issues or Issue Description

Refs #15634, #11938, #15879.

This follows the merged subscription reporting in #15634. The older
proposal in #11938 addresses part of ACP model attribution. This change
also rejects conflicting models across a turn, fixes credential-backed
billing capture, and explains cost gaps in the existing dashboard. The
Pi receipt recovery work in #15879 covers a separate adapter recovery
path. This PR preserves unresolved receipts and does not recover
provider usage or reprice past entries.

**What happened?**

ACP results use the requested model even when the runtime selects a
model. Native and OpenCode API runs can report unknown billing despite a
matching API credential. The dashboard shows notices without links to
the affected runs. These gaps make API and subscription totals harder to
interpret.

**Expected behavior**

Record the model selected by the runtime. Identify API billing only from
a matching credential. Keep costs unresolved when reliable usage or
pricing is absent. Show the affected agents and runs. Offer an
accounting retry only when saved evidence is ready.

**Steps to reproduce**

1. Run an ACP agent with its model left unset, or use a matching API
credential with a native or OpenCode agent.
2. Inspect the recorded model and billing category for the run.
3. Open Costs Overview for a period with unpriced usage or terminal runs
awaiting receipts.
4. Inspect the notice and try to find the affected run or the relevant
agent settings.

**Paperclip version or commit**

Current master at `657e71584a0`. The patch is rebased on that commit.

**Deployment mode**

Self-hosted server and local development. The cost detail tests use a
disposable PostgreSQL database.

## What Changed

- Preserve the runtime-selected ACP model in checkpoints and final
results. Conflicting models across one turn remain unpriced.
- Share credential-backed API billing checks across native and OpenCode
results. Keep unknown billing when the provider and credential do not
match.
- Add company-scoped cost detail and accounting retry endpoints. Board
viewers can read details but cannot retry. Agents and foreign companies
are denied.
- Limit each detail category to 25 entries. Use one consistent database
snapshot and sparse indexes matching the filters and sort order. Add the
unknown-billing count to the existing summary query.
- Replace the notice with an expandable count line. Group entries
alphabetically by agent. Show the saved blob icon, link each name to
configuration, and put run and retry links beside the date.
- Preserve estimate and unavailable-price labels on Providers and
Billers; keep retry confirmation after the resolved notice disappears.
- Fetch details only while expanded. Retain the last loaded details
after a refresh error. Retry saved accounting only; do not rerun the
agent.
- Add capture, database, authorization, UI, and Storybook coverage.
Update the implementation contract and cost reporting guide.

## Verification

- `pnpm -r typecheck` passed after rebase.
- `pnpm build` and `pnpm build-storybook` passed after rebase.
- `pnpm check:token-gates` and `git diff --check` passed.
- 1,086 focused tests passed across 17 files. These cover ACP, native
and OpenCode capture, PostgreSQL reports, route authorization, OpenAPI,
Costs UI, and existing accounting regressions.
- Desktop and mobile browser checks passed during UI review. They cover
lazy expansion, alphabetical groups, loaded blob icons, configuration
and run links, keyboard retry, and layout overflow.
- `pnpm test:run` was attempted with command-scoped
`init.defaultBranch=master` for Git fixtures. It was stopped after a
native session recovery failure reproduced on unchanged base
`657e71584a0` (`archives a damaged prior epoch before completing guarded
same-task replacement with real runnerd`). An MCP upload case failed in
the broad run but passed in isolation on both the base and PR branch.
These local limitations do not affect the 1,086 passing focused tests.
- Current-head CI is green, including all unit test lanes, serialized
server suites, runner checks, typecheck, build, policy, and eight
browser shards. Apex re-review is 5/5 on `56de60effdb`; all four
original findings are addressed and every review thread is resolved.
- PostgreSQL applies migration `0333` in the integration fixtures.
EXPLAIN ANALYZE on the production detail statements uses the new sparse
indexes behind 5,000 healthy records in each table.
- Ten provider/biller card cases cover missing and estimated prices; the
retry test covers row removal and notice unmount. A live Storybook
browser check verifies the confirmation and updated count.
- Run `pnpm storybook`. Open **Costs / Subscriptions / Cost Data Quality
Details** to inspect the production page with representative fixtures.

## Risks

- Model and billing metadata change for future runs. Estimates still
require complete usage and a supported price. No past cost amount is
rewritten.
- A missing final receipt remains unresolved for budget checks. The
display changes after fifteen minutes; that time limit never authorizes
settlement.
- Accounting retry is a write action. It retains the existing company
checks, receipt fences, idempotency, and audit logging.
- Detail reads are bounded and run only after expansion. They poll every
30 seconds while open. No provider probe or new summary query is added.
- Migration `0333` adds two partial indexes; it changes no stored cost
amounts or table columns. Index creation scans the existing tables and
may briefly block writes during deployment. No lockfile or workflow
change is included.

## Model Used

OpenAI Codex, based on GPT-6, with repository inspection, code editing,
browser checks, and test execution. The exact serving model ID,
reasoning setting, 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: Codex <noreply@openai.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-11 22:48:29 -07:00
Devin FoleyandPaperclip eab93fd4a0 fix: checkpoint adapter usage and preserve unknown prices (#14991)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 18:16:18 -07:00
DottaandPaperclip e38d6d16b6 feat(connections): add advanced provider setup and live browser qualification (#15341)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Users connect accounts and choose an agent harness and model.
> - The runtime change in #14970 supports custom providers on those
connections.
> - Normal setup must stay simple while advanced users can choose a
compatible gateway.
> - Shared connector rows and access controls keep these choices
consistent.
> - This pull request refines the agent setup UI and adds review stories
and repeatable browser qualification.
> - The qualification checks real tools and downloaded outputs, not only
a successful run status.

## Linked Issues or Issue Description

Refs #14970, #37, #13083, #14104, #14565, #12692.

The core implementation in #14970 is merged. This branch incorporates
its squash commit and targets `master`. Both PRs contain our
implementation. #14016 is a reference only and is not a dependency. This
PR has 96 changed files.

## What Changed

- Complete model-provider connector presentation beside other
connectors. Each row uses the existing Connect action and connection
list. Tags are stored without category UI. The base PR includes the
provider forms and routes.
- Show persistent Subscription, API Key, and Advanced choices. Label
Advanced as Custom Gateway. Reuse provider logos, connection lists, and
permissions controls. Default access to the organization and all agents
when permitted; keep narrowing controls under Advanced.
- Keep Configure reachable before subscription sign-in, so users can
select a supported environment when the default cannot sign in. Testing
and saving still require a connection. Show the execution environment in
Configure. Preserve the confirmed Connect choice. Editing a method,
credential, saved account, or advanced choice requires that current
choice to connect before testing or saving. Use matching model and
thinking-effort dropdowns and retain connection icons in selected
values.
- Preserve the new harness model default when switching an existing
OpenCode agent to Codex or Claude, and resolve user-selected model names
with the effective harness.
- Load popular OpenRouter models through the shared connection-model
discovery path. Keep explicit model lists and manual model entry
available.
- Group onboarding, connection setup, agent runtime, management,
recovery, and production-component stories under AI Connections /
Provider routing.
- Add an explicit-only provider-connections browser suite for managed
local or existing local/staging targets. Use private browser profiles
and credential handoffs. Support human-assisted subscription sign-in
without sharing passwords or tokens in reports.
- Verify persisted connection identity, runtime probes, tool execution,
exact artifact bytes, completion, and context-dependent follow-up.
Retain source/model provenance, cost bounds, closed error diagnostics,
original failures, and cleanup evidence.
- Add Gemini startup-model and skill-root fixes, Grok private-history
detection, ACP filesystem regression fixtures, selected-workspace
handling for local Hermes, and artifact-helper workspace fallback.
- Keep managed Grok runtime homes disposable. Remove host-side
transcript retention/restoration because private file modes do not
isolate same-user agent processes. Ignore earlier development archives
and use a fresh task handoff when history is unavailable. Verify the
absence of restored transcripts with a separate same-user process.
- Capture stopped-run diagnostics before deleting an attached-company
fixture agent. Track creation and owned sign-in receipts; revoke only
this attempt's accounts and never adopt a concurrent campaign's newly
created account. Preserve failure signals and final status through
cleanup.
- Require the requested environment in the saved agent and every run,
including follow-ups. Reject a forced incompatible target. Keep one
cancellation state through startup, every cell, reporting, and teardown
for SIGINT, SIGTERM, and SIGHUP. Stop further paid cells after
interruption. Document qualification limits.

## Verification

- Current head `b3bb3e94d577d43d9965a6b9daba039f599b2e49` includes
master `d9f600043`. The security fix in `a758fde31` passes full
workspace typecheck, production build, and 119 connection/Grok
regressions. The unchanged UI passes all 126
configuration/model-discovery tests and token gates. The final
published-guide correction passes Grok adapter typecheck. Earlier head
`eebd8225c` passed the complete deterministic runner suite (1,404 Vitest
tests and 128 Node tests) and all CI jobs. Current-head CI run
`37520147514` passed all 47 jobs, including the full sharded Vitest and
browser matrix, production build, and canary dry run. All 55 checks
completed: 53 successes and two expected skips. The current-head
security scan passed, Greptile is 5/5, and no review threads remain
open.
- A separate same-user process reproduced reading a restored Grok
transcript before the security fix. The regression now finds no
transcript. Existing fresh-session fallback and ordinary session
metadata behavior pass.
- The final account-choice and cleanup fixes pass 85 setup tests and 26
qualification-harness tests. Regressions verify that editing a
connection invalidates confirmation, Configure remains reachable before
sign-in, diagnostics are captured before fixture deletion, and
concurrent campaigns cannot adopt or revoke each other's accounts. UI
and E2E typechecks pass.
- The Storybook build and actual Chromium production-component stories
passed during this change. Review the neighboring AI Connections /
Provider routing stories, regular connector rows, three connection
modes, model discovery, and the single execution-environment control in
Configure.
- Cancellation smoke verified authenticated cleanup before browser close
for SIGINT, SIGTERM, and SIGHUP. Regressions cover interruption during
startup and reporting, missing-file ACP resource errors, and preserved
permission denials. Both ACP runtime versions and 54 ACPX/Grok
regressions passed. The deterministic connection-intent browser suite
passed two tests.
- Historical local qualification retained 43 passing API/gateway cells
out of 46, with downloaded outputs and follow-up receipts. These
attempts span earlier builds; they do not qualify this exact commit or
staging. Subscription combinations, Gemini overloads, and the unresolved
follow-up failure remain recorded rather than counted as passing.
- Use `pnpm test:e2e:runner -- --list --suite provider-connections` to
inspect the matrix. Follow `tests/runner-e2e/PROVIDER-CONNECTIONS.md`
for credentials, target URL, sign-in assistance, budget, evidence, and
cleanup. Paid live tests remain opt-in.

## Risks

- The core implementation in #14970 is merged. This PR adds no database
migration of its own.
- Subscription login needs an interactive provider session. Dedicated
accounts and staging qualification remain follow-up work; this PR does
not certify every login combination for production.
- Managed Grok transcript resume is deferred until provider history has
an OS isolation or authorized broker solution. Follow-ups start fresh
with Paperclip task context; earlier live Grok results do not qualify
this behavior.
- Gemini CLI 0.58.0 has an upstream ACP new-file error conversion
defect. Live overloads and one unresolved follow-up timeout remain
recorded. The stock CLI is unchanged, and those cases are not marked as
passing.
- Real-provider tests spend credits and use private credential/evidence
directories. The launcher requires explicit selection and checks target
ownership. It must not attach to a developer's database by accident.
- OpenClaw Gateway, Hermes Gateway, Claude Managed, AWS AgentCore,
Process, HTTP, and legacy ACPX local remain outside custom provider
setup.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository tools, code
execution, and browser testing. The exact deployment model ID and
context window size were 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-06 15:21:22 -05:00
DottaandPaperclip a590ab769d Give managed agents persistent cryptographic identities (#15352)
Give agents persistent Ed25519 identities encrypted with the existing instance master key. Create keys transactionally for new agents and lazily before supported managed runs, expose public identities in the API and agent UI, and protect private material during runtime delivery and output persistence.

Preserve identities in recovery backups while giving imported and development-cloned agents fresh keys.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 13:57:03 -05:00
Devin FoleyandPaperclip 3b47a6befd Record bounded workspace restore failure stages (#15005)
Capture allowlisted restore substep and failure metadata for future diagnosis while preserving workspace recovery behavior, error identity, cleanup ordering, and privacy.

Validation: exact-head Greptile 5/5, passing CI, no unresolved review threads, and a clean merge. Detailed verification and limitations are recorded in the pull request.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-05 10:58:32 -07:00
DottaandPaperclip b17019e14d fix(agents): reduce default instructions and qualify stock harnesses (#14948)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Its adapters supply task context and access to Paperclip skills and
tools.
> - The default hire manual and shared prompts also repeat general work
procedures.
> - Those procedures overlap with stock provider instructions and the
Paperclip skill.
> - Existing E2E fixtures supply a QA manual, so they do not qualify the
production default.
> - This pull request reduces the generic instructions and adds real
default-hire coverage.
> - The benefit is less competing guidance, with inspectable evidence
for preserved skills and task context.

## Linked Issues or Issue Description

Refs: #14920. That merged change preserves native Codex base
instructions. This PR covers the default manual, shared legacy prompts,
operational skill guidance, and the narrowly approved ACP
skill-discovery/session-environment repair for measured delivery and
credential-persistence failures.

**What existing behavior does this improve?**

New non-CEO hires without a custom bundle and legacy task/chat startup
and continuation prompts.

**Current behavior**

The shipped default manual contains 602 words. Generic task/chat prompts
and ordinary resume deltas repeat work procedures already available
through the harness and Paperclip skill.

**Proposed behavior**

The default manual contains only the eight-word company identity. Shared
startup prompts retain identity and connection guidance. Ordinary resume
deltas retain current work context without the generic execution
contract.

**Reason and benefit**

Let the stock harness guide general work. Keep Paperclip-specific
capabilities and independently test default hires, skills, ordered
comments, and chat restart.

**Breaking changes**

New default hires receive less guidance. Existing saved manuals,
explicit custom bundles, CEO templates, and specialized wake contracts
retain their behavior. The obsolete includeExecutionContract option
remains accepted for source compatibility.

## What Changed

- Reduce the default hire manual to one sentence.
- Reduce shared task/chat defaults and remove the generic
ordinary-resume contract.
- Keep connection guidance, auth, skills, custom prompts, and
specialized wake context.
- Add credential-free instruction-boundary gates and 26 explicit Product
E2E cells across eight legacy/native profiles, including two focused
Paperclip-storage cases.
- Capture public hire receipts before providers run, then grade
delivered prompts and independent task/chat outcomes.
- Add an early legacy skill API recipe for saving a task document,
checking the saved revision receipt and linking the document. Improve
stock task/heartbeat skill-selection metadata and show a clickable
Markdown UI-link example. Keep native tool completion separate.
- Advertise bounded routing descriptions and exact successfully staged
SKILL.md paths in legacy ACP Claude; keep full bodies on demand and
preserve remote path rebasing.
- Remove only the provider environment from copied persisted ACP session
records, while loading current run credentials and preserving all other
options/conversation state.
- Regenerate both capability metadata inventories and reject stale
manifests/inventories before provider admission.
- Publish the original reduction and focused skill-repair comparisons,
preserving all failures, automatic recovery, cost coverage and
limitations.

## Verification

**Behavioral qualification remains pending.** Original legacy ACP Claude
loses the issue document only in the reduced cohort beneath an unchanged
credential failure. A source-backed diagnosis finds that neither
ordinary assignment reads the staged operational skill, while the
runtime persists provider environment in session state. The new common
repairs expose skill metadata/path and omit persisted env; strict
document and credential guards stay intact. [Inspectable diagnosis and
retained
hashes](https://github.com/paperclipai/paperclip/blob/9f654db4541d3d002769c988f6e51fc0b08dadbd/doc/plans/2026-10-03-legacy-acp-claude-readiness.md).

Current repair head `de0965984ff3edf611ae6d0e7ca5c7d5ae3947bb`
incorporates master `569c7203aa24b95440682983ce7940ba1d4247bd` (merged
#14961/#15007). All 222 affected adapter tests, adapter-utils/E2E
typechecks, and final 96 variant/grader/retry calibrations pass. The
frozen historical comparator is
`c25697f4260b6f3adfea143c3ae9932e2f42986d`: 8,280 of 8,291 paths
identical, exactly two production instruction paths plus nine declared
unit expectations differ. The operational skill/discovery/environment
repairs, selected model/profile/task/core grader/auth/permissions/retry
policy are identical. Both actual launcher prepare→verify admissions
pass with zero providers. [Immutable manifest and exact
receipts](https://github.com/paperclipai/paperclip/blob/9f654db4541d3d002769c988f6e51fc0b08dadbd/doc/plans/2026-10-03-legacy-acp-claude-evidence/manifest.json).

One original legacy ACP Claude cell per variant is authorized, with
enforced single campaign attempts, 12-minute deadlines and company/agent
1,000-cent hard stops; every product recovery run/cost is counted.
Actual live outcomes are pending. Current normal CI has one failed
server shard and failed aggregate verify under diagnosis; other normal
gates including typecheck/build/Rust/all eight browser shards pass.
Fresh review completed successfully; the valid historical startup/resume
masking finding was fixed with per-invocation task/chat checks and
strict complete-snapshot capture, calibrated and resolved. Prior heads,
failures and campaigns below remain historical evidence, not checks on
this repair head.

- Prior head `36aa4d81c49a1a8f6f04b1a068fae19aa901955f` is replayed on
merged hiring master `862a5758ba0e88a33232c1f1fa645e85c38a3113`. All 52
current-head checks pass with two intentional Storybook skips, including
repository typecheck/test/build and the browser shard. Fresh Greptile is
5/5 with zero unresolved review threads. Exact-head stock prerequisites
pass 599 assertions (598 TypeScript + 1 Rust), all six gates and
retained receipt verification, zero providers/source errors. Fingerprint
`a7f5a22d860a88fe20cce213c6d5e0004788f32c8363930729aea4fd740ad16d`.
Combined catalog/hiring calibrations pass 67 assertions, E2E typecheck
and 26-cell stock discovery pass. Canonical contract/inventory checks
and the later issue-derived reference calibration are retained; that
reference-only follow-up is not live-qualified by earlier frozen runs.
- Prior full repository typecheck/build passed. The complete local
Vitest run executed 14,956 tests: 14,870 passed, 83 skipped, three
timing failures. All three affected files passed unchanged narrow
reruns; original failures remain retained. Current-head CI now passes
the full general checks; the original local failures remain retained.
- The original 24-pair default-manual/shared-prompt comparison has two
new overall classic Claude/OpenCode document-delivery failures plus an
additional legacy ACP Claude document loss beneath an unchanged
credential-guard failure (not closed by later runs), two newly passing
OpenCode ordered cases, seven unchanged failures and 13 unchanged
passes. Equal 15/24 totals do not establish behavioral equivalence.
[Complete original
report](https://github.com/paperclipai/paperclip/blob/875f4c397d9e8c3f12f39dedd59abaf1eaf5236e/doc/plans/2026-10-02-stock-harness-live-comparison.md).
- The skill-only repair holds the eight-word manual/shared prompts and
merged #14920 fixed. All four matched profile configurations and 203
fixture/behavior files match. Candidate
`abd0b628ca642c09a54a4edc56a5227402f6686e` varies only the two skill
sources against baseline `bc83fe030234439ac51279502a28803958963e2e`.
[Candidate
workflow](https://github.com/paperclipai/paperclip/actions/runs/37060885547)
and [baseline
workflow](https://github.com/paperclipai/paperclip/actions/runs/37060888047)
each pass 571 exact-source prerequisites before providers; all eight
cells clean up successfully. Failed campaigns publish successfully and
remain failed.
- Repair pairs: Claude original Fail → Pass; Claude explicit Pass →
Pass; both OpenCode cases Fail → Fail. Explicit OpenCode's handoff
worsens beneath the unchanged failing UI-link grade: baseline gives a
clickable API URL, candidate gives a code-formatted path without an
anchor. The request's usable-link wording is narrower in the UI-only
oracle. [Complete repair report and safe
projection](https://github.com/paperclipai/paperclip/blob/875f4c397d9e8c3f12f39dedd59abaf1eaf5236e/doc/plans/2026-10-02-legacy-document-skill-repair.md).
- The subsequent narrow stock metadata/link correction has two matched
Pass → Pass cases, zero new machine failures/passes and no pending
pairs. Both original-case handoff links remain deficient: candidate uses
a wrong PAP prefix, baseline supplies a bare prefix-less slug path; the
preserved original oracle only requires a durable document. Both
explicit clickable UI-link cases pass revision/content/link grading. All
four exact-source 587-check gates, single assignment runs and cleanup
pass. This does not establish fix causality because baseline also
succeeds. [Candidate
workflow](https://github.com/paperclipai/paperclip/actions/runs/37069547401)
freezes `fe9dc1e3c518825242ed889ab9c8352986f8c2ed`; [matched
baseline](https://github.com/paperclipai/paperclip/actions/runs/37069552374)
freezes `0d7ecfa96d72fba79b7f0a25052b42c0686c0488`. This is a skill-only
comparison with reduced manuals/shared prompts held constant, not a
repeat of the historical-manual comparison. Only original and clarified
explicit classic OpenCode cases are selected, two per variant/four
expected turns. 8,242 other tracked files and both profile hashes match;
protected workflows admit each exact source before credentials.
[Complete qualification
report](https://github.com/paperclipai/paperclip/blob/74d0d3d945f4c52d0814b5a845ab5bd09f33cd6b/doc/plans/2026-10-02-opencode-skill-routing-link-qualification.md).
Candidate original loads Paperclip/reference before saving publicly;
baseline original loads it after writing locally, then saves publicly
within the same assignment. Reported cost totals are $0.0107824490
candidate / $0.0107909015 baseline, with unmetered runtime. The later
reference-only issue-derived link correction is provider-free calibrated
and **not live-qualified** by these frozen runs; no further paid runs.
- Retained tool calls show the repaired original OpenCode assignment
loads only its assigned output skill before writing locally. Operational
Paperclip is first loaded during automatic disposition recovery; its
early recipe is visible then, but it never saves the missing document.
Explicit candidate loads Paperclip and reads the new reference before
saving successfully. All nine actual runs are counted. Reported LLM
totals are $0.3802537209 baseline and $0.4918990161 candidate; local
runtime is unmetered.
- Initial setup, packaging, cancelled/missing-cell recovery, callback
test and relative-output attempts remain retained. No completed provider
failure was rerun. Frozen measurement branches are unchanged by later
canonical metadata maintenance.
- Run `pnpm test:e2e:runner:stock-harness`, `pnpm test:e2e:runner:unit`,
and `pnpm test:e2e:runner:typecheck`. Select `stock-harness` explicitly
for paid execution; it is excluded from `--all`.

Prior-head integration: `36aa4d81c49a1a8f6f04b1a068fae19aa901955f`
replays this PR on merged hiring #14985
(`862a5758ba0e88a33232c1f1fa645e85c38a3113`), preserving the four
explicit custom-CEO-bundle checks, minimal generic manual boundary, and
both suites. The combined fixture catalog and hiring calibrations pass
67 assertions; exact-head stock prerequisites pass 599 assertions (598
TypeScript + 1 Rust), all six gates and retained-receipt verification,
zero providers/source errors, fingerprint
`a7f5a22d860a88fe20cce213c6d5e0004788f32c8363930729aea4fd740ad16d`. E2E
typecheck and 26-cell stock discovery pass. Fresh current-head CI passes
all 52 checks with two intentional skips, and fresh Greptile is 5/5 with
zero unresolved review threads.

The prior source-plan browser failure is retained: a deterministic
process fixture replayed its last `fixture:plan` command on
`chat_task_completed`, writing revision 2 with identical body after the
approval handoff. This was not paid provider execution. Rebased
current-head CI passes the same assertion without an old-head retry or a
change to that browser fixture.

The merged hiring change was measured separately on immutable matched
unions, with this reduced/shared/operational context and native
completion guidance held constant. [Complete original two-profile
report](https://github.com/paperclipai/paperclip/blob/f0512647656be78e48abd8c22a3078db8bf6bcd2/doc/plans/2026-10-02-hiring-template-live-comparison.md):
[candidate](https://github.com/paperclipai/paperclip/actions/runs/37075466208)
/ [historical
baseline](https://github.com/paperclipai/paperclip/actions/runs/37075469463),
705 provider-free prerequisites each. Both pairs are unchanged Fail →
Fail on the exact-five count, with six core delivery checks passing all
four cells; 28 actual successful runs include eight automatic completion
wakes, zero retries, four successful cleanups. Source-read coverage is
uncomparable, actual model charges unknown. Separately versioned
provider-free accounting remains analytical work; original verdicts are
preserved. This does not rerun or qualify the completed default-manual
or native campaigns.

## Risks

- Legacy ACP Claude's additional delivery loss is not closed by any
later matched run and blocks the no-extra-failing-behavior merge
criterion. Legacy document delivery may have relied on the prior
manual/shared prompts. The early skill repair improves Claude in one
trial; the later OpenCode pairs pass in both variants and cannot
establish causality or robust recovery. Both original-case links remain
deficient beneath the storage-only grade. The later issue-derived
reference correction has only provider-free validation. Native
finish/block descriptions must not be supplied to legacy agents.
- The comparison holds merged native Codex fix #14920 constant; it
cannot measure that fix's before/after task performance.
- These bounded skill/context/chat workflows do not measure general
coding quality. Unrepresented providers remain unqualified.
- Saved manuals and old Codex sessions are not automatically migrated.
Codex through ACP still has a separate base-instruction follow-up.

## Model Used

OpenAI Codex, GPT-6 family as identified by this session. The exact
deployment ID and context-window size are not exposed. The assistant
used reasoning, repository tools, code execution, and delegated PR/eval
work.

## 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 (relevant suites and all
three unchanged narrow reruns pass; complete-run timing failures
retained in Verification)
- [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 on the new repair head
(prior-head checks retained above)
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
on the new repair head
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-03 12:32:42 -05:00
Devin FoleyandPaperclip 4abff286c2 fix: retain resolved ACP execution timeout metadata (#14986)
## Thinking Path

> - Paperclip manages agent work through adapters and heartbeat runs.
> - ACP adapters resolve a timeout for the selected execution target.
> - An untouched sandbox timeout uses a four-hour default.
> - Heartbeat finalization rebuilt the metadata from the stored zero.
> - This made a timed-out sandbox run report an effective timeout of
zero.
> - This change retains the adapter's resolved policy for accurate run
diagnostics.

## Linked Issues or Issue Description

**What happened?**

ACP sandbox runs with `timeoutSec: 0` use the four-hour default. Their
terminal metadata reports `effectiveTimeoutSec: 0` and `timeoutSource:
config` because heartbeat finalization only reads the stored agent
configuration.

**Expected behavior**

The result must report the policy the adapter used: `14400` and
`sandbox_default`. Explicit limits, fractional limits, explicit
unlimited overrides, and local defaults must keep their resolved values.

**Steps to reproduce**

Run an ACP adapter on a sandbox target with `timeoutSec: 0`. Compare the
start log's four-hour policy with the terminal result's effective
timeout. The new tests exercise the adapter result and the heartbeat
metadata merge without waiting four hours.

**Paperclip version or commit**

Reproduced from `6eaf218924f0a89faf1c02eb0d6877a6c5c8a2cb`.

**Deployment mode**

Self-hosted server with an ACP sandbox execution target.

Searched open timeout and metadata issues and PRs. Related #14804
exposes timeout configuration in forms; #14496 proposes a default
policy; #14833 addresses CLI session retention. This PR changes only ACP
result metadata.

## What Changed

- Retain the resolved timeout in the ACP result after settlement.
- Use validated adapter resolution when merging terminal timeout
metadata. Preserve config fallbacks for older adapters and the HTTP
millisecond policy.
- Test sandbox defaults, explicit and fractional limits, explicit
unlimited overrides, local defaults, malformed metadata, and unchanged
cancellation fields.
- Document the result fields and their meaning.

## Verification

- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- Stop metadata tests: 23 passed.
- Reporter and diagnostic suites: 84 passed; two real-Sentry-SDK tests
skipped because the optional SDK is not installed.
- ACP engine suite: all 206 tests passed with a deterministic local
`gemini --version` shim. Ambient host CLI probes made the existing
Gemini session-resume fixture intermittent (one assertion failure in
each of two broad runs); an isolated 15-case rerun and the clean-base
206-test suite also passed. No assertion or timeout was changed.
- `pnpm test:run` is in progress. This PR does not claim a complete
local suite pass.
- Independent review found no blocking issues. The tests cover real
adapter emission and the real metadata merge separately.

## Risks

Low runtime risk: this changes result diagnostics. It does not change
timeout values, cancellation acknowledgement, cleanup, checkpoint
safety, retries, or provider operations. It does not fix the cause of a
quiet or long-running tool. Older stored results are not rewritten. The
new source values apply only when an adapter returns a valid resolution.

## Model Used

OpenAI GPT-6 with reasoning, repository inspection, code editing, and
test execution. The deployment-specific 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
- [ ] 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-02 16:09:36 -07:00
DottaandPaperclip 2ec82c5774 fix(runner): preserve task context when tool connections change (#14963)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use tools through company-scoped connections and provider
sessions.
> - Resolving a tool connection currently forces a fresh session even
when the provider can load new tools into the existing conversation.
> - A fresh provider conversation can receive too little history to
continue the task.
> - This pull request adds explicit tool-refresh capabilities and uses
them in both runner paths.
> - Fresh attempts receive bounded task history with source IDs and
retrieval instructions.
> - The benefit is that agents can continue the same task after a
connection changes.

## Linked Issues or Issue Description

**What happened?**

A resolved tool connection forced a fresh provider conversation. The new
conversation could lose the original goal and prior answers. Claude also
rejected resume when only the MCP server set changed.

**Expected behavior**

Resume the provider conversation when its harness can refresh tools.
When a fresh session is required, supply enough bounded history to
continue the task. Preserve company, agent, task, workspace, model,
instruction, and skill checks.

**Steps to reproduce**

1. Start a conversation and agree on a task and its constraints.
2. Request and connect a tool needed for the task.
3. Continue the conversation after the connection resolves.
4. Check that the agent remembers the task and can use the new tool.

**Paperclip version or commit**

The bug was reproduced on master at `c46e41e81`. This branch is rebased
on current master.

**Deployment mode**

Self-hosted server. Both legacy adapters and the native runner are
affected.

Related public work: Refs #13282 for task-backed conversations. Refs
#13057 for the broader session-compaction proposal. Refs #14659 for
another report about local CLI session continuity. This change fixes
tool-connection continuation. Provider authentication repairs keep their
existing recovery behavior.

## What Changed

- Expose tool-refresh support in native harness descriptors and legacy
adapter metadata.
- Request tool refresh after connection resolution. Keep provider
authentication repair as a fresh-session wake.
- Reload current tools and credentials while retaining supported Claude,
Codex, Grok, and other provider conversations.
- Allow MCP-only changes during qualified native recovery. Keep all
other compatibility checks.
- Refresh managed-provider and ACPX tool bindings when attaching a new
run.
- Add a fresh-session handoff for both runner paths. Bound database
reads, excerpts, and the final packet to 24,000 bytes.
- Include the original request, recent messages, decisions, plans, prior
answers, and source IDs. Mark omitted content. Apply reset boundaries,
wake cutoffs, quarantine, and secret redaction.
- Add regression tests and document the capabilities and handoff
behavior.

## Verification

- `pnpm -r typecheck` and `pnpm build` passed. Rust formatting passed.
- Final review fixes passed 314 server tests, 333 adapter utility tests,
139 native-session runtime tests, and 12 managed-provider Rust tests.
They verify historical quarantine, raised budgets across attachment, no
history reads on successful resume, and handoff delivery on fresh retry.
- Broader branch verification also passed 1,401 adapter utility tests,
1,047 runner TypeScript tests, 43 Grok adapter tests, and 311 Rust core
tests.
- Live Claude CLI and Grok ACP probes preserved the provider session ID,
recalled a prior task constraint, and called a newly added read-only MCP
tool.
- GitHub CI passed on `b21486d18084a7aa4cafbe8e012f7cad6585d9cc`: 55
successful checks and 4 skipped checks. This includes all test shards,
all eight browser shards, runner checks, and the Grok clean public npm
install canary. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/37057514976).
- A full local test attempt encountered a separate Git snapshot timeout.
All affected local suites passed after the final edits, and the full CI
test gates passed.
- Review the capability matrix in `packages/paperclip-runner/README.md`.
Repeat the four reproduction steps with a supported provider and with an
unsupported harness.

## Risks

- Provider tool refresh can fail. Existing recovery falls back to a
fresh conversation where policy permits it.
- A new transport can replace an old process while preserving the
provider conversation. Tests cover current credentials and unchanged
identity.
- Long history can omit older context. Explicit markers and source IDs
let the agent retrieve needed context within task scope.
- Unknown and unqualified harnesses use the fresh-session path. No
database migration is required.

## Model Used

OpenAI Codex, GPT-6, with reasoning, tool use, code execution, and live
provider testing. The exact model ID and context-window size are not
exposed in this session. Claude and Grok also ran as test subjects.

## 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-02 15:11:44 -05:00
DottaandPaperclip 7a52dcdc74 fix: repair MCP validation and cancelled execution recovery (#14951)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The tool gateway gives agents access to connected services. Recovery
controls what happens when a run stops.
> - Generated tool names can exceed the provider limit after the MCP
client adds its prefix.
> - The same invalid definition can fail each automatic retry. A
cancelled run can also hold saved messages without showing its cause.
> - This pull request bounds tool names, stops configuration retries,
and retains cancellation evidence.
> - It shows the stopped run and admits saved input only after the
existing safety checks pass.
> - The benefit is a clear recovery path that preserves operator Stop
and prevents duplicate message delivery.

## Linked Issues or Issue Description

**What happened?**

A long connected MCP tool name makes the provider reject the entire
request. Automatic recovery repeats the invalid request. Separately,
unexpected legacy cancellations can leave saved input behind a recovery
hold. The notice does not identify the stopped run or its cause.

**Expected behavior**

Complete MCP names fit the provider limit. Tool-definition errors
require configuration repair. Cancelled runs retain their source and
reason. The recovery notice shows the cause and saved-message count.
Verified unexpected cancellations can start a fresh turn through the
existing admission checks.

**Steps to reproduce**

1. Assign an App gallery connection with a long application key and tool
name to a Claude agent.
2. Start a run. The provider rejects a name over 128 characters,
including its MCP prefix.
3. For cancellation recovery, stop a legacy provider turn without an
operator Stop request and send a user message while the recovery hold is
active.
4. Inspect the recovery notice and the deferred message queue.

**Paperclip version or commit**

Rebased onto master at `cf8ad63c806685bfd7c48e3ed4a919d61a7c55f1`.

**Deployment mode**

Hosted or self-hosted server with legacy Claude or Codex execution.

Related public work:

- Refs #14017. That PR caps name segments. This PR preserves existing
short names and uses stable hash aliases for long complete names. It
also covers classification and recovery.
- Refs #4510. That PR adds a cancellation-source column. This PR records
bounded evidence in the existing run result, without a migration.
- Refs #12552 and #4506. Those PRs suppress recovery after operator
cancellation. This PR preserves operator intent and uses the existing
continuation gates.

## What Changed

- Bound gateway names with the full provider prefix in the 128-character
budget. Retain the original upstream tool name for dispatch and
permissions.
- Classify invalid tool definitions as configuration failures before
diagnostic redaction. Stop automatic retries and continuation attempts
for that error code.
- Persist cancellation source, expectedness, initiator, reason, and
time. Preserve recorded Stop intent when adapter results arrive. Report
unexpected started cancellations with closed diagnostic labels.
- Show the run cause, saved-message count, and Inspect run link. Offer
Continue for eligible unexpected cancellations. Require verified
provider stop, empty tool inventory, ownership, and the existing pause,
budget, approval, and dependency gates. Use the existing queue for
single delivery.
- Add regression coverage and update the execution, MCP gateway, and
run-log documentation.

## Verification

- `pnpm -r typecheck` and `pnpm build` passed.
- `pnpm check:token-gates` passed.
- Ran `pnpm test:run` and completed its workspace and serialized groups.
Initial resource and timing failures passed on isolated reruns. All 149
serialized route suites passed.
- Reran the changed server, adapter, and UI suites after the rebase.
Coverage includes long-name upstream dispatch, configuration retry
suppression, cancellation evidence retention, privacy labels, oversized
run projection, and concurrent saved-message delivery.
- `pnpm test:e2e tests/e2e/legacy-failure-continuation.spec.ts` passed
all six browser scenarios. The recovery notice shows the run cause and
inspection link, and each recovery entry point reaches one new response.
- Added database-backed checks for active, removed, paused, unavailable,
and disabled chat connections. The final continuation and
recovery-notice suites passed 167 tests. Externally bound chats hide
board Continue and show a usable next action.
- All 55 GitHub checks passed on
`42afbf1371dcaeb72646e3d8f65c19ff7cddf8de`. Two unrelated Storybook jobs
were skipped by their normal conditions. Greptile reviewed that commit
at 5/5 with no findings and no open review threads.

## Risks

- Long tool names change to aliases. Existing short names stay
compatible. The original connection and upstream name remain the
dispatch authority.
- Invalid tool definitions no longer get automatic retries. An operator
must repair the configuration before a new attempt.
- Continuation changes apply only to positively identified unexpected
legacy cancellations with complete empty tool inventory. Operator Stop,
unknown historical cancellations, outstanding tools, and unverified
provider termination keep their holds.
- No database migration. The added projection fields are optional.
Cancellation reason and initiator IDs remain local run evidence; Sentry
receives only closed source and initiator-type labels and expectedness.

## Model Used

- OpenAI GPT-6 through Codex, with reasoning, repository editing, shell
execution, and GitHub tool use. The runtime does not expose the exact
model variant 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
- [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-02 13:47:59 -05:00
Devin FoleyandPaperclip 0ea6b10967 Record ACP activity and workspace restore failure evidence (#14665)
## Thinking Path

Paperclip records terminal run failures for operators. A timeout's own
log and cleanup output update the run's last-output timestamp, so that
timestamp can make a long-silent provider look active. Snapshot runtime
activity before finalization and include the saved workspace restore
classification to make the next failure actionable without copying tool
payloads.

## Linked Issues or Issue Description

**What existing behavior does this improve?**
Terminal run diagnostics in the existing opt-in Sentry integration.

**Current behavior**
Reports cannot distinguish runtime events from finalization logging and
omit the already-persisted workspace restore code. A later successful
run also does not establish that earlier workspace files were restored.

**Proposed behavior**
Record runtime-event age/count and pending-tool inventory at
finalization, before status reads and cleanup. Forward only finite
counts, a completeness boolean, and known restore codes through the
existing reporter.

**Reason and benefit**
Operators can distinguish a silent turn with unfinished tools from
recent runtime activity and see restore failures without retrieving
private run output. Neither signal certifies productive work or
successful recovery.

**Breaking changes**
None. Error grouping, execution deadlines, cancellation, recovery
policy, and the Sentry opt-in remain unchanged.

Related diagnostic work: #14573, #14575, #14639.

## What Changed

- Snapshot ACP activity before success/failure finalization, including
thrown relay failures.
- Forward bounded numeric/boolean evidence and shared workspace restore
codes; exclude commands, tool IDs, paths, and arbitrary result data.
- Document limitations and test silence, empty streams, timeout, cleanup
delay, incomplete tool inventory, and privacy.

## Verification

- `pnpm -r typecheck` passed after the final implementation.
- Changed suites: 252 tests passed; all 29 database reporter tests
subsequently passed after restoring the embedded-Postgres package
library symlinks. The migration test also passed (30 database cases
total).
- `pnpm build` passed during implementation. Final head
`fe78dba6f592b1abccac7cdbf341bd2e0b0d30cb` passed all 53 CI checks,
including complete test coverage, typecheck, build, and browser/runner
gates; two unrelated checks intentionally skipped.
- Full local test attempts initially hit missing embedded-Postgres
library symlinks; the dependency setup was repaired and database tests
passed. Duplicate local full-suite runs were stopped after full CI
completed. This PR does not claim a completed full local suite.
- Review regression: completed, failed, and cancelled tools are excluded
from the pending count; focused activity/timeout tests and adapter-utils
typecheck passed.
- Reviewed the diff for secrets, customer data, and internal references.

## Risks

Low risk, diagnostic-only. The existing tool inventory is incomplete for
some runtime events, so the report carries its completeness flag. Event
age is measured at finalization and does not prove useful work or
identify the underlying provider failure. No schema changes or new
capture gate.

## Model Used

OpenAI GPT-6 via Codex, with repository inspection, code execution, and
tests. Exact model build identifier is not exposed by this session.

## Checklist

- [x] Thinking path and model are specified
- [x] Checked ROADMAP.md; this is a maintenance correction, not planned
feature work
- [x] Searched for duplicate and related PRs
- [x] Described the issue using the enhancement template
- [x] No internal issue references, customer data, or private instance
links
- [x] Descriptive branch name
- [x] Focused regression tests pass
- [x] Added tests and updated documentation
- [x] Risks documented
- [x] Required validation and CI gates are green (full suite validated
in CI; local scope documented above)
- [x] Greptile is 5/5 with no unresolved findings
- [x] I will address review comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-30 14:27:53 -07:00
0be2afcca6 feat(ui): improve task composer controls and pending input (#14322)
## Thinking Path

> - Paperclip lets operators assign tasks to AI agents and review their
work.
> - The task composer controls the next message and its assigned agent.
> - Operators needed a way to choose that agent's model and effort
without leaving the composer.
> - The old mode selector, upload button, and input cards made the
mobile composer crowded and hid normal messaging during a pending
decision.
> - Harnesses publish different model and effort capabilities, so the
picker must follow the selected agent.
> - This pull request adds one responsive composer flow, keeps pending
cards visible above it, and protects Codex ACP authentication in the
local test path.
> - Operators can choose run settings, send a message, and answer a
pending card as separate actions.

## Linked Issues or Issue Description

**Subsystem affected**

Task composer UI, issue thread interactions, Codex ACP credential
handling, and Storybook.

**Problem or motivation**

The composer did not expose model or effort for the selected agent.
Mobile actions wrapped poorly. Pending questions and confirmations
replaced the composer. A local Codex ACP test could also reuse host
authentication after the managed key was removed.

**Proposed solution**

Put assignee search, model search, exact model IDs, effort, and fast
mode in one picker. Use a mobile dialog. Replace the direct-upload plus
action and separate mode selector with an Add menu and removable Plan or
Ask chips. Place pending interaction cards above the usable composer.
Keep these cards pending after an ordinary message unless their creator
asks for comment superseding. Replace managed ACP auth files atomically
and isolate the test key from host credentials.

**Roadmap alignment**

ROADMAP.md does not list an overlapping composer milestone. This change
improves the existing task and review flows.

## What Changed

- Added the combined assignee, model, and effort picker to both task
composers. Search matches agent name, role, and harness. The server uses
a curated Codex list by default and honors instance-declared models.
Manual IDs remain available.
- Added an effort slider for known model capabilities, a conditional
Codex fast control, and reset. The picker opens in a modal on mobile.
- Added the Add menu for files, supported goals, Plan mode, and Ask
mode. Plan and Ask are exclusive removable chips. Keyboard mode cycling
remains available.
- Adjusted mobile spacing, avatars, wrapping, and Send placement.
Removed the composer divider.
- Moved pending question, confirmation, review, and related cards above
the composer. Ordinary comments now leave question and confirmation
cards pending by default. The onboarding prompt retains explicit comment
superseding.
- Updated the Storybook composer group with responsive states and the
production picker. Added UI, service, route, and browser regression
coverage.
- Isolated Codex ACP API-key authentication, skipped subscription auth
merge and shared-home copy-back for remote API-key runs, and replaced
the managed auth file atomically.

## Verification

- `pnpm -r typecheck` — passed on the final local head.
- `pnpm check:token-gates` — passed on the final local head.
- `pnpm exec vitest run server/src/__tests__/adapter-models.test.ts
ui/src/components/task-chat/ComposerRunSettingsPicker.test.tsx` — 31
tests passed, including role and harness search, declared Codex models,
and filtering general OpenAI models.
- `pnpm exec vitest run
server/src/__tests__/issue-thread-interactions-service.test.ts` — 74
tests passed.
- `pnpm exec vitest run
packages/adapters/codex-local/src/server/acp.test.ts` — 42 tests passed,
including remote API-key copy-back isolation.
- `pnpm test:run` — attempted locally; the embedded PostgreSQL test
database could not initialize on macOS. The isolated
`heartbeat-run-event-sequencing` suite reproduced that environment
failure. GitHub CI runs the full test matrix for this head.
- `pnpm build` — passed on the final head. `pnpm build-storybook` passed
after the last UI change; only server code, tests, and docs changed
afterward.
- Live local test drive — Codex ACP ran a task with a managed API key.
The test agent was restored to its default ACP configuration afterward.
- Review the interactive stories under the top-level Composer group with
`pnpm storybook`. Check a narrow desktop width and mobile Plan, Ask,
picker, and pending-question states.

## Risks

- A pending card stays open when an ordinary comment changes the
discussion. Its creator can set `supersedeOnUserComment: true` when a
new comment should replace it.
- Model and effort overrides persist on the task until reset or changed.
An unlisted manual model ID may fail when the provider runs it.
- Some harness catalogs do not report effort support. The picker hides
effort for those models.
- No database migration is required.

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

## Model Used

OpenAI GPT-6 via Codex. This runtime does not expose the exact model ID
or context window to the task. The model used code execution and browser
tools.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: OpenAI Codex <codex@openai.com>
2026-09-28 23:02:39 +00:00
DottaandPaperclip 992f720262 fix: make runner task context ownership explicit (#13753)
<!-- Write all pull request text in Simplified Technical English
(ASD-STE100). -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task descriptions, comments, continuation data, skills, and
execution rules enter several agent adapters.
> - The same source can be rendered by more than one automatic input
carrier.
> - Failed resumes can also rebuild input from stale or compact context.
> - This pull request gives each Paperclip-owned source one delivery
owner and preserves the required transport boundaries.
> - It adds deterministic adapter, interaction, runner, and browser
tests for these boundaries.
> - The benefit is more predictable context delivery with explicit
evidence for later live qualification.

## Linked Issues or Issue Description

Related: #13144 removes a duplicate environment payload and bounds wake
lists. Related: #11360 addresses Hermes resume behavior. This pull
request preserves compatible active-session formats while repairing
context ownership and stale question creation.

**What happened?**

Task descriptions and comments could enter more than one automatic
context block. Native transports could wrap a complete model input in a
second task envelope. Some legacy and gateway adapters could omit the
owned assignment on ordinary tasks or rebuild a failed resume with stale
compact context. A continuation could also request a question after
newer human comments had arrived.

**Expected behavior**

Each task or comment source has one automatic model-facing owner.
Distinct comment IDs and repeated wording remain distinct. Fresh
fallback attempts rebuild the required full context. A question request
is rejected when newer queued human direction makes it stale. Harness
access policy remains owned by execution configuration.

**Steps to reproduce**

1. Build a task with a description and current comments.
2. Capture the actual adapter or runner input.
3. Compare source ownership and task-envelope nesting.
4. Queue a human comment before a continuation requests a question.
5. Trigger a failed resume and inspect the fresh retry input.
6. Run the focused adapter, interaction, runner, and browser checks.

## What Changed

- Add shared prompt-section selection at the provider-attempt boundary.
- Deliver owned assignment context through native, legacy CLI, ACP,
gateway, cloud, Pi, Kimi, Grok, Gemini, OpenCode, Cursor, OpenClaw, and
Hermes paths.
- Rebuild full or compact context after resume recovery changes the
attempt. Add native and Claude ACP tests of actual recovery requests.
- Preserve custom templates, loaded instruction files, execution
policies, and older active-session formats.
- Record continuation source metadata and reject stale question creation
under the issue-row lock.
- Add explicit Product E2E context-integrity profiles, prerequisite
gates, credential-isolation checks, and report fixtures.
- Bypass service-worker forwarding for same-origin Vite development
modules. A real Chromium test fails with resource exhaustion before the
repair and passes after it. Production asset caching keeps its existing
policy.
- Add browser diagnostics and service-worker module-loading regressions.
- Add an explicit zero-retry eval option. The default retry behavior
remains unchanged. Each campaign records its effective policy.
- Remove the model-facing working-directory sentence from four prompt
builders. Existing workspace, sandbox, permission, and custom-template
configuration remains unchanged.
- Align the everyday workflow assertion with the current 47-entry
catalog.

Compared with current upstream master, the branch carries the
context-ownership implementation and its tests, the explicit
context-integrity catalog and evidence harness, and the focused browser
regression checks.

## Verification

**Merge assessment:** focused regression evidence supports merge. This
is not full completion of the original broad qualification matrix. The
maintainer has authorized merge after fresh verification of the master
integration.

- Current head: `bbd52f82114eabf09bc7b1a7e97d54a5b43bbc00`. This
integrates current master `2f585ef26a1814fa209715242d1ca791b63e4c4e`.
All 14 conflicts are resolved. Cancellation checks, workspace
finalization, native Grok support, and both sets of tests are retained.
- Current-head Greptile: **5/5**, with no blocking findings. The review
names this exact commit. All **59 reported checks are terminal: 55
successful, 4 skipped, zero pending or failing**. This includes the full
root general and serialized suites, separate runner checks, typecheck,
build, canary, browser E2E, Docker, and security checks. The successful
legacy security status is included in that total.
- After integration: workspace typecheck and full build passed. Separate
runner checks passed: **2,160 TypeScript tests (10 skipped), 582 Rust
tests, and 39 preparation checks**. Other passing checks include 621
Product E2E harness units, 376 focused shared/adapter tests, 160
real-database/API tests, 86 Hermes tests, 18 browser-support checks, and
Product E2E typechecking. The complete root suite passed in CI. The
duplicate local monolithic root run was stopped after that CI result; it
is not counted as a completed local pass.
- New native recovery coverage retains full assignment, completion
contract, and explicit skill selection after safe replacement, for old
and prepared input formats. Full native session test file: **136/136
passed**.
- New Claude ACP coverage captures actual fresh, resumed, and
missing-session fallback requests. It verifies one assignment copy,
comment order, identical text under distinct comment IDs, and full
fallback context. Full file: **33/33 passed**. Both affected TypeScript
checks passed.
- Existing deterministic tests cover source revisions, approval and
trust boundaries, completion validation, custom templates, compatible
sessions, standalone driver wrapping, and maintained adapter transport
requests.
- Provider-free browser support: **17/17 passed** after the master
merge. Service-worker unit tests: **33/33 passed**. The module-overload
regression failed before the repair and passed after it in real
Chromium.

### Fresh live comparisons

The new batch ran exactly four Product E2E attempts. **All four passed
on the first attempt; no retries.** Each has six terminal matchers plus
the existing browser lifecycle and invariant checks.

| Exact case ID | Control | Candidate |
|---|---|---|
| `core-compatibility.runner-codex.local.plan-revise-accept` | Passed |
Passed |
|
`local-session-integrity.runner-acpx-claude.local.structured-question-restart-resume`
| Passed | Passed |

The plan case checks a revised canonical plan and revision-bound
approval before completion. The question case restarts the server before
submitting the answer, then verifies the continuation completes.

Control source is `dfa4e1bda8d50a1a01746603251a9128dbe9d0d6`. Candidate
source is `79fcdb5dece501d28064ea9da306603881b46f0c`. They use identical
frozen definitions and provider versions: Codex `0.156.0` with
`gpt-5.6-sol`; ACPX `0.13.1` / Claude ACP `0.73.0` with
`claude-sonnet-5`. The September 24 head added master browser recovery
and test-only changes. The September 28 head also integrates newer
master changes, including cancellation, workspace finalization, and
native Grok. These are frozen-source live results, not exact-head live
runs.

The candidate received one description copy where the control initially
received three. The submitted initial plan envelopes were 7,969 versus
19,097 characters. Question envelopes were 7,592 versus 18,919. These
are structural measurements, not whole-provider token or dollar savings.

### Earlier evidence and failed attempts

- The preceding fresh batch has four effective passing pairs: OpenCode
comment continuation and assigned skill, native Codex comment
continuation, and native Claude comment continuation. It retains **11
attempts: eight passed and three failed**.
- Original failures remain recorded: missing local PostgreSQL library
links before task creation; host-sleep cleanup after task/page checks
passed; and a Claude **control** session-open rejection before a model
turn. Setup was repaired identically on both worktrees. The permitted
unchanged infrastructure retries passed. The underlying Claude provider
startup error was not retained and remains unknown.
- Older R2 retains **17 passes and one failure** across 18 attempts,
including eight both-pass native/legacy Codex/Claude pairs. Its OpenCode
blank-page failure led to the service-worker repair. R2 is historical
evidence: master changed the native fixed prompt and removed duplicate
wake environment data afterward.
- The September 24 CI run initially failed one unrelated preview
readiness test (`ECONNREFUSED` on its local fixture). Its test and
production code match master. Isolated local verification passed **28
tests, 3 skipped**. One unchanged CI retry passed the full shard: **831
passed, 1 skipped**, including all **31 preview-exposure tests**. The
aggregate CI gate passed afterward. The precise startup cause remains
unknown; a port race is a hypothesis, not a proved cause.

### Limits

The original wider profile/workflow matrix, repeated trials, and remote
Daytona qualification are incomplete. These results support a focused
merge recommendation, not statistical equivalence or universal harness
qualification. Some usage receipts are missing in both variants, so no
token or dollar savings are claimed. The $500 ceiling was preserved
using conservative allowances; failed attempts and unknown charges
remain in the ledger.

Reproduce the focused additions with `pnpm exec vitest run
packages/adapters/claude-local/src/server/acp.test.ts` and `pnpm
--filter @paperclipai/paperclip-runner exec vitest run
src/native-session-runtime.test.ts`. Full checks use `pnpm -r
typecheck`, `pnpm test:run`, `pnpm build`, and the separate runner
checks. Paid evals require the frozen definitions, profiles, and
credentials; do not use `--all` as a substitute for the selected cases.

## Risks

- Context placement changes can affect model behavior. Deterministic
checks cover the selected paths, but live qualification remains
incomplete.
- The stale-question guard can reject a request when queued human
comments arrived during the run. This is intended.
- New stored inputs and model envelopes retain compatibility readers for
older active sessions.
- Custom templates may intentionally repeat content.
- Removing a model-facing working-directory sentence does not change
filesystem, command, sandbox, or permission configuration.
- The worker bypass applies only to same-origin development module
paths. Cache-policy tests preserve private-response handling and
production asset caching. Mounted HTTP fixture changes remain test-only.
- This PR does not claim measured token savings or statistical
equivalence across every harness.

## Model Used

OpenAI Codex, exact model gpt-6-astra, with repository tools and code
execution. Bounded supporting work used gpt-5.6-luna and gpt-6-luna. The
serving context-window size is not exposed in this task.

## 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 using the required issue fields
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] I have run the focused local checks and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect these changes
- [x] I have considered and documented risks above
- [x] All current-head Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
for the current head
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-28 14:49:14 -05:00
DottaandPaperclip cbc5132e6c fix(adapters): expose a verified provider stop before workspace restoration (#14311)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent adapters own local or remote provider processes.
> - Run cleanup must know when the final provider process has stopped.
> - A remote timeout or a lost transport does not prove that the
provider stopped.
> - Retried provider invocations also make an earlier stop signal stale.
> - This pull request adds a verified final-invocation stop callback
before workspace restoration.
> - The dependent instruction revision change uses that boundary to
preserve private instruction edits safely.

## Linked Issues or Issue Description

**What happened?**

Adapter completion did not expose a reliable point between provider
shutdown and workspace restoration. Cleanup could lose provider-written
files, or treat a remote timeout as proof that a process stopped.

**Expected behavior**

Cleanup runs once after the final provider invocation has a verified
stop receipt and before workspace restoration. An incomplete remote
command keeps collection pending.

**Steps to reproduce**

1. Run a remote provider that returns a timeout without a numeric exit
code.
2. Let the adapter return or retry the provider.
3. Attempt to collect provider-written files during cleanup. The adapter
has no verified final-process boundary to use.

This is the prerequisite for the stacked canonical instruction revision
pull request. It has no database or UI dependency. Related #13291
verifies remote termination for later recovery; this change exposes the
earlier adapter-owned stop boundary before workspace restoration. The
scopes do not duplicate each other.

## What Changed

- Add a stop callback to adapter execution context and a
final-invocation fence.
- Confirm local child closure and complete remote exit receipts. Reject
remote timeouts, missing exits, transport failures, and SSH exit 255 as
stop proof.
- Invoke collection once before workspace restoration in eight CLI
adapters and at the confirmed ACP stop boundary.
- Preserve the stop observation when a later log flush fails.
- Run bridge and workspace cleanup in `finally` even when collection
rejects. ACP records a safe error without exposing a raw filesystem
path. Grok keeps collection errors separate from workspace restore
failures and preserves completed provider results when both cleanup
steps fail.
- Correct the existing Cursor test shell fixture so bounded remote file
reads run against real fixture files.

## Verification

- Three stop-boundary regressions failed before the callback
implementation and passed after it.
- Independent prerequisite branch: 377 tests passed across 24 adapter,
process-target, and ACP suites. Two added collector-rejection tests
failed before the cleanup fix and passed after it.
- A third regression reproduced Grok misclassifying a collection failure
as failed workspace restoration. Two additional cases covered completed
and failed provider turns when collection and restore both fail. The
Grok and restore-classifier suites passed 48 tests.
- All nine affected package typechecks and affected package builds
passed; Grok checks passed again after its classification fix.
- Integrated instruction branch: native local, legacy local, and native
Daytona each passed three browser tasks with exact persisted bytes,
fresh-task readback, history/restore, and explicit conflict resolution.
Unchanged warm Daytona passed three turns. Legacy Codex passed all five
checks again after the exception-safe cleanup fix.
- Alternate staging passed the same three-task native Daytona flow:
exact stopped-run save, independent downloaded readback, browser
history/restore, and explicit resolution of a real concurrent edit. The
deployed source was `14c3d810c9e05625121b3d27767aea9317b03125`, which
covers the initial adapter callback. Later Grok cleanup failures are
qualified by the adapter tests above.

- The final combined native Daytona flow passed again on deployed
`2bedd0f23bf4698b1f8b818f6796900647030427`: three fresh tasks proved
ordinary instruction edits, independent readback, History/Restore,
concurrent board conflict, and explicit candidate resolution. This
native staging flow does not claim to exercise the Grok adapter.

## Risks

- An unverified remote stop intentionally does not trigger collection. A
later controller with verified stop evidence must recover it or report
the copy unavailable.
- The callback is optional. Callers that do not register it retain their
existing behavior.
- The callback runs before workspace restoration and can delay cleanup
if its caller does not bound its own work. The dependent instruction
collector uses bounded reads and retries. A rejected callback still
permits bridge and workspace cleanup; it cannot claim an instruction
save.

## Model Used

OpenAI Codex, GPT-6, with tool use and code execution. The runtime does
not expose the exact deployment variant or context-window size. Multiple
Codex agents implemented and verified the change.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-28 08:45:53 -05:00
Devin FoleyandPaperclip 4b8ec588f3 Stop duplicating wake context in adapter environments (#13891)
## Thinking Path

> - Paperclip manages agent work and preserves task context.
> - Built-in adapters already include wake context in the agent prompt.
> - They also copy the full wake JSON into a process environment
variable.
> - A large environment entry can prevent the agent from starting with
`spawn E2BIG`.
> - This change removes the duplicate environment entry and uses the
existing prompt delivery.
> - The agent keeps its context without extra file transport or new
history limits.

## Linked Issues or Issue Description

Refs #13144, #13860, #13872, #13793.

Large wake payloads can exceed the operating system limit for one
environment entry. The launch-envelope fix in #13793 handles the outer
transport but leaves that child environment entry intact.

Credit to @nickyleach for the prompt-only approach in #13144. This PR
applies that part on current master. It does not include that PR's
30-item history limits or recovery-history endpoint. Those behavior
changes can be reviewed separately from the process launch fix.

## What Changed

- Stop exporting `PAPERCLIP_WAKE_PAYLOAD_JSON` in the shared ACP engine
and all ten built-in adapter writers.
- Ignore configured values of the retired variable so saved adapter
settings cannot restore the oversized entry. Also drop inherited copies
in Hermes, which builds its environment directly.
- Keep scalar runtime variables, existing prompt rendering, continuation
history, resume deltas, gateway bodies, and Hermes JSON template
variables.
- Document the prompt delivery contract and the migration for custom
instructions that read the retired variable.
- Test large local and sandbox child-process launches, fresh and resumed
ACP turns, SDK delivery, and configured-variable filtering.

## Verification

- `pnpm -r typecheck` passed.
- Focused adapter utility, ACP, Codex child-process, and Cursor Cloud
suites: 340 tests passed.
- Hermes execution and prompt tests: 18 tests passed using its package
Vitest configuration.
- The child-process tests deliver over 128 KB of context through stdin
and check the complete text. The ACP test retains 50 complete messages
and 50 completed actions, then checks the resumed delta.
- `pnpm build` passed.
- `pnpm test:run` was attempted, then stopped after it reproduced ten
macOS runtime-skill-cache permission failures (also reproduced on
unchanged master) and one HTTPS backfill test failure. The HTTPS test
passed when rerun unchanged on this branch and master. The complete
local suite was not completed; Linux CI provides the full-suite gate.
- CI is green on c3b8191f97: 53 checks passed and two skipped. Attempt 3
passed the remaining shards without source changes. Earlier attempts hit
a lost runner, preview readiness, and chat browser failures. The preview
test passed unchanged locally. Local chat tests passed 3/4; the
remaining sidebar focus-style assertion also fails on unchanged master.
No tests were weakened or skipped to obtain the passing rerun.
- The staged diff passed `gitleaks stdin --redact` and `git diff
--check`.

## Risks

- Custom instructions or scripts that read `PAPERCLIP_WAKE_PAYLOAD_JSON`
must use the wake payload in the prompt instead. The variable is absent
even for small wakes.
- This removes one cause of `E2BIG`. Legacy CLI paths for Gemini, Grok,
Kimi, Pi, and Hermes still pass prompts as arguments and retain their
existing argument-size limits. Other large environment variables also
remain subject to OS limits.
- No new context truncation, API route, database migration,
authorization change, or production rollout is part of this PR. Existing
prompt windows and resume rendering remain unchanged.

## Model Used

OpenAI GPT-6 through Codex, with code execution and repository tools.
The exact model variant 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-09-23 13:50:10 -07:00
DottaandPaperclip d9b3a5653e feat(chat): add initial Slack communication guidance and connection menus (#13760)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat connectors let people use the same tasks and agent tools from
external conversations.
> - Agents need communication guidance that fits the conversation
medium.
> - That guidance belongs in the original task context, without repeated
instructions on each turn.
> - Connection owners also need clear settings and a consistent way to
remove a connection.
> - This pull request adds initial Slack guidance, optional connection
instructions, and chat connection menus.
> - The benefit is clearer Slack replies with the existing Paperclip
workflow and permissions.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Agent replies in Slack and chat connection management in the Apps
catalog.

**Current behavior**

Slack tasks do not carry a saved communication profile. The catalog
shows a separate Manage button and does not offer removal on every chat
connection row.

**Proposed behavior**

Save Slack guidance when a new conversation creates a task. Restore that
original guidance when a model session is rebuilt. Do not append it to
ordinary follow-ups. Expose optional additional instructions in Slack
Settings. Put Manage and Remove connection in a three-dot menu for all
chat providers. Keep Finish setup visible for drafts.

**Reason and benefit**

Small answers fit in Slack. Substantial deliverables use ordinary
document or artifact tools with a useful Slack summary. Connection
settings apply to new tasks and cannot change permissions. Users can
remove both active and unfinished chat connections from the catalog.

**Breaking changes**

Two additive database columns store endpoint preferences and the initial
conversation snapshot. Existing endpoints default to empty preferences.
Existing conversations keep their original behavior. Non-Slack guidance
is unchanged.

Related public context:
https://github.com/paperclipai/paperclip/pull/13741 improves native chat
recovery. This change adds communication context to those existing
execution paths. A search found no duplicate communication-guidance PR.

## What Changed

- Add a provider-guidance registry, enabled for Slack first.
- Persist optional endpoint communication instructions and capture an
immutable snapshot when a conversation creates a task.
- Resolve guidance from the verified company-scoped connection. Restore
it for fresh native and legacy sessions without per-turn reminders,
extra model calls, or extra context queries.
- Add the Slack Settings field, validation, audit coverage, and
Storybook save/error states.
- Add Manage and Remove connection menus for all seven chat providers.
Keep the draft setup button. Require removal confirmation and allow
retry after failure.
- Add regression coverage, an active/draft menu story, and connector
documentation.

## Verification

All CI checks are green for 5f48df4e0. Greptile scored this head 5/5
with no actionable findings. No review threads remain unresolved.

- Passed `pnpm -r typecheck` and `pnpm build` on PR head 5f48df4e0.
- Passed design-token checks, UI typecheck, and all 20 catalog tests
after rebase. Tests cover all seven providers, active/draft removal,
confirmation, cache refresh, errors, and cancellation.
- Verified the active/draft menu in Storybook. The interaction test runs
without browser console errors.
- Passed focused guidance, endpoint persistence/isolation, heartbeat
trust, native context, ACPX, adapter utility, and CLI recovery tests.
Full UI and CLI groups passed (6,512 and 502 tests).
- Tested real Slack conversations on staging: concise updates with
public links, a planning question with buttons, a saved plan, a saved
report, task creation and assignment, and explicit detailed output. Old
tasks retained original preferences after an edit; a new task used the
changed preferences. Restored the staging setting afterward.
- Existing safe progress remained visible without duplicate final
replies or private reasoning.
- Broad local tests found resource/time-sensitive failures that passed
targeted reruns. One Cursor archive-download fixture failed on both this
branch and the unchanged main checkout. The full local suite is not
claimed clean. All PR-head CI test shards passed, including general,
serialized, Runner, and browser suites. The redundant local full-suite
rerun was stopped after CI completed successfully.
- Live delegation was not tested because the staging company has only
one agent. Live testing also found separate latency and runner
task-editing capability gaps; this PR does not add connector-specific
workflow behavior to hide them.

## Risks

- Prompt guidance changes the form of new Slack replies. Explicit
requests for detail still take precedence.
- The additive migration is idempotent. Conversation snapshots remain
fixed when connection settings change.
- Native and legacy recovery must preserve the initial context without
duplicates; targeted tests cover these paths.
- Removing a connection stops new work through the existing lifecycle
action. It retains Paperclip task history and does not delete the
external app or bot.

## Model Used

OpenAI GPT-6 through Codex, with repository editing, shell tools, and
browser testing. The host does not expose a more specific model ID or
context-window size. No separate model calls were added to the product.

## 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 (targeted suites; broad
local limitations are listed 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-09-21 14:14:25 -05:00
DottaandPaperclip 45c99a0d06 fix(adapters): default legacy harnesses and connected tools to full auto (#13693)
## Thinking Path

> - Paperclip lets people manage AI agents and their work.
> - Legacy adapters launch provider CLIs and expose connected tools.
> - Existing defaults did not consistently grant full automatic
permission.
> - Remote Claude used a fixed tool list that omitted MCP tools and
future tools.
> - Direct Codex launches and OpenCode configuration also used narrower
defaults.
> - This change gives all these paths the same full-auto default as
native runners.
> - Explicit restrictive settings continue to work.

## Linked Issues or Issue Description

Refs #13686. This PR is stacked on that native-runner and
task-reassignment PR. Merge #13686 first.

Related: #831 (constructed Claude agents), #1935 (adapter-switching
permission defaults).

## What Changed

- Use actual Claude permission bypass for local and remote runs and
probes. Remove the fixed tool list so MCP and future provider tools are
included.
- Identify actual managed sandbox targets to Claude with `IS_SANDBOX=1`.
Do not mark ordinary host execution as a sandbox.
- Default direct Codex execution to approval and sandbox bypass,
matching agent creation. Preserve explicit false, CLI profiles, sandbox
modes, approval policy, and network restrictions.
- Set OpenCode's full-auto runtime permission to `allow` for every tool
and connection. Preserve the existing explicit opt-out.
- Default Gemini probes to the same YOLO mode as execution. Make the
legacy ACP `default` alias use `approve-all` for fresh and resumed
sessions.
- Add default, opt-out, remote, probe, connected-tool, and resume
regression tests. Update adapter configuration documentation.
- Other adapter paths already request full automatic permission or have
no provider approval gate.

## Verification

- Full workspace `pnpm -r typecheck` and `pnpm build` passed locally
after rebasing onto current master. Targeted adapter/server and legacy
ACP tests passed, including defaults, explicit opt-outs, remote
launches, connected tools, and fresh/resumed sessions.
- Greptile reviewed current head
`8ca135eaffcf9cfdba6f1368e896a781a0891d50` at **5/5**. The security
reviewer acknowledged the documented full-auto requirement. Acknowledged
discussions are resolved.
- Current head has **54 passing checks**. [PR
checks](https://github.com/paperclipai/paperclip/pull/13693/checks). The
process-adapter signoff browser shard passed on one retry after its
first attempt exceeded a three-second issue-run wait.
- **Six native Claude/Codex real-provider cases passed on their first
attempt, with cleanup passing**, against the combined branch: plans,
reassignment, and backlog creation/status. [Campaign and downloadable
evidence](https://github.com/paperclipai/paperclip/actions/runs/35469926548).
This does not claim a real-provider run of every legacy adapter.
- The live-tested revision is
`a37881c824dcd7170380fc4b788732fc743e5da7`. The current head differs
only in the corrected heartbeat test expectation; application code is
identical.
- The campaign result-enforcement job passed. The separate report
publisher failed during frozen dependency installation because the
trusted workflow's patched-dependency configuration does not match its
lockfile. Passing case evidence remains downloadable from the workflow.
- Full-suite coverage comes from CI partitions. The separate unsharded
local run was stopped after the corresponding CI partitions passed; it
is not counted as a completed local run.

## Risks

- Missing permission settings now grant all provider operations,
including connected tools. OpenCode full-auto also overrides ambient
provider permission rules. An explicit Paperclip permission opt-out
preserves restrictive behavior.
- Claude refuses full bypass as root outside an identified sandbox.
Ordinary host deployments must run Claude as a non-root user. Managed
sandbox launches include the required marker.
- These defaults do not grant additional Paperclip roles, connections,
or company access. Existing controller authorization and governance
still apply.
- This PR depends on #13686. Retarget it to master after that PR merges.

## Model Used

OpenAI Codex, based on GPT-6, with code execution and repository tools.
The exact deployment 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-09-19 16:49:18 -05:00
02c7175e72 feat(agents): hired agents inherit provider credential references (#13268)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters need provider credentials to start work
> - A hired agent can lack the credential reference that its hiring
agent already uses
> - The child agent then cannot authenticate, even when the company has
a valid credential
> - This pull request copies matching credential references from the
hiring agent to the hired agent
> - The benefit is that hired agents can start with the provider access
that the hiring agent already uses

## Linked Issues or Issue Description

This change relates to [PR
#9920](https://github.com/paperclipai/paperclip/pull/9920), which covers
credential inheritance for other agent creation paths. This pull request
covers hiring-specific inheritance and fixed Claude OAuth binding
checks.

### What existing behavior does this improve?

The agent hire route builds the child adapter configuration from the
hire request only.

### Current behavior

A hired agent does not receive matching provider credential references
from its hiring agent. The child agent cannot run when the request omits
the credential.

### Proposed behavior

The hire route inherits matching credential references from the hiring
agent. The request keeps priority. A Claude hire that supplies any
Claude credential inherits none.

### Reason and benefit

The child agent can use the provider access that the hiring agent
already uses. The change copies references only and never copies raw
token values.

### Breaking changes

None. The change affects only hires that need an inherited reference.

## What Changed

- Copy matching credential references from the hiring agent into the
hired agent adapter configuration.
- Preserve pinned versions, `required`, and `allowMissingOverride`
fields on each copied reference.
- Keep hire-request credentials ahead of inherited credentials.
- Reject inherited fixed Claude OAuth bindings unless the parent agent
passes company, adapter, and exact-binding checks inside the same
transaction.
- Add route and service tests for inheritance, precedence, and binding
validation.

## Verification

- `pnpm exec vitest run --project @paperclipai/server
src/__tests__/agent-hire-auth-inheritance-routes.test.ts
src/__tests__/agents-claude-oauth-binding.test.ts` — 60 passed.
- `pnpm exec vitest run --project @paperclipai/server
src/__tests__/agent-hire-idempotency-routes.test.ts
src/__tests__/agents-service-secret-bindings.test.ts
src/__tests__/secrets-service-user-secret-owner-scoped.test.ts` — 28
passed.
- `tsc --noEmit` in `server/` — the error count matches the merge base,
with no error in either changed source file.
- `git diff --check` — clean.

## Risks

Low risk. The route copies references, not raw tokens. The request keeps
precedence. Company, adapter, and exact-binding checks protect the
inherited Claude OAuth path.

## Model Used

Codex, OpenAI GPT-5, with code execution and review support. The
implementation commit predates this pull request handoff.

## 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: nickyleach <331803+nickyleach@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-14 09:26:27 -07:00
DottaandPaperclip 827ba8a434 fix: cancel stalled sandbox startup without waiting for setup (#13352)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Sandbox runs prepare credentials and files before an agent starts.
> - Stop must work during that preparation.
> - ACPX registered cancellation, but did not handle it while a setup
command was waiting.
> - Daytona cleanup waited for that same command before stopping the
sandbox.
> - This change stops the run's sandbox first and requires proof before
abandoning setup.

## Linked Issues or Issue Description

**What happened?**

Stop left a sandbox run active when remote credential setup stalled. The
run kept its connection lease until the sandbox was stopped separately.

**Expected behavior**

Stop terminates the selected run's sandbox, prevents later setup from
launching the agent, and lets run cleanup finish. It must not report
success without proof from the provider.

**Steps to reproduce**

1. Start an ACPX agent in Daytona.
2. Hold a command during remote credential or file setup.
3. Select Stop before the agent starts.
4. Before this fix, cleanup waits for the held command and never reaches
sandbox stop.

Related: #13351 exposed this during connection acceptance testing.
#12150 addresses scheduler load and session initialization limits, a
separate startup problem.

## What Changed

- Handle cancellation during ACPX sandbox preparation with a host-owned
stop callback.
- Pass an explicit active-work cancellation flag through environment
cleanup.
- Stop Daytona before draining setup commands. Keep normal graceful
cleanup.
- Require an exact run and lease termination receipt. Keep ownership of
outstanding requests when stop cannot be verified.
- Reject late setup work and defer sandbox resume until old requests
settle.
- Add regression tests and document the cancellation boundary.

## Verification

- Red: both the stalled ACPX setup test and the Daytona cancellation
test failed before the fix because Stop never reached the provider.
- Green: adapter and Daytona suites passed, along with cancellation
boundary and database-backed receipt/isolation tests.
- Two real Daytona probes ran a five-minute setup command. Cancellation
returned matching stopped receipts in 6.01 and 6.533 seconds. No later
setup command ran. Both test sandboxes were deleted.
- Repository typecheck and build passed locally. The full required CI
suite passed, including all server/workspace tests, browser shards,
Paperclip Runner verification, and canary packaging. The duplicate local
full-suite run was interrupted after CI passed; it is not claimed as a
completed local pass.
- No UI changes. The live probe uses the actual adapter cancellation
boundary and Daytona plugin; it is not a browser acceptance test.

## Risks

- Provider stop failures remain unacknowledged. The adapter keeps
ownership while its original requests remain active.
- A retry can receive a settling-work error until old provider requests
finish.
- Cancelled sandboxes are stopped and retained under their existing
provider expiry policy.
- Local execution and cancellation after the agent turn starts keep
their current behavior.
- Other providers must return an exact termination receipt to permit
early setup cancellation. No database migration.

## Model Used

OpenAI GPT-6 through Codex, with code execution and tool use. The exact
deployment identifier 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-09-13 08:35:43 -05:00
DottaandPaperclip ab15aff390 feat: add experimental persistent agent chat (#13284)
## Thinking Path

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

## Linked Issues or Issue Description

**Subsystem affected**

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

**Problem or motivation**

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

**Proposed solution**

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

**Roadmap alignment**

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

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

## What Changed

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

## Verification

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

## Risks

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-12 08:56:04 -05:00
DottaandPaperclip 9031516a7e fix: recover legacy Daytona startup failures from task and inbox (#13272)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Legacy conversation adapters can run in Daytona sandboxes.
> - A server restart during provisioning can occur before the invocation
event exists.
> - Recovery then lacks the old adapter identity and leaves a hold that
ordinary user retries cannot clear.
> - A remote launch can also fail when its host relay looks for Node in
the sandbox PATH.
> - This pull request records the adapter at claim time and restores
explicit user continuation after verified cleanup.
> - Users can recover from the task or inbox while the failed run and
uncertain action history remain intact.

## Linked Issues or Issue Description

Refs #13237, #13239, #13254. Those changes cover recorded conversation
runs, native user continuation, and explicit remote Stop. This change
covers legacy failure before `adapter.invoke` and exact task/inbox
Retry.

Refs #9771 for overlapping generated-command quoting. This change also
supplies the absolute host Node executable. Refs #13163 and #13264 for
the separate native restart and retained-workspace work.

**What happened?**
A legacy Daytona run interrupted during provisioning became
`process_lost` without an invocation event. Recovery preserved an
execution hold, and Retry or a new task reply could not resume it.
Cleanup could also run before the Daytona plugin was ready. On a macOS
host, a subsequent ACP relay launch failed with `env: node: No such file
or directory` because the remote launch environment did not contain the
host Node path.

**Expected behavior**
An interrupted conversation can continue after its previous execution
stops. Explicit Retry and new user replies should start a fresh turn
with the task history. Cleanup failures must remain visible and
recoverable. The host relay must use the host Node executable.

**Steps to reproduce**
1. Use a legacy Claude adapter with a Daytona environment.
2. Interrupt the server after it acquires the sandbox lease and before
it records `adapter.invoke`.
3. Restart and inspect the task hold.
4. Retry from the task or inbox, or send a new task reply.
5. Confirm the old sandbox has stopped and one new response arrives.

**Paperclip version or commit**
Reproduced from master at `3bafac12f796fbea02e609e1074a9639f872e9c4`.
The branch is rebased on `51b0e01ea`, including #13261 and #13270.

**Deployment mode**
Built from source on macOS with a real Daytona sandbox and the legacy
Claude ACP adapter.

## What Changed

- Count new browser specs with the scheduler's median duration in the
shard-balance check. This fixes a false policy failure after new specs
arrive from both branches. The balance threshold is unchanged.

- Persist server-owned adapter identity in the queued-to-running claim
before provisioning starts.
- Wait for provider plugin startup before restart cleanup. Keep failed
cleanup leases as active ownership blockers.
- Admit exact board retries and new user comments after verified
termination. Retain the old run, task history, approvals, and unknown
action outcomes.
- Adopt repeated Retry requests. Permit one scoped cleanup attempt per
explicit user Retry after the automatic limit, with an activity record.
A later user Retry can recover after a transient provider failure;
automatic attempts remain capped.
- Resume replies deferred during cleanup, including historical legacy
startup failures.
- Launch the host ACP relay through the absolute host Node executable.
- Add a task-level Retry button and return actionable blockers when
retry admission is refused.
- Add database regressions and three browser recovery journeys. Exclude
installed third-party dependency skills from the shipped-skill audit.

## Verification

- Current head: `d23c84181`, rebased on `51b0e01ea`. Conflict resolution
retains the saved-message recovery, local stop receipts, and wait
reasons from #13270 alongside exact legacy Retry support.
- Real Daytona: interrupted the server after lease acquisition and
before adapter invocation. Restart cleanup confirmed provider
termination. Task Retry cleared a seeded historical hold and a real
Claude agent returned `Recovery verified.` in the task. Removed the
disposable sandbox and environment after testing.
- All three browser recovery journeys passed again after the final
rebase. Task Retry, Inbox Retry, and a new reply each produced one fresh
successor, completed the task, preserved the failed run, and retained
the answer after reload.
- All 29 e2e/server shard-partition tests passed. The balance check now
uses the scheduler's median fallback for unmeasured specs, with the same
balance threshold.
- Server typecheck passed after rebuilding the generated runner
dependencies. The combined recovery/route run passed 136 of 137 tests.
Its remaining route test timed out during the first cold module import
at its explicit 10-second limit; an isolated rerun reproduced that
timeout and passed the other 51 route cases. The complete CI suite
passed on this head. The same route file passed all 52 cases in CI,
including the first cold import in 7.5 seconds.
- Before the final rebase, recursive typecheck, full build, UI token
gates, 132 targeted server tests, and the complete [CI
workflow](https://github.com/paperclipai/paperclip/actions/runs/34650004085)
passed. The subsequent CI failure was the shard-balance accounting
mismatch fixed here.
- Greptile reviewed `d23c84181` at 5/5 with no outstanding actionable
findings. The complete [current CI
workflow](https://github.com/paperclipai/paperclip/actions/runs/34653327949)
passed on attempt 2. All test, typecheck, build, and canary jobs passed
on the first attempt. Docker setup timed out fetching BuildKit from
Docker Hub; retrying that job and its dependent aggregate succeeded.

## Risks

- Recovery admission changes executable authority. Company, task, agent,
user, approvals, process ownership, and provider termination checks
remain required.
- Explicit continuation starts a fresh conversation with history. It
does not certify unknown external action outcomes or rerun
non-conversation adapters automatically.
- Changing task status alone does not clear an execution hold. The task
now offers an explicit Retry action.
- Historical adapter claims and invocation events take precedence over
current agent settings. Known process or webhook runs retain their hold.
Pre-upgrade rows with no adapter evidence may receive only a new
explicit user turn after termination proof; they do not become eligible
for automatic replay.
- No schema migration or sandbox-image change is required. This branch
has not been deployed to production.

## Model Used

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-11 18:08:14 -05:00
Nicky LeachandPaperclip ad4f0b5867 Fix Codex API key authentication in tests and runs (#13260)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent runtime settings can bind organization secrets to an adapter
environment
> - Paperclip redacts plain environment values when it returns a saved
agent to the UI
> - A saved-agent test sent the redacted `CODEX_HOME` value back to the
server
> - Codex ACP also received the API key without an ACP API-key
authentication request
> - This pull request restores saved environment values for tests and
selects API-key authentication for Codex ACP runs
> - The benefit is that Codex agents can test and run with an
organization-scoped OpenAI API key

## Linked Issues or Issue Description

**What happened?**

Testing a saved Codex agent sent `***REDACTED***` as `CODEX_HOME`.
Secret normalization rejected that placeholder. Remote Codex ACP runs
received `OPENAI_API_KEY`, but session creation stopped with
`Authentication required`.

**Expected behavior**

Paperclip must use the saved `CODEX_HOME` value when it tests an
existing agent. Codex ACP must select API-key authentication when
`OPENAI_API_KEY` is available.

**Steps to reproduce**

1. Create an organization-scoped secret named `OPENAI_API_KEY`.
2. Give a Codex agent access to the secret.
3. Save the agent runtime settings.
4. Test the saved agent again.
5. Run the agent in a remote sandbox through ACP.

**Paperclip version or commit**

Reproduced on master before commit
`68c17709d7c051a804a416263e2e08920f1dfcb1`.

**Deployment mode**

Self-hosted server with a remote sandbox environment.

**Installation method**

Built from source.

**Agent adapter(s) involved**

Codex.

## What Changed

- Send the saved agent ID with adapter environment tests.
- Restore redacted plain environment values from the saved agent before
test-time secret resolution.
- Select the Codex ACP `api-key` authentication method when
`OPENAI_API_KEY` is present.
- Add focused regression coverage for saved-agent tests and remote ACP
launch configuration.

## Verification

- `pnpm --filter @paperclipai/adapter-utils exec vitest run
src/acpx-engine/execute.test.ts`
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/agent-adapter-validation-routes.test.ts`
- `pnpm --filter @paperclipai/ui exec vitest run
src/lib/test-agent-setup.test.ts`
- `pnpm -r typecheck`
- `pnpm test:run`
- `pnpm build`
- `git diff --check`

## Risks

- Low risk. The test route reads saved configuration only when the
request supplies a compatible agent ID and the caller can update that
agent.
- The Codex ACP change applies only when `OPENAI_API_KEY` exists and no
explicit `DEFAULT_AUTH_REQUEST` exists.
- There are no schema migrations or telemetry changes.

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

## Model Used

- OpenAI Codex with `gpt-5`. The context-window size is not exposed in
this runtime. The model used reasoning, repository search, file editing,
command execution, and test execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-11 13:58:29 -07:00
Nicky LeachandPaperclip 87b3e5fc61 fix(adapter-utils): stage selected skills into the sandbox for a remote Claude ACP run (#13196)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - A user selects skills for an agent, and the host materializes those
skills into a bundle the agent reads
> - An agent can run in a remote sandbox, where the host must stage
every file the agent needs
> - On the Agent Client Protocol lane the host built that bundle and
then named its host path in the prompt, but it never staged the bundle
into the sandbox
> - The agent therefore read a path that does not exist inside the
sandbox, and the run failed on the missing skill file
> - The command-line lane of the same adapter already stages a `skills`
asset and reads the in-sandbox directory back from the staged runtime
> - This pull request carries that proven pattern to the Agent Client
Protocol lane, so a selected skill reaches the agent in a remote run

## Linked Issues or Issue Description

No public issue exists for this change. The description follows.

**What happened?**

A remote run of the Claude adapter on the Agent Client Protocol lane
could not read any selected
skill. The host builds the skill bundle in its own state directory, then
writes that host path into
the prompt as `Skill root: <path>`. The remote seam of that lane staged
one asset only, the
configuration seed. It staged no skills asset, so no skill file crossed
into the sandbox. The agent
then tried to read the skill file at the host path, and the read failed
with a missing-file error.

**Expected behavior**

A remote run receives the skills the user selected, and the prompt names
the directory that holds
those skills inside the sandbox.

**Steps to reproduce**

1. Select one or more skills for an agent that uses the Claude adapter.
2. Start a run for that agent in a remote sandbox on the Agent Client
Protocol lane.
3. Ask the agent to read the skill file at the path the prompt names.
The file is not there.

**Agent adapter(s) involved**

The Claude local adapter, on its Agent Client Protocol lane. The shared
engine in
`packages/adapter-utils` carries the prompt rewrite.

**Additional context**

The command-line lane of the same adapter already stages a `skills`
asset and remaps onto the staged
directory. This change reuses that mechanism instead of adding a new
transport. One other adapter
shows the same host-path shape on its own Agent Client Protocol lane.
That lane is tracked
separately and this pull request does not change it.

## What Changed

- Return the host skill bundle directory from the Claude skill runtime
step, and carry it through the
remote managed-home context to the staging seam. The value is null for a
non-Claude agent, for a
run that selects no skill, and for a run whose selected skills all fail
to materialize.
- Stage that bundle as a `skills` asset on the Claude Agent Client
Protocol remote seam, and only
  when the run selected a skill.
- **Stage that asset with `followSymlinks: false`.** The bundle holds an
owned copy of each selected
skill, and the copy step never copies a symbolic link at the root or at
any depth. So the bundle
contains no symbolic link, and staging has none to follow. Refusing to
follow one also stops a link
planted in the bundle directory after the copy from pulling an unrelated
host file into the sandbox.
A regression test walks the real adapter sources and pins the reviewed
`followSymlinks` value at
  every skills staging site, so a new or changed site fails the test.
- **Drop a skill whose staged copy has no usable `SKILL.md`** from the
prompt, the skill identity, the
command notes, and the bundle, and log which skill was dropped and why.
Without this, a skill whose
copy failed, or whose `SKILL.md` is a symbolic link the copy step skips,
stayed advertised in the
prompt while its file was absent — the same missing-file symptom this
change exists to fix.
- Rewrite the `Skill root:` prompt line, the skill identity, and the
command notes onto the
in-sandbox directory. The rewrite runs in the engine, after the
workspace placement returns the
staged runtime. A compatible session resume reuses the cached staged
runtime, so the rewrite runs
  on that path too.
- Keep the session fingerprint on the host-independent skill identity. A
change to the selected skill
set still invalidates a warm session, and the volatile sandbox path
stays out of the hash.
- A local run, and a run with no selected skill, keep their current
behaviour.

## Verification

- `pnpm exec vitest run --project @paperclipai/adapter-claude-local
src/server/acp.test.ts` — 28 of 28
  pass.
- `pnpm exec vitest run --project @paperclipai/adapter-utils
src/acpx-engine/execute.test.ts
src/skills-staging-follow-symlinks.test.ts`
  — the new engine tests and the staging-site tests pass.
- `pnpm --filter @paperclipai/adapter-utils exec tsc --noEmit`, and the
same check on the adapter
  package — both exit 0.
- The end-to-end test drives the lane against a local sandbox stand-in.
It reads the skill root out
of the prompt the runtime received, and then opens the skill file at
that path. That is the
  reported symptom, proved closed.
- The new tests carry a sensitivity control. Restoring only the
production files to their previous
content fails 7 of the 9 new tests. The other 2 do not depend on
production code: one is a parser
  unit test for the source scanner.

## Risks

Low risk, and the change is a two-way door. A revert restores the
previous behaviour exactly.

- **Scope.** The change touches one adapter lane. It does not change the
local lane, and it does not
change any other adapter. No existing staging site changes its
`followSymlinks` value.
- **The staged bundle and the workspace.** The staged skills land under
the runtime directory inside
the workspace. The workspace restore excludes that whole runtime
directory, so the staged skills
never return to the host worktree. A test proves the exclusion end to
end.
- **Session reuse.** The rewritten path never enters the session
fingerprint, so it cannot invalidate
  a warm session, and a compatible resume applies the same staged path.
- **Direction of data.** Files move from the host into the sandbox only.
The change adds no path that
  writes sandbox content onto the host.
- **A dropped skill.** A skill with no usable `SKILL.md` is now absent
from the prompt instead of
named but unreadable. The run logs the skill and the reason, so the
cause is visible.

## Model Used

Claude Opus 5 (`claude-opus-5`), with extended thinking and tool use,
through Paperclip agents.

## Test plan

- [x] `pnpm exec vitest run --project @paperclipai/adapter-claude-local
src/server/acp.test.ts` passes — 28 tests.
- [x] `pnpm exec vitest run --project @paperclipai/adapter-utils
src/acpx-engine/execute.test.ts
src/skills-staging-follow-symlinks.test.ts` passes.
- [x] `pnpm --filter @paperclipai/adapter-utils exec tsc --noEmit` exits
0.
- [x] All continuous-integration gates are green.
- [x] The automated review reports no open finding against the current
head.

## Required 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 bug report
template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run the targeted tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect this change
- [x] I have considered and documented the risks above
- [x] All continuous-integration gates are green
- [x] The automated review score is 5/5 with no open current-head
findings
- [x] I have addressed every reviewer comment that applies to the
current head

**Note on the branch history.** This branch first carried a different
change: a filename-based admission filter that refused to stage files
such as `.env` from a skill directory, together with a switch from
symbolic-link bundles to copied bundles. That approach was rejected and
**reverted** on this branch. It does not match the documented trust
boundary, because the host already delivers credentials into the sandbox
on purpose, and replacing the symbolic-link bundles broke live editing
of a skill. The revert is in this branch's history. The file that work
changed, `packages/adapter-utils/src/server-utils.ts`, is byte-for-byte
identical to `master` here and is not part of this diff. Earlier review
findings that name that file target the reverted code. All of them are
resolved, and the automated review passes on the current head.

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-11 07:50:06 -07:00
Nicky LeachandPaperclip d1ba17eeca fix(adapter-utils): fail fast when the sandbox control channel is lost mid-turn (#13158)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Adapter utilities run agent turns and report their results to the
control plane
> - A lost sandbox control channel can leave an agent turn without a
result
> - The host then waits for the full adapter timeout instead of
reporting the loss
> - This pull request adds a push loss signal and a bounded host wait
> - The benefit is a prompt failure terminal when the agent stops
answering

## Linked Issues or Issue Description

**What happened?**

A sandbox control channel loss during an Agent Client Protocol turn left
the host waiting for the four-hour adapter execution timeout.

**Expected behavior**

The host should detect the terminal channel loss, stop the turn, and
report a safe failure without waiting for the agent.

**Steps to reproduce**

1. Start an Agent Client Protocol turn through a sandbox adapter.
2. Close the duplex control channel while the turn remains active.
3. Observe the host response before the adapter timeout expires.

**Paperclip version or commit**

Test the pull request commit set at
`10b6bbc5525a79fd575298607dd5a25ae448fc8a`.

**Deployment mode**

The change applies to sandbox-backed adapter execution.

## What Changed

- Add `onLoss(listener)` to the duplex bridge handle.
- Register the loss listener at turn start and read losses latched
before turn start.
- Cancel the turn on loss and arm a 30-second host deadline.
- Close the stream locally when the deadline wins and create a host
terminal.
- Derive the public error from the closed `DuplexLossReason` enum.
- Add tests for loss order, cancellation, timeout, and safe error
output.

## Verification

- Run `pnpm --filter @paperclipai/adapter-utils exec tsc --noEmit`.
- Run `pnpm --filter @paperclipai/adapter-utils exec vitest run
src/acpx-engine/execute.test.ts -t "run-disposition seam"`.
- Confirm that the full pull request workflow passes.

## Risks

The new deadline changes a lost-channel path from a long wait to a
host-built failure after 30 seconds. Orderly completion keeps its
existing behavior. The deadline race against a pending `turn.result` has
no direct test.

## Model Used

OpenAI Codex, GPT-5, with tool use and code execution. The runtime does
not expose a more specific deployment version 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
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-10 15:37:05 -07:00
DottaandPaperclip 889947c238 feat: add experimental native chat connectors (#13038)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People also ask agents for work in their existing chat tools.
> - Each external conversation needs one task and a current authorized
source.
> - Retries, Stop, and provider failures must not duplicate work or
expose private data.
> - The first chat PR establishes the opt-in provider and data
contracts.
> - This PR adds experimental channel integration and its durable
control plane.
> - Users can request work from connected channels and inspect delivery
in Paperclip.

## Linked Issues or Issue Description

Refs #13100 and #13092. This is the second of exactly two chat PRs.
Foundation #13100 is merged and changed 143 files. Runner prerequisite
#13092 is also merged. This PR changes 400 files against master, below
the 500-file review limit. It contains no wireframe images or HTML
galleries.

## What Changed

- Add native Slack, GitHub, Microsoft Teams, Telegram, and Discord chat
connections. Keep chat disabled unless the operator enables experimental
chat connectors. Preserve the production GitHub tool connection and its
normal setup path.
- Bind each provider bot identity to one immutable Paperclip agent. Bind
each admitted external conversation to one task. Paperclip owns tasks,
runs, permissions, and audit records.
- Add durable admission, per-conversation queues, questions, task
controls, progress, final replies, images, files, and delivery receipts.
Board comments remain internal unless explicitly sent to the channel.
- Check current identity, provider reach, resource access, credentials,
runtime generation, and exact source before provider effects. Keep
private responses private. Never send raw reasoning, private logs,
credentials, or tool arguments.
- Hold uncertain sends for explicit audited resolution. Make Board
Send-to-channel atomic and idempotent. Keep reconnect and setup
credentials in Paperclip secret storage.
- Preserve current native-runner authority across retries, lost
acknowledgements, and recovery. Keep immutable input and completion
contracts separate from newer user input. Receipt reconciliation cannot
launch a provider.
- Reconcile chat close/new ordering and provider-effect lock order.
Audit resource access changes in the same transaction. Submit only the
selected resource from each UI toggle so stale pages cannot undo
unrelated access changes.
- Drain Codex stdout before certifying process exit. Bound the drain
with the existing shutdown grace. Preserve observed terminal authority
without treating an undrained process as successful or reusable.
- Incorporate master `018ca5da` with its ACP Stop, mobile task layout,
runner packaging, and official lock changes. Preserve dedicated
chat-answer continuations in both directions when ordinary queued
comments are adopted after Stop.
- Fence late adapter readiness behind an earlier Stop for the same run.
Preserve verified cleanup for registered adapters. Handle single Stop,
agent pause, duplicate Stops, and failure release without creating a
false cancellation receipt.
- Incorporate master's `6dd48cad4` wake-queue extraction. Preserve exact
failed-chat retry authorization and lineage, retired question-source
suppression, and the block on generic recovery that would discard the
admitted source. Fresh deferred input retains its separate promotion
path.
- Incorporate master `2a05b5ed3` and its queue-admission extraction,
simplified transaction ports, and separate runner CI job. Preserve exact
durable receipts, actor separation, and dedicated-answer isolation
through the new module. A failed receipt insert rolls back the
accompanying deferred-wake merge.

## Verification

Current head: `afe19299d06253cb628eb398e91d1200ea9f412a`, incorporating
master `2a05b5ed3457ea33efd6895520447d1d97fe98d8`. The conflicts are
resolved. This successor fixes two test-harness boundaries exposed by
CI: per-case route-module preparation and actual durable-save completion
before intentional runner termination. Production code and all existing
test/turn deadlines are unchanged. [Exact-head Greptile
review](https://github.com/paperclipai/paperclip/pull/13038#issuecomment-5587250594)
is **5/5**, completed September 10 at 13:20:55 UTC, with no actionable
findings or open review threads. [Fresh exact-head
CI](https://github.com/paperclipai/paperclip/actions/runs/34481724341)
passes **all 24 jobs**, including Build and both required aggregates.
Normal exact-head guarded merge was attempted and rejected by the
remaining branch approval policy: CODEOWNER review is required and no
human approval is present. Normal **squash auto-merge is enabled** as of
September 10 at 13:36:26 UTC. Requested CODEOWNERS have been notified;
no approval bypass or self-approval was used. Earlier-head results below
remain historical evidence, not qualification of this successor.

- Final exact-head Linux evidence: 995/995 chat integration cases; 36/36
agent-skills routes; 35/35 runner live-session cases, including real
process kill/resume; 1948 runner Vitest cases with three existing
benchmark/platform guards; 870/870 API-authority cases; and 104 browser
cases with four existing optional skips. Rust, conformance/replay, full
repository build, typecheck, canary, all server/workspace shards, and
both required aggregates pass with normal CI concurrency. Earlier failed
attempts remain recorded below.

- Latest test-only qualification: 141/141
route/permissions/authentication cases pass in separate cold forks, with
plain server types and independent review clear. The real-runner suite
passes 35/35, with plain runner types and independent review clear. A
controlled premature-save acknowledgement fails as expected; matching
ownership/effect/process evidence, rejected saves, real turn outcome,
test abort, and pre-kill liveness are covered. No local reproduction of
the original CI scheduling failure is claimed. The preceding [CI
run](https://github.com/paperclipai/paperclip/actions/runs/34479680858)
passes 21/24 jobs, including all 995 Linux chat cases and browser
aggregate (104 passed, four existing optional skips); only Build, the
skills serialized shard, and the required verification aggregate fail.
Its exact-head Greptile review was 5/5. Both failed job logs are
retained.

- Final fixture qualification: all eight focused Discord cases and all
995 chat integration cases pass. The exact modal statement/PID is
observed before taking the real connection lock; the test then proves
its actual blocking relationship before mutation. Original SQL
execution, provider behavior, negative assertions, and 1s/15s timeouts
remain unchanged. Independent review is clear and test/production hashes
remain frozen. The preceding [CI
attempt](https://github.com/paperclipai/paperclip/actions/runs/34477184777)
passed 22 jobs, including Build/runner, typecheck, canary, all other
test shards, and browser aggregate (104 passed, four existing optional
skips); the two fixture failures and failed verification aggregate
remain recorded, not relabeled as a pass.

- Current queue-module composition: 308/308 recovery/batching/queue/Stop
tests; 995/995 full chat integration; 89/89 module tests, including real
PostgreSQL receipt-insert rollback; 24/24 workflow/module-boundary
tests; plain server and UI types. All four actual local process/ACP
browser paths pass in 1.4 minutes. Fresh databases, no skips or retries,
stable reviewed source hashes. The initial boundary failure is retained;
its no-op service wrapper was removed without changing recovery context
or weakening the check. An exploratory standalone test-directory
typecheck fails because its new upstream transformation config is not a
standalone typechecking project; standard CI/build does not invoke it,
and no configuration was weakened to suppress those diagnostics.

- The preceding head `e02a63d462ce5d47433b0aeb632bb6fd20aab1ba` passed
[all 24 CI
jobs](https://github.com/paperclipai/paperclip/actions/runs/34436462958)
and exact-head Greptile review at 5/5. Required CODEOWNER review
prevented its normal merge before master advanced again.

- Final extracted-module composition: 307/307 recovery, batching, queue
and Stop-control tests; 995/995 full chat integration; 49/49 module
tests including eight PostgreSQL adapter cases; and 19/19 issue-update
tests. Plain server types pass. All four actual local process/ACP
browser paths pass in 1.3 minutes. Fresh databases, no skips or retries
in these cohorts, frozen source hashes, and independent review clear.

- The preceding head `3e4e1c1c` passes [all PR CI
jobs](https://github.com/paperclipai/paperclip/actions/runs/34415826820),
including Build and required `ci / verify` and `ci / e2e`. Both the
original Rust failure and the previously load-sensitive lineage fixture
pass with unchanged Linux concurrency. Master advanced afterward and
required this reconciliation.
- Final master composition: 448/448 focused UI tests, 186/186 adapter
tests, 24/24 queue/control tests, and 11/11 packaging tests. Plain UI,
server, shared, and adapter types pass. Token gates and diff checks
pass. Independent server and UI reviews are clear.
- Stop-registration regression: both real-service cases fail against
exact `a95` source and pass with the fix. The full corrected
recovery/control suite passes 265/265. Duplicate-owner and failed-Stop
controls also pass. Plain server types pass. The readiness barrier
prevents provider startup without adding an acknowledgment to an already
terminal run.
- Final qualification strengthens terminal-field equality and repeats
both affected cases successfully on a fresh database. All four actual
local process/ACP browser paths pass again in 1.3 minutes, without skips
or retries. The final screenshot shows Cancelled, a paused subtree,
retained input, and no error toast.
- Two new actual-service regressions fail before the merge fix. They
prove that queued-comment adoption could consume a dedicated chat answer
or add unrelated input to that answer. The fixed four-case cohort
passes, including ordinary upstream continuation and adapter Stop
controls. Full recovery passes 257/257. All four actual local
process/ACP Stop browser flows pass in 1.4 minutes, without skips or
retries, on a fresh database.
- The unchanged runner artifact was qualified with 171/171 transport
tests, 870/870 API-authority tests, conformance 1/1, and replay 11/11.
Six controlled reader tests prove the exit/drain repair. Its local
serial Rust workspace passed 546 top-level cases plus two invoked
helpers; the later passing Linux CI supplies default-concurrency
evidence.
- Prior exact-source full chat integration passes 995/995. Settings
regressions cover concurrent stale pages, 501 destinations, pending
state, rejected updates, and explicit retry. These deterministic tests
do not prove live provider behavior.
- Retained failed attempts and their causes are in the [qualification
log](https://github.com/paperclipai/paperclip/blob/afe19299d06253cb628eb398e91d1200ea9f412a/doc/plans/chat-adapters/2026-09-08-chat-queue-and-webhook-repair.md).
The first merge adapter run timed out while macOS slept for 290 seconds.
Its unchanged repeat passed with a temporary sleep guard. No assertion,
deadline, or CI gate was weakened.

Review commands include `pnpm --filter @paperclipai/server exec vitest
run src/__tests__/heartbeat-process-recovery.test.ts
src/__tests__/issue-queued-comments-routes.test.ts` and `pnpm exec
playwright test --config tests/e2e/playwright.config.ts
tests/e2e/acp-stop-continuation.spec.ts`. Database suites require fresh
disposable databases. See the [browser
runbook](https://github.com/paperclipai/paperclip/blob/afe19299d06253cb628eb398e91d1200ea9f412a/doc/plans/chat-adapters/2026-09-04-chat-adapters-browser-e2e-runbook.md)
for provider setup and separate live acceptance steps.

## Risks

- This remains experimental. Deterministic tests and bounded live
evidence do not establish every provider feature, tenant, permission
layout, or media shape. Teams work-tenant qualification is still open.
- Failed and uncertain provider effects remain visible and can require
operator action. A transport receipt does not prove recipient
visibility.
- Native controller and runner artifacts must remain compatible.
Preserve lease ownership, terminal authority, source binding, and
quarantine during future changes.
- Access and audit rows commit together, but activity notifications
remain best-effort. This is not a new durable event outbox.
- The PR operation does not deploy a live server, replace its runner, or
change provider permissions. Remaining live qualification is documented
in the [temporary
handoff](https://github.com/paperclipai/paperclip/blob/afe19299d06253cb628eb398e91d1200ea9f412a/doc/plans/chat-adapters/2026-09-08-open-qualification-followups.md).

## Model Used

OpenAI Codex assisted with implementation, tool execution, testing, and
review. The work records `gpt-6-astra` assistance. The environment does
not report a context-window size. No private reasoning traces are
included.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-10 10:06:45 -05:00
DottaandPaperclip 018ca5daaf fix: verify ACP Stop and preserve safe continuation (#13119)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task controls coordinate provider execution and queued user
messages.
> - Stop could finish before an embedded ACP provider stopped its tools.
> - A later request could be held for reconciliation without a clear
task response.
> - A restored provider could also retain the stopped run's API
credential.
> - This pull request verifies provider termination and preserves safe
session continuation.
> - Operators can continue known-safe work and see why uncertain work
cannot start.

## Linked Issues or Issue Description

**What happened?**

Stop could leave an embedded ACP provider running. A queued follow-up
followed by “go” could fail before it reached the provider. Task chat
could show a generic missing-response message. Even a restored session
could use the previous run's credential and fail its task update.

**Expected behavior**

Stop waits for confirmed provider termination. A later explicit wake
continues the same compatible session only when recorded actions have
known outcomes. It carries pending comments and the current run's
environment. Uncertain actions retain a visible reconciliation hold.
Composer Stop preserves the existing pause rule: conversation can
continue while paused, but task work requires Resume.

**Steps to reproduce**

1. Start an embedded ACP task.
2. Send a second request while the provider is running.
3. Interrupt the run, then send “go”. Also test composer Stop followed
by Resume work.
4. Check that the request is delivered once and that the provider can
complete the task through the current run's API credential.
5. Repeat with an unfinished write. Confirm that the write stops and
that further execution stays blocked with a visible reason.

**Paperclip version or commit**

Built from source on master at `3bc60dd8b` plus this branch.

**Deployment mode**

Local source build with an isolated embedded PostgreSQL instance.

Refs #11183. Refs #12552. Those changes address recovery after operator
cancellation. This change also covers embedded ACP termination, session
proof, pending-comment delivery, and task feedback.

## What Changed

- Propagate Stop into embedded ACP and wait for bounded adapter cleanup
and provider exit. Retain the actual ChildProcess object for forced
termination on all platforms; never signal a recycled numeric PID.
- Preserve interrupted checkpoints only for acknowledged, local,
persistent sessions with settled reads or no tools. Keep writes,
incomplete actions, and forced termination blocked.
- Restore the same compatible provider session with the current run's
environment. Reject fresh-session fallback for an interrupted
checkpoint.
- Adopt pending comments on the next explicit wake. Stop alone does not
dispatch them.
- Share the execution-blocker rule across dispatch, Resume, and task
detail. Show Stopped or Couldn't start with the recorded reason. Resolve
the stopped agent for the run link, including reviewer runs.
- Keep execution reconciliation holds intact when generic recovery sees
queued comments or healthy child tasks.
- Add process, service, component, and browser regression coverage. Fix
disposable database cleanup and React test settling exposed by the full
suite.

## Verification

- Passed `pnpm -r typecheck`, `pnpm build`, and `pnpm
check:token-gates`.
- Passed all three `acp-stop-continuation.spec.ts` browser journeys.
They use an actual ACP child process and require task completion through
the agent API.
- Passed 165 adapter execution, operator-stop, and child-process control
tests, 17 queued-comment route tests, and 65 tests in the two adjusted
UI suites. Earlier focused recovery, heartbeat, and task-control tests
also passed.
- Manually used the browser to queue a request, Stop, send “go” while
paused, and Resume. The same session answered once and moved the task to
Done with the current run's credential.
- Manually interrupted an unfinished write. Its file size stayed fixed
for five seconds. “Go” showed the reconciliation reason and did not
start another provider prompt.
- Separate live Claude ACP smoke checks confirmed that Stop ended a
disposable local write and that a no-tool interruption could resume the
exact provider session. The browser fixture does not call Drive or
another external app.
- Passed all 5,615 UI tests and 3,090 other workspace tests. The CLI and
general server groups pass with targeted retries: two transient server
failures passed together on retry, and two embedded-database startup
failures passed after removing abandoned shared-memory segments from
this task's completed browser fixtures. All 144 serialized server suites
completed, with 2,189 tests passing after two transient HTTP socket
failures passed on retry.
- Passed all 135 heartbeat process/recovery tests, including a
deterministic regression that failed before the recovery-sweep fix.
- Passed 18 dispatch integration tests, including stopped-reviewer
links, company boundaries, and malformed run IDs.
- Greptile is 5/5 on `7dd170d83`, with zero unresolved review threads.
The security scan and all required CI gates pass for the same commit.

## Risks

- Safe continuation depends on complete tool reporting and a restorable
local provider session. Unknown outcomes remain blocked and require
reconciliation.
- Provider cleanup can take time. A timeout does not grant replay
permission.
- The change adds optional adapter context fields and an optional issue
projection. It does not change the database schema or require a
migration.
- Test cleanup truncates company data only in a disposable test
database.

## Model Used

OpenAI GPT-6, running as Codex with repository tools, code execution,
and browser interaction. The runtime does not expose a more specific
model deployment 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
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-09 22:06:06 -05:00
DottaandPaperclip cabc9146d0 feat(apps): add secure remote MCP and PostHog setup (#12339)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Apps give those agents governed access to external tools.
> - Remote MCP setup needs secure endpoint validation and durable
credentials.
> - PostHog needs both browser sign-in and personal API key setup paths.
> - This pull request adds the shared remote MCP foundation and the
PostHog definition.
> - The benefit is a secure and reusable base for later app connection
work.

## Linked Issues or Issue Description

Refs #11965

This is stack 1 of 11. It replaces the first reviewable part of #11965.

## What Changed

- Add guarded remote MCP setup and credential handling.
- Add PostHog OAuth and API key connection methods.
- Add focused server, shared contract, and UI coverage.
- Keep the migration replay-safe and idempotent.
- Give the late-close security regression the same 10-second CI headroom
as the adjacent real-timer handshake test.
- Synchronize fake-timer handshake tests at the exact ensure-session
boundary so real filesystem setup cannot race the fake deadline.
- Drive PTY overflow coverage only after listener registration so
scheduling cannot reorder the test fixture.

## Verification

- pnpm exec vitest run
packages/adapter-utils/src/acpx-engine/execute.test.ts
server/src/__tests__/plugin-worker-manager.test.ts (220 passed; affected
cases also passed five focused stress repetitions)
- `pnpm exec vitest run
packages/adapter-utils/src/acpx-engine/execute.test.ts -t "never leaks a
sandbox-provided value from a late close rejection into logs or the
result"` (1 passed)
- `pnpm exec vitest run
packages/adapter-utils/src/acpx-engine/execute.test.ts -t "never
promotes a late ensureSession resolution|closes a late-resolving real
handle exactly once"` (2 passed)
- `pnpm -r typecheck`
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/tool-access-service.test.ts`
- `pnpm --filter @paperclipai/db check:migrations`
- `pnpm build`

## Risks

- Remote endpoint validation can reject configurations that previously
passed without checks.
- OAuth configuration errors can block setup until the operator corrects
the provider settings.
- The migration uses guarded statements so repeated execution is safe.
- The test-only synchronization changes do not affect runtime behavior;
they remove filesystem/fake-clock and listener-registration races
observed under parallel CI load.

> I checked `ROADMAP.md`. This stack continues the existing app
connection work from #11965 and does not duplicate another planned item.

## Model Used

OpenAI Codex, GPT-5. The runtime model ID and context window were not
exposed. The model used reasoning, tool use, and code execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-29 12:08:32 -05:00
Nicky LeachandPaperclip a20a4944ec feat: add Grok device login to the sandbox login panel (#12469)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip uses adapters to connect agents and model providers to its
control plane
> - The sandbox login panel supports displayed-code login for selected
adapters
> - Grok users need the same login path and a private credential home
for later runs
> - This pull request adds Grok support to the shared device-login path
and preserves the existing Codex path
> - The benefit is one secure login flow for both adapters with
company-scoped credential storage

## Linked Issues or Issue Description

**Agent or provider**

Grok Local needs displayed-code login support in the sandbox login
panel.

**Why this adapter is useful**

This change lets users sign in to Grok from the sandbox login panel. It
also gives later Grok runs access to the stored credential.

**How the agent is invoked**

The Grok local adapter uses its login command through the shared
displayed-code login flow. Later runs receive the managed home through
`GROK_HOME`.

**Additional context**

The change uses adapter-scoped login lifecycle handling. It stores the
credential in a company-scoped directory with mode `0700`, and it stores
the credential file with mode `0600`.

## What Changed

- Rename the shared device-login modules to adapter-neutral names.
- Scope the shared login lifecycle to a closed adapter set.
- Return the device-login URL that the provider prints.
- Add the Grok prompt parser, login command, capability, and login panel
entry.
- Store the Grok credential in a private, company-scoped home directory.
- Pass `GROK_HOME` to later Grok runs.
- Add tests for the Grok adapter, the Daytona sandbox provider, the
server login path, and the user interface.

## Verification

- Run `pnpm vitest run
packages/adapters/grok-local/src/server/adapter-auth-promotion.test.ts`.
- Run the Grok adapter package suite.
- Run the Daytona sandbox provider suite.
- Run the server device-login suites.
- Run the user interface suite.
- Confirm the full CI suite passes.

## Risks

The change extends shared login lifecycle code to another adapter. A
regression could affect Codex login. The credential path uses explicit
`chmod` calls to keep the directory at mode `0700` and the file at mode
`0600`.

## Model Used

OpenAI Codex, GPT-5. The runtime used tool calls and code review
support. The runtime did not provide a context-window value.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-28 21:48:34 -07:00
Nicky LeachandPaperclip e127faa14c fix(adapter-utils): bound the ACP startup handshake and fence the abandoned session promise (#12454)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Adapter utilities start and control agent sessions.
> - The ACP startup handshake can stay pending when the sandbox
transport closes.
> - A pending handshake keeps the run active and prevents a clear
operator result.
> - This pull request bounds the handshake and fences its abandoned
promise.
> - The result gives each startup failure a terminal state and a safe
host-authored diagnostic.

## Linked Issues or Issue Description

No matching public issue or pull request appeared in the GitHub search
for this failure. The issue details follow.

**What happened?**

The adapter engine awaited `runtime.ensureSession()` without a startup
bound. A lost sandbox transport could leave the await pending.

**Expected behavior**

The engine must end the run when the startup deadline expires or the
duplex transport closes. A late session result must not reopen the
settled run.

**Steps to reproduce**

1. Start an ACP-backed agent run.
2. Keep the ACP initialization call pending.
3. Let the startup deadline expire or close the duplex transport.
4. Confirm that the run reaches a terminal state and that a late session
result does not reopen it.

**Paperclip version or commit**

`66e1c0df8b23cb8354b36dd446d9548dc4389191` merge base.

**Deployment mode**

Local dev (`pnpm dev`).

**Installation method**

Built from source (`pnpm dev`).

**Agent adapter(s) involved**

Custom / external plugin adapter.

**Database mode**

Not database-related.

**Relevant logs or output**

The new tests use fixed host-authored diagnostics for handshake guard
failures and late close failures.

**Additional context**

The change updates the execution semantics document and adds regression
coverage. The three existing failures in `execute.test.ts` also occur at
the merge base.

## What Changed

- Bound `runtime.ensureSession()` with a startup deadline and a duplex
transport loss check.
- Added terminal error codes for handshake timeout and transport loss.
- Fenced late session resolution and rejection so the settled run has
one owner.
- Suppressed sandbox-controlled diagnostic values on the guard-failure
and late-close paths.
- Added regression tests for timeout, transport loss, late resolution,
and late close rejection.
- Documented the startup live-path contract.

## Verification

- `pnpm --filter @paperclipai/adapter-utils exec tsc --noEmit` exits 0.
- The engine test suite runs from the repository root.
- The new regression cases pass.
- The three known failures remain the only failures and also fail at the
merge base. The board approved this pre-existing test exception.
- Cold start and session resume cases pass.
- All required GitHub checks pass.
- Greptile reports 5/5 with no open P2 findings, recommendations, or
follow-ups.

## Risks

The startup guard changes only the ACP startup path. A slow but valid
startup can now end at the configured deadline. The fence closes a late
handle once and records fixed host-authored diagnostics.

## Model Used

OpenAI Codex, GPT-5, current model version, tool use and code execution,
with the full task context.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
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. Three pre-existing failures remain and
have an approved exception.
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-28 12:21:37 -07:00
Nicky LeachandPaperclip dc7a1a020a fix(adapter-utils): skip the remote session close when the duplex channel is already lost (#12394)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The adapter runtime settles each run through a duplex control
channel
> - A lost channel can leave the remote session-close call without a
usable peer
> - The call has no deadline, so run teardown can wait for the full
adapter timeout
> - This pull request skips that remote call after the runtime latches
channel loss
> - The benefit is faster run finalization while the local cleanup
effects remain

## Linked Issues or Issue Description

**What happened?**

The run teardown placed a remote session-close call over a duplex
control channel that the runtime had already latched as lost. The call
blocked until the adapter execution timeout released it.

**Expected behavior**

Run teardown should release the local warm handle and continue when the
duplex control channel has already failed.

**Steps to reproduce**

1. Start an adapter run with the duplex control channel.
2. Latch a channel-loss state before settlement.
3. Use a runtime whose close call never resolves.
4. Confirm that teardown returns without a remote close call.

**Paperclip version or commit**

Commit d966069a78.

**Deployment mode**

Built from source.

**Agent adapter(s) involved**

Not adapter-specific. The change applies to the shared adapter runtime.

**Database mode**

Not database-related.

**Additional context**

Pull request #12373 used a larger approach for the same failure. The
board closed that pull request. This pull request contains the smaller
change.

## What Changed

- Add the required readonly `skipRemoteClose` field to the runtime
settlement plan.
- Set the field from the latched channel-loss state on the turn-finalize
plan.
- Set the field to `false` on every other settlement plan.
- Release the warm handle locally before the `end_session` step returns
without the remote call.
- Add a test that drives the lost-channel path through the settlement
sequence.

## Verification

- `./node_modules/.bin/tsc --noEmit -p packages/adapter-utils`
- `./node_modules/.bin/vitest run
packages/adapter-utils/src/acpx-engine/execute.test.ts` passes the new
test. Three existing tests fail on the merge base: two
session-fingerprint tests and one workspace-hints test.
- `./node_modules/.bin/vitest run
packages/adapter-utils/src/acpx-engine/run-fault-matrix.test.ts` reports
20 passed.
- Full CI will run on this pull request.

## Risks

The skipped remote close also skips the vendored runtime caller for
`closeBackendSession`. The run can keep a retained client after duplex
loss. A separate follow-up owns that residual. The environment lease
still releases in the teardown `finally` block.

## Model Used

OpenAI Codex, GPT-5, with tool use and code review assistance.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-27 22:08:08 -07:00
Nicky LeachandPaperclip 198fc8b281 fix(adapter-utils): harden the referenced-project ignore scan (#12214)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters stage referenced projects into controlled sandboxes
> - The ignore scan must preserve exact Git path bytes and fail closed
on unsafe input
> - Unbounded ignored-path data and raw diagnostics can harm resource
use or expose host details
> - This pull request adds exact path parsing, input bounds, fixed
failure categories, and saturation-only retry
> - The benefit is safer and more predictable referenced-project staging

## Linked Issues or Issue Description

**What happened?**

The referenced-project ignore scan trimmed NUL-delimited Git paths. It
also accepted a large ignored-path set and exposed raw failure details
through staging errors and warnings.

**Expected behavior**

The scan must preserve leading and trailing whitespace in Git paths. It
must reject oversized ignored-path data and expose only fixed failure
categories.

**Steps to reproduce**

1. Run the referenced-project ignore scan with paths that start or end
with whitespace.
2. Provide more than 10,000 ignored entries or more than 2 MiB of path
bytes.
3. Trigger a scan failure and inspect the reported reason.

**Paperclip version or commit**

d560bc2ae2

**Deployment mode**

Built from source.

**Installation method**

Built from source.

**Agent adapter(s) involved**

Not adapter-specific.

**Database mode**

Not database-related.

**Additional context**

This change covers the overlay diff, untracked, deleted, and ignored Git
paths. It also retries only typed scheduler saturation failures.

## What Changed

- Preserve all bytes in NUL-delimited Git path records.
- Bound ignored-entry count and total UTF-8 path bytes during parsing.
- Redact scan failure details to three fixed reason categories.
- Retry only the typed scheduler saturation error, with three total
attempts and 1 second then 2 second waits.
- Add tests for path whitespace, limits, diagnostics, retry behavior,
and scheduler code parity.

## Verification

- `npx tsc --noEmit` in `packages/adapter-utils` passed.
- `npx vitest run packages/adapter-utils` passed with 977 tests and 4
skipped.
- Continuous integration must run the server suite and the full
repository gates.

## Risks

The scan now rejects ignored-path data above fixed limits. Saturation
retries add up to 3 seconds before a final failure. The resolver still
fails closed for all other errors.

## Model Used

OpenAI GPT-5. The model used tool calls, code inspection, and command
execution. The exact context window and reasoning mode are not exposed
by the runtime.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-26 08:30:42 -07:00
DottaandPaperclip a9d0927fe8 fix(adapters): restore Paperclip skill for legacy runners (#12225)
<!-- 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.
> - Legacy local adapters run agents that use the Paperclip skill for
the control-plane workflow.
> - PR #7029 removed the required-skill fallback and made runtime skill
selection depend only on stored preferences.
> - No migration or runtime fallback replaced that behavior for existing
agents or non-CEO agents.
> - PR #12138 added core skills to new CEOs, and PR #12147 added Claude
skill discovery. These changes did not mount the operational skill for
all legacy agents.
> - This pull request makes the operational skill a legacy adapter
runtime invariant. It keeps all other skills configurable.
> - The native runner stays unchanged because its protocol supplies the
control-plane contract.
> - The benefit is that new and existing legacy agents can always
operate through Paperclip.

## Linked Issues or Issue Description

Refs #7029

Refs #12138

Refs #12147

**What happened?**

A skill-capable legacy local agent could start without
`paperclipai/paperclip/paperclip`. This happened when the agent had no
stored skill preference. An explicit empty preference also removed the
skill. The agent then reported that the Paperclip skill was not
available.

**Expected behavior**

Every skill-capable legacy local adapter must mount the Paperclip
operational skill when the runtime inventory contains it. Optional
skills must remain configurable. The native runner must keep its current
protocol-based behavior.

**Steps to reproduce**

1. Create a non-CEO `codex_local` agent without `paperclipSkillSync`
preferences.
2. Start a legacy heartbeat.
3. Inspect the managed `CODEX_HOME/skills` directory.
4. Observe that the Paperclip skill is absent before this change.

**Paperclip version or commit**

The problem reproduces on `master` before this pull request. PR #7029
introduced the configured-only selection behavior.

**Deployment mode**

Local development and self-hosted legacy local adapters.

## What Changed

- Added a shared legacy skill resolver that always selects the canonical
Paperclip operational skill when it is available.
- Applied the resolver to direct adapter execution, ACPX execution,
skill snapshots, and persistent skill sync.
- Added Hermes skill materialization at sync and run boundaries.
- Aligned Cursor, Gemini, and OpenCode execution-time injection with the
configured child `HOME`.
- Made Hermes stop execution when another installation blocks the
required operational skill.
- Kept optional skills controlled by `paperclipSkillSync.desiredSkills`.
- Kept `paperclip_runner` on the configurable-only resolver.
- Added regression coverage for missing preferences, empty preferences,
each skill-capable legacy adapter, ACPX, Hermes, and native runner
isolation.
- Documented the legacy runtime invariant.

## Verification

- `pnpm -r typecheck` passed on the pushed commit.
- `pnpm build` passed on the pushed commit.
- The adapter utility regression suites passed: 236 tests.
- The changed server adapter suites passed: 48 tests across 12 files.
- The OpenCode adapter suite passed: 8 tests.
- The Hermes adapter suite passed: 7 tests.
- `git diff --check` passed.
- `pnpm test:run` is not clean on this macOS host. The command reported
failures in unchanged workspace and filesystem suites. An isolated rerun
of `company-skills.test.ts` and `company-skills-service.test.ts`
reproduced 11 failures because macOS resolved `/var/...` paths as
`/private/var/...`. The changed adapter suites pass independently.

## Risks

- This change deliberately makes the operational skill non-removable for
skill-capable legacy local adapters.
- Existing agents receive the skill on their next list, sync, or run
boundary. No database migration is required.
- The resolver does not create a skill when the runtime inventory does
not contain the canonical entry.
- Hermes aborts a run if another installation occupies the required
operational skill target.
- Hermes removes only an undesired Paperclip-owned symlink that still
points to the known Paperclip source.
- The native runner does not receive the legacy default.

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

## Model Used

OpenAI Codex based on GPT-5. The exact serving model ID and context
window were not exposed. The agent used reasoning, tool use, and code
execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-26 09:45:24 -05:00
Nicky LeachandPaperclip 822e0aed93 fix(adapter-utils): move the workspace-restore merge lock to an instance-scoped root and surface restore failures on the run (#12187)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters restore sandbox work into project workspaces after a
run
> - The restore lock used the target workspace parent, which can reject
writes
> - The teardown then hid restore errors, so a run could report success
with lost work
> - This pull request moves the lock into an instance-scoped root and
reports safe restore failure codes
> - The benefit is reliable restore coordination and visible failure
evidence without changing run success semantics

## Linked Issues or Issue Description

Refs: #10914

## What Changed

- Move the workspace-restore merge lock into a private, instance-scoped
root.
- Derive the lock key from the canonical target path with SHA-256.
- Resolve the lock root from the caller environment and reject unsafe
root types.
- Classify restore failures with three allowlisted codes.
- Add the failure code to run result JSON without exposing a host path
or process identifier.
- Keep restore failure fail-open for the run exit code and run status.

## Verification

- Run `npx vitest run
packages/adapter-utils/src/workspace-restore-merge.test.ts`.
- Run `npx vitest run
packages/adapter-utils/src/acpx-engine/run-fault-matrix.test.ts`.
- Run the four Codex credential suites.
- Confirm the branch includes the current `master` commit and no manual
lockfile edit.
- Confirm all pull request checks and the Greptile review reach a
terminal green state.

## Risks

- The lock path changes for workspace restore and removes the
sibling-directory fallback.
- A misconfigured or inaccessible instance home can still stop lock
setup.
- Restore remains fail-open, so callers must inspect the result evidence
when a restore fails.

## Model Used

OpenAI GPT-5. The model used tool calls and code execution to validate
and route an author-provided change. The implementing engineer authored
the code.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-25 14:32:14 -07:00
Nicky LeachandPaperclip 6880213de5 fix(adapter-utils): honor .gitignore for referenced-project staging (#12184)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Sandbox adapters stage project files before an agent starts.
> - Referenced projects ignored Git-ignored paths and copied large local
directories.
> - This behavior increased staging time and disk use, and it differed
from anchor workspaces.
> - This pull request resolves Git-ignored paths once and shares that
result across all referenced-project consumers.
> - The benefit is smaller, faster, and consistent project staging.

## Linked Issues or Issue Description

No public GitHub issue exists for this bug.

**What happened?**
Referenced-project staging copied Git-ignored paths, except for a fixed
list of heavy directory names. A large repository therefore used much
more time and disk space than the same repository in an anchor
workspace.

**Expected behavior**
Referenced-project staging should exclude the same Git-ignored paths
that the workspace staging path excludes.

**Steps to reproduce**
1. Create a referenced project with a large Git-ignored directory.
2. Start a sandbox or SSH run that stages the referenced project.
3. Observe that the ignored directory enters the staged content.

**Paperclip version or commit**
Commit `9964b034bbff24e700c8eccf5a8b1fc3daa44bf2`.

**Deployment mode**
Built from source.

## What Changed

- Resolve each referenced project's Git-ignored paths once before
staging.
- Carry the resolved paths as a required field on
`SandboxAdditionalSource`.
- Reuse the resolved paths in sandbox staging, SSH staging, and
content-signature code.
- Harden the read-only Git helper with a bounded process, a reduced
environment, and disabled system and global configuration.
- Fail closed on Git errors, timeouts, and invalid path relations.
- Escape tar glob metacharacters in ignore-derived exclude entries.
- Add and update unit tests for the resolver and its three consumers.

## Verification

- `pnpm vitest run --config packages/adapter-utils/vitest.config.ts`
passes 266 tests locally.
- `pnpm exec tsc --noEmit -p packages/adapter-utils/tsconfig.json`
passes locally.
- CI must pass on this pull request.
- Greptile must report 5/5 with no unresolved comments before merge.

## Risks

- A Git error or timeout now prevents staging for the affected
referenced project.
- The resolver uses a bounded read-only Git process and fails closed by
design.
- The change stays inside `packages/adapter-utils` and does not change
the database schema.

## Model Used

Claude Sonnet 5 (Anthropic) assisted the implementation with code
execution and tool use. The exact context window and reasoning mode are
not recorded.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-25 14:22:47 -07:00
Nicky LeachandPaperclip 2862e18484 refactor(adapter-utils): remove the retired duplex_v1 sandbox bridge transport (#12171)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The adapter utilities provide sandbox transport paths for agent
execution
> - The retired `duplex_v1` path remains in host, gateway, and test code
after `http2_v1` replaced it
> - Retired transport code adds maintenance cost and leaves an unsafe
fallback for unknown gateway modes
> - This pull request removes the retired path, moves shared `http2_v1`
contracts to a leaf module, and closes mode dispatch to a fixed
allowlist
> - The benefit is a smaller transport surface and explicit failure for
unsupported modes

## Linked Issues or Issue Description

Refs #12120

The `http2_v1` transport replaced `duplex_v1`, but the retired broker,
gateway, constants, and tests remain in the adapter utilities. An
unknown bridge mode can also fall through to the queue gateway when a
queue directory exists. This change removes the retired code and rejects
unsupported modes before gateway selection.

## What Changed

- Delete the host `duplex_v1` broker and its transport-only tests.
- Delete the in-sandbox duplex gateway and retired mode constants.
- Move shared `http2_v1` symbols into `bridge-transport-contract.ts`.
- Update the remaining importers and repair their focused tests.
- Validate bridge modes against `http2_v1` and `queue_v1` before queue
lookup.
- Keep `queue_v1`, `duplex-frame-codec.ts`, and duplex telemetry
dimensions unchanged.

## Verification

- [x] `npx tsc --noEmit -p packages/adapter-utils` passes.
- [x] `npx vitest run packages/adapter-utils/src` passes: 48 files and
968 tests pass, with 4 pre-existing platform skips.
- [x] Full CI is green on this pull request.
- [x] Greptile review is complete and every finding is resolved.

## Risks

The change removes an internal transport that no host path selects. The
main risk is an overlooked import or test dependency. Targeted typecheck
and tests cover the adapter utility package. Full CI must confirm
workspace-wide compatibility.

## Model Used

Anthropic Claude Sonnet 5 assisted with the implementation, as recorded
in the commit. The commit does not record a context-window size or
reasoning mode.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-25 08:47:43 -07:00
Nicky LeachandPaperclip 16b59c9315 feat(adapter-utils): stream duplex bridge bodies as sequenced chunks with receive-side spill (#12006)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent adapters use a duplex bridge to send requests and responses
across an isolated boundary
> - The bridge held each request body and response body in memory on
both ends
> - Large bodies can exhaust memory and reduce the safe size of adapter
traffic
> - This pull request sends receive-side bodies as sequenced chunks and
spills large bodies to disk
> - The benefit is bounded memory use with strict size, order, and
cleanup checks

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The adapter-utils duplex bridge transports request and response bodies
across the sandbox boundary.

**Current behavior**

The bridge stores each complete body in memory on both ends of the
duplex channel.

**Proposed behavior**

The bridge sends body chunks with sequence checks. The receive side
keeps bodies up to 1 MiB in memory and spills larger bodies to a
temporary file.

**Reason and benefit**

This change reduces memory pressure and keeps malformed or oversized
input on a terminal error path.

**Breaking changes**

The duplex frame version changes to version 2. The request and response
envelopes now carry bodyByteCount, and body_chunk frames carry the body
data.

## What Changed

- Add version 2 body_chunk frames with 256 KiB raw slices encoded as
canonical base64 text.
- Add receive-side memory and spill reassembly with per-channel disk and
file limits.
- Reject malformed, reordered, oversized, truncated, and non-canonical
body chunks.
- Stream reassembled request bodies to the host forward handler with a
web stream and half-duplex request.
- Remove spill files on success, failure, channel death, and startup
cleanup.

## Verification

- Run the adapter-utils type-check.
- Run the adapter-utils duplex test suite.
- Run all pull request checks.
- Run the Greptile review and confirm a 5/5 score with no open findings.

## Risks

The wire format changes from version 1 to version 2. Older bridge peers
cannot use this protocol. The receive path adds temporary file
operations and cleanup paths. The implementation fails closed when a
body violates size or sequence rules.

## Model Used

OpenAI GPT-5 Codex, tool-enabled coding agent. The exact context-window
size and reasoning mode are not exposed by the runtime.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-23 08:52:31 -07:00
Nicky LeachandPaperclip cc42a67e7e fix(adapter-utils): extend the duplex fail-closed run disposition to the CLI lane (#11966)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip runs agents through adapter execution lanes
> - Duplex adapters can lose their control channel before a process
completes
> - The ACP lane already fails closed, but the CLI lane can report false
success
> - This pull request applies the same completion rule to the CLI lane
and shares the loss code
> - The benefit is consistent failure reporting when a duplex channel
closes during a run

## Linked Issues or Issue Description

**What happened?**

A CLI-lane duplex run can lose its control channel before clean process
completion. The run can then report `succeeded` with exit code 0 and no
error code.

**Expected behavior**

The execution target must fail closed when the channel dies before clean
completion. It must return exit code 1, the typed `duplex_channel_lost`
error code, and a short stderr note.

**Steps to reproduce**

1. Start a duplex adapter run through the CLI execution lane.
2. Close the duplex control channel before the process completes
cleanly.
3. Inspect the run result and error code.

**Paperclip version or commit**

Commit `5e01523d4eb6df4a20a0bddd05374c9c42225203`.

**Deployment mode**

Built from source.

**Installation method**

Built from source with pnpm.

**Agent adapter(s) involved**

Claude Code, Codex, Cursor, Gemini, Kimi, OpenCode, and Pi local
adapters.

**Database mode**

Not database-related.

## What Changed

- Add an optional `errorCode` field to `RunProcessResult`.
- Add a one-read completion seam to the execution target process
options.
- Fail closed when a duplex channel dies before clean process
completion.
- Add `settleRunDisposition()` to atomically read and mark orderly
completion.
- Share the typed duplex loss error code across the ACP and CLI lanes.
- Mark non-success terminal results as orderly completion before
teardown.
- Wire the seam through the seven duplex adapters.
- Add regression tests for channel loss, clean completion, and non-clean
terminal results.

## Verification

- `npx vitest run
packages/adapter-utils/src/execution-target-sandbox.test.ts` — 118
passed.
- `npx vitest run packages/adapter-utils/src/acpx-engine/execute.test.ts
-t "sandbox duplex run-disposition seam"` — 4 passed.
- The author confirmed a clean type-check for
`@paperclipai/adapter-utils` and the seven duplex adapter packages.
- Pre-existing environment failures remain outside this change. They
include `EACCES mkdir '/srv/paperclip'` and remote file-size setup
failures.

## Risks

The change alters terminal status for CLI duplex runs that lose control
before clean completion. The typed error code and stderr note keep the
failure visible. The broker marks failed, cancelled, and timed-out
results as orderly completion to prevent false loss events during
teardown.

## Model Used

OpenAI Codex, GPT-5, tool use and code execution, with the standard
GPT-5 context window. The model assisted with the implementation and
test work.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-22 11:12:51 -07:00
Nicky LeachandPaperclip 10d2781a29 feat(sandbox): add the duplex bridge broker, gated transport selection, and fixed observability (#11769)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Sandbox adapters provide controlled execution for untrusted provider
environments.
> - The sandbox channel needs one persistent duplex transport with
strict host control.
> - The transport must remain off unless the instance setting and
provider capability both allow it.
> - The host must detect loss, bound resource use, and expose only safe
telemetry.
> - This pull request adds the broker, gated selection, kill-switch
wiring, fixed observability, and real-process proof.
> - The benefit is safer sandbox execution with bounded failure behavior
and inspectable transport results.

## Linked Issues or Issue Description

No public issue exists for this change. The related pull requests are
#11738 and #11750.

**Problem or motivation**

The sandbox duplex channel needs a host-controlled broker, strict
transport gates, bounded provider input, and safe loss telemetry.
Without these controls, a provider can cause replay, resource growth,
unsafe endpoint selection, or data exposure through telemetry.

**Proposed solution**

Add a host broker with nested time limits, request limits, one-shot
loss, and per-id deduplication. Select duplex transport only when the
instance setting and provider capability both equal true. Assign the
endpoint and nonce on the host. Reject invalid readiness data and use
the file bridge on failure. Add fixed redacted telemetry and a
real-process end-to-end test harness.

**Alternatives considered**

Keep the file bridge as the only transport. This avoids new channel
behavior but does not provide persistent duplex operation for supported
sandbox providers.

**Roadmap alignment**

This change supports the Cloud / Sandbox agents section in ROADMAP.md.

## What Changed

- Add the duplex bridge broker with bounded forward, response, and
gateway wait budgets.
- Bound concurrent requests, lifetime requests, and request-id bytes
before retention or forwarding.
- Select duplex transport only when both required gates are true.
- Assign the loopback port and nonce on the host and enforce a
liveness-only READY frame.
- Fall back to the file bridge after invalid readiness, contamination,
bind failure, or timeout.
- Carry the kill switch through the server, acpx engine, and six local
adapters.
- Add fixed, redacted duplex telemetry with a provider allowlist.
- Add a real-process end-to-end harness for readiness, round trips,
loss, and teardown.
- Add regression coverage for limits, loss, UTF-8 splits, concurrency,
and telemetry dimensions.

## Verification

- Adapter-utils, server, and Daytona typechecks pass locally.
- Adapter-utils tests pass, including the codec, broker,
execution-target sandbox, and real-process harness.
- Server kill-switch tests pass.
- Live Daytona tests pass with the required provider key and skip
without that key.
- The root pnpm-lock.yaml file has no diff.
- The branch contains ten commits after origin/master.

## Risks

- Duplex transport remains disabled unless both gates equal true.
- A provider remains an untrusted boundary and needs least-privilege
credentials and quotas.
- The server telemetry recorder stays deferred; the default recorder
does nothing.
- A provider that pre-binds the host port causes a fail-closed fallback
to the file bridge.
- The change adds no database migration and changes no root lockfile.

## Model Used

OpenAI GPT-5, exact model family GPT-5, large context window, reasoning,
and tool use. The model assisted with Git handoff validation and PR
preparation. The implementation commits came from the engineering
worktree.

## 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/... or 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
- [x] I searched the GitHub PR list for similar PRs and confirmed this
is not a duplicate

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-22 09:01:31 -07:00
nearfolk c2cfd55e97 fix: exclude thought text from automatic issue comments (#11801)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The heartbeat system records agent runs and can add a run summary to
an issue.
> - The ACPX engine receives output text and internal thought text as
separate streams.
> - The default summary strategy joined both streams and could publish
internal text in an issue comment.
> - Paperclip already has final-output segmentation for run summaries.
> - This pull request makes final-output-only summaries mandatory and
removes the configuration bypass.
> - The benefit is that automatic issue comments contain the intended
final message instead of internal execution text.

## Linked Issues or Issue Description

Refs #11761

**What happened?**

The ACPX engine used the full summary strategy when an adapter did not
set `summaryStrategy`. That strategy joined all text deltas, including
thought-stream text and intermediate narration. The heartbeat finalizer
could then store that summary as an issue comment.

**Expected behavior**

An automatic issue comment must use only the final output segment.
Configuration must not allow thought-stream text or intermediate
narration into that summary.

**Steps to reproduce**

1. Run an ACPX adapter without a configured `summaryStrategy`.
2. Emit an output delta, a thought delta, a tool call, and a final
output delta.
3. Read the generated run summary.
4. Observe that the old default included all text deltas.

**Paperclip version or commit**

`54b8bec44417511c623999613f9f1006f8af0517`

**Deployment mode**

Built from source with a local ACPX adapter.

## What Changed

- Limit ACPX run summaries to the final non-empty output segment.
- Ignore the legacy full-summary setting so configuration cannot bypass
containment.
- Update regression tests for the safe default and an attempted unsafe
override.

## Verification

- Observed the new guard fail before the implementation change because
the summary contained thought text.
- Ran `pnpm exec vitest run
packages/adapter-utils/src/acpx-engine/execute.test.ts -t "defaults run
summaries to the final output segment without thought text|does not
allow configuration to include thought text in run summaries"`. Result:
2 passed.
- Ran `pnpm exec vitest run
packages/adapter-utils/src/acpx-engine/execute.test.ts`. Result: 130
passed.
- Ran `pnpm --filter @paperclipai/adapter-utils typecheck`. Result:
passed.

## Risks

- Run summaries are shorter for adapters that relied on full text
aggregation.
- The old `summaryStrategy: "full"` setting no longer changes summary
behavior. This is an intentional containment change.
- The change does not alter run logs or tool events. It changes only the
summary selected for downstream use.

> This is a focused security and privacy bug fix. It does not add
roadmap scope.

## Model Used

- OpenAI Codex on the GPT-5 family. The runtime did not expose the exact
model ID or context-window size. Reasoning, tool use, terminal
execution, and code editing were enabled.

## Checklist

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