Commit Graph
175 Commits
Author SHA1 Message Date
DottaandPaperclip 87a7312cfd refactor(server): extract heartbeat run-log formatting (#15573)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Heartbeat orchestration records agent output and run events.
> - The heartbeat service still contains more than 30,000 lines after
the first extraction.
> - Log formatting has fixed limits and does not write run state.
> - These helpers form a small next step toward a more manageable
heartbeat service.
> - This PR moves them into the heartbeat folder without changing their
function bodies.
> - Direct boundary tests and existing caller tests check the output.

## Linked Issues or Issue Description

Refs: #15568.

**What existing behavior does this improve?**

This improves the structure and test coverage of heartbeat run-log
formatting.

**Subsystem affected**

server/ — orchestration services.

**Current behavior**

`heartbeat.ts` contains excerpt handling, payload size limits, and log
chunk formatting beside run orchestration.

**Proposed behavior**

Move these helpers and their constants into
`server/src/services/heartbeat/run-log.ts`.
Keep the same function bodies, output, limits, and public exports.

**Reason and benefit**

Run-log formatting has its own small module and focused tests.
This keeps the second extraction small enough to review on its own.

**Breaking changes**

None. The existing public import path and persisted output stay the
same.

Related run-log PRs: Refs: #6373, Refs: #8841. Those PRs change
redaction behavior. This PR only moves existing formatting code.

## What Changed

- Move 109 lines of helper functions and six constants into
`heartbeat/run-log.ts`.
- Move `appendExcerpt` and retain the existing public exports for
`boundHeartbeatRunEventPayloadForStorage` and `compactRunLogChunk` in
`heartbeat.ts`.
- Add 17 direct regression cases for size and depth limits, cycles,
shared references, immutable input, image omission, redaction order,
excerpt tails, and UTF-8 boundaries.
- Document both heartbeat extractions in `doc/DEVELOPING.md`.

## Verification

- Before extraction, four focused files passed with 55 tests.
- After extraction and the two new excerpt tests, the same four files
passed with 57 tests.
- Run `pnpm exec vitest run
server/src/services/heartbeat/run-log.test.ts
server/src/__tests__/heartbeat-run-log.test.ts
server/src/__tests__/heartbeat-list.test.ts
server/src/__tests__/redaction.test.ts`.
- The original and extracted function blocks match byte for byte after
adding the export keyword to `appendExcerpt`.
- Existing tests still import the public helpers from `heartbeat.ts`.
- `node scripts/check-module-boundaries.mjs` and `git diff --check`
passed.
- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- The full suite passed in CI. The duplicate local `pnpm test:run` was
stopped after CI passed; it did not complete locally.
- All CI gates passed on commit
`4e65c666e3b5b46162b3a528b37fba8902a1d200`: 54 passing checks, two
skipped Storybook checks.
- Fresh Greptile review of the same commit: 5/5, no actionable or inline
findings. The PR has no merge conflicts.

## Risks

- Low risk. Moving code can cause an import or build error.
- The same redaction and adapter utility modules remain in use.
- Database writes, current-user redaction, live event delivery, and run
state remain in `heartbeat.ts`.
- The event schema and payload output do not change.
- No database, API, Telemetry, Observability, or UI contract changes are
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. The exact serving model ID and context window
were not exposed in this session. Used reasoning, repository inspection,
shell tools, and code execution.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-08 09:34:37 -05:00
DottaandPaperclip 51653becc2 refactor(server): extract heartbeat task markdown rendering (#15568)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Heartbeat orchestration supplies each run with task context.
> - The task Markdown renderer is inside a service with more than 31,000
lines.
> - The renderer formats task data and does not write run state.
> - It is a small first step toward a more manageable heartbeat service.
> - This PR moves the renderer without changing its function body or
public export.
> - Direct tests and existing caller tests check the output before and
after the move.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

This improves the structure and test coverage of heartbeat task context
rendering.

**Subsystem affected**

server/ — orchestration services.

**Current behavior**

`buildPaperclipTaskMarkdown` occupies 352 lines inside `heartbeat.ts`.
The service also owns run execution, scheduling, recovery, and
cancellation.

**Proposed behavior**

Move the renderer to `heartbeat/task-markdown.ts`.
Keep its function body and the existing `heartbeat.ts` export unchanged.
Leave orchestration in place for this first PR.

**Reason and benefit**

Prompt formatting has its own small source file and direct regression
tests.
Reviewers can check this one extraction before a later refactor.

**Breaking changes**

None. The input type, rendered output, and existing import path stay the
same.

Related renderer changes: Refs: #4732, Refs: #14030.
These PRs change prompt behavior. This PR only moves the current
renderer.

## What Changed

- Move the 352-line renderer to
`server/src/services/heartbeat/task-markdown.ts`.
- Import and re-export it from `heartbeat.ts`. Remove imports used only
by the renderer.
- Add seven direct regression cases. Cover empty context, ordered
comment-only wakes, input preservation, nested code fences, ancestor
limits, attachment-only wakes, and rejected plans.
- Keep the renderer and its direct tests in
`server/src/services/heartbeat/`. Document this folder as the home for
relevant later extractions in `doc/DEVELOPING.md`.

## Verification

- The focused suite passed before and after extraction, and after moving
to the heartbeat folder: four files, 85 tests.
- Run `pnpm exec vitest run
server/src/services/heartbeat/task-markdown.test.ts
server/src/__tests__/heartbeat-context-summary.test.ts
server/src/__tests__/heartbeat-chat-task-link.test.ts
server/src/__tests__/codex-local-execute.test.ts`.
- The extracted function matches the original function byte for byte.
The folder move only adjusts imports.
- `node scripts/check-module-boundaries.mjs` passed.
- `git diff --check` passed.
- The initial extraction passed local `pnpm -r typecheck` and `pnpm
build`.
- The folder update passed `pnpm --filter @paperclipai/server exec tsc
--noEmit` and `pnpm --filter @paperclipai/server build`.
- The initial extraction passed the full CI suite. Its duplicate local
`pnpm test:run` was stopped after CI passed; it did not complete
locally.
- The folder update passed all CI gates on commit
`e21e589b379d7ca2fae16c1dcd91cf2f604fd03f`: 54 passing checks, two
skipped Storybook checks. Three test shards passed after one retry
following simultaneous runner shutdowns; those failures had no failed
test assertions.
- Fresh Greptile review of commit
`e21e589b379d7ca2fae16c1dcd91cf2f604fd03f`: 5/5, no actionable or inline
findings.

## Risks

- Low risk. A moved module can change import resolution or expose an
import cycle.
- Existing caller tests still load the compatibility export from
`heartbeat.ts`.
- The same guidance constants and public task URL resolver remain in
use.
- No run-state writes, transactions, locks, shared process state, or
cleanup paths moved.
- No database, API, telemetry, or UI contracts changed.

> 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. The exact serving model ID and context window
were not exposed in this session. Used reasoning, repository inspection,
shell tools, and code execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-08 09:06:04 -05:00
DottaandPaperclip d66acb7ac1 feat: automate Slack bot app setup and installation (#15413)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat connectors give each agent a customer-owned bot and task-backed
conversations.
> - Manual Slack setup requires app creation and copying durable
credentials.
> - Operators need a shorter setup that an assisting agent can use
safely.
> - This pull request creates the app through Slack's Manifest API and
installs it through OAuth.
> - Durable registration state supports recovery without creating
another app.
> - A four-screen wizard, automatic avatar upload, and OAuth account
linking reduce setup work.
> - Connector settings and per-turn tool guidance support daily use
after installation.

## Linked Issues or Issue Description

**Subsystem affected**

Native Slack bot setup, company secret storage, chat connector
management, and agent tool guidance.

**Problem or motivation**

New Slack bots require manual app creation and copying a signing secret
and bot token. Interrupted setup can create duplicate apps. The setup
and management screens contain unnecessary controls. Agents also need
guidance for native questions, files, thread replies, and governed Slack
actions.

**Proposed solution**

Use a temporary app-configuration access token to create a
customer-owned app. Save durable secrets in the vault. Bind OAuth to the
initiating actor, company, endpoint, registration revision, scopes, and
configured origins. Preserve manual and existing-app recovery. Link the
installing user's account, send a welcome DM, and advance from saved
server evidence. Keep request-URL recovery instructions available if
automatic connection detection waits.

**Alternatives considered**

The Slack CLI adds installation requirements. Socket Mode changes
transport. A shared Paperclip-owned app changes app ownership. These
alternatives are outside this change.

**Roadmap alignment**

This extends existing chat connectors and secrets capabilities. Related
public work: #14037 and #13954 cover Slack MCP prerequisites and user
OAuth. No duplicate bot-registration PR was found.

## What Changed

- Share one reviewed manifest builder between automatic registration and
manual setup.
- Add replay-safe migration 0318 and company-bound registration state
with vault references and uncertain-creation recovery.
- Add registration, installation, callback, and resume APIs with
short-lived, single-use OAuth state.
- Save installation credentials before downstream checks and preserve
bot identity constraints.
- Reduce automatic setup to four screens. Keep advanced app details,
manual recovery, and existing-app setup.
- Upload the agent avatar with the Paperclip dark background. Link the
OAuth installer's account and send setup DMs.
- Show agent and connector-owner avatars. Simplify settings, access, and
conversation screens.
- Discover joined Slack channels and enable them by default. Start a
task from a bare mention and admit same-thread follow-ups.
- Refresh Slack tool guidance each turn. Add native-form, file,
approval, and delivery regressions plus manual model probe definitions
and sanitized acceptance records.
- Update deployment/database docs, OpenAPI, redaction, removal cleanup,
production Storybook stories, and provider browser tests.
- Merge current master and move the registration migration after its
latest migration without rewriting published commits.

The completed Slack success view intentionally has a single centered
**Done** action and no **Save & exit**, as explicitly requested by the
product owner. `DESIGN.md` records this exception; unfinished setup
steps retain the aligned wizard footer.

## Verification

- Passed after the master merge: repository typecheck, full build,
Storybook build, design-token gates, module-boundary gates, and
migration generation.
- Passed: all 352 focused Slack deterministic tests and all 14 affected
provider browser tests. Browser tests use controlled provider fixtures
and a separate throwaway instance.
- Passed on current head `c5d01e0e2`: the complete GitHub test matrix
(general server, chat, all workspaces, serialized server, and Runner),
all eight browser shards, typecheck/release registry, build, canary dry
run, security checks, and policy gates. There are 52 passing checks and
no pending or failing checks.
- Greptile completed on the exact current head with 5/5 and no
actionable findings or open review threads.
- Local repair verification passed 93 focused tests, including same-app
reinstall after revocation and rejection of consent started before
revocation, the AgentMail browser journey, and repository typecheck.
Local build and Storybook build also passed. The redundant local
full-suite rerun was stopped after the complete current-head CI matrix
passed.
- Real Slack setup and agent replies were exercised in the authorized
isolated test drive during the setup iteration.
- The ten additional model probes were attempted with legacy
`codex_local`, `gpt-5.6-sol`: five passed, two failed, and three were
partly verified. Native runtime is not qualified. See
`server/src/services/connectors/slack/evals/2026-10-08-acceptance.md`
for evidence and limits.
- Passing model probes cover native forms, downloaded file bytes, bare
mentions with thread replies, explicit posts/reactions, and saved
approval denial.
- The controlled uncertain-write probe found wrong delivery-check IDs.
The canvas fallback attempt used an invented tool name. Search
pagination/native search, a private-source denied-tool receipt, and
distinct board/webhook origins remain unqualified.

Reviewer path: enable Chat connectors, start Slack chat setup, select an
agent, enter an app-configuration access token, and approve Slack
installation. Send a message to the bot and confirm that setup advances
to success. Inspect settings and allowed channels. See
`doc/connections/SLACK-AUTOMATIC-SETUP.md` for deployment and recovery.

## Risks

- Slack app creation has no provider idempotency guarantee. A timeout
after dispatch stays uncertain until the operator checks Slack.
- OAuth needs a stable public HTTPS board origin. Webhook ingress may
use a separate configured HTTPS origin. Workspace policy can delay
installation.
- Migration 0318 can replay safely on instances that applied the earlier
development migration.
- OAuth installation now links the installer to the initiating Paperclip
user. Identity checks and company access rules still apply.
- Joined channels now enable bot responses by default. Linked-user
authorization and per-action approval rules still apply.
- Model behavior has the documented delivery-check and canvas fallback
failures. A passing CI run does not establish that every model probe
passed.
- Removing the connection does not delete the customer's Slack app. No
new first-party telemetry is added.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution, and browser verification. The runtime does not expose a more
specific authoring model ID or context-window size. The live bot probes
used OpenAI `gpt-5.6-sol` through `codex_local` in legacy 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-10-08 06:33:31 -05:00
DottaandPaperclip d0f69670db fix(runner): recover saved execution prompts after upgrades (#15518)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runs save an immutable execution context for restart
recovery.
> - The context includes the prompt text, revision, and content hashes.
> - The parser required that saved prompt to match the current release.
> - A server upgrade could reject a valid saved run before provider
recovery.
> - This pull request validates and preserves the saved prompt snapshot.
> - Routine prompt changes no longer need a catalog of past strings.

## Linked Issues or Issue Description

**What happened?**

A hot restart selected a dead native runner for same-run recovery.
Reading its saved v5 execution input failed with
`input.runtimeContext.prompt must match the fixed Paperclip prompt
revision`. The new controller accepted only v6.

**Expected behavior**

Recovery uses the saved prompt and validates its content hashes. It
preserves the same run and provider session without starting a duplicate
turn.

**Steps to reproduce**

1. Start a native run and save its execution input and provider
checkpoint.
2. Change the fixed execution prompt in the server release.
3. Stop the runner and recover the saved run with the new controller.
4. Observe that the old parser rejects the saved prompt before provider
recovery.

**Paperclip version or commit**

The v5-to-v6 prompt change was introduced in #15446. The defect also
reproduces on current master before this fix.

**Deployment mode**

Source-built server with the native runner.

Related work: #15446 added task-monitor guidance. The held prompt-size
experiment in #15489 changes prompt wording but does not add recovery
compatibility.

## What Changed

- Read the prompt text and revision from the saved execution snapshot.
- Treat the revision as non-empty metadata and preserve the exact saved
bytes.
- Validate the prompt SHA-256 and the aggregate context digest.
- Keep fresh-run builders on the current prompt constants.
- Test arbitrary saved prompts, malformed fields, altered text, stale
hashes, and aggregate drift.
- Test recovery parsing for Codex input versions v3-v5 and OpenCode,
ACPX Pi, and Dot v6 inputs.
- Extend the real-process restart suite with both the incident's v5 wire
fixture and a prompt unknown to this release.
- Run the restart recovery suite in the existing Rust-equipped PR lane,
where its runner and fake-provider binaries are built. Verify complete,
non-overlapping test coverage for PR, release, and local callers.
- Document recovery from saved snapshots without a historical prompt
catalog.

## Verification

- Red: the new contract regressions fail against the catalog-based
parser with the original prompt-validation error.
- Green: 53 focused contract and materialization tests pass.
- Red: the real-process unknown-prompt regression fails with master's
original parser at the saved-input recovery read after process loss.
- Green: all 15 real-process restart tests pass locally on the final
branch. The saved-prompt cases keep the run and provider session,
replace the PID, and record one `turn/start`.
- Local repository `pnpm -r typecheck` and `pnpm build` passed after
rebase on `89f09dad723766e5351953f0731b9aa5daada28d`. The 53 focused
tests also passed on that head.
- Red: the new test-roster checks fail against the old CI placement.
- Green: all 26 test-scheduling checks pass after moving the restart
suite.
- CI ran all 15 restart recovery tests with no skips on final head
`6719fc2bb7a31a0f72ea04c7e525a63dcc6f9105`. [Runner test
job](https://github.com/paperclipai/paperclip/actions/runs/37764782334/job/113271464966).
- Greptile scored 5/5 on that exact head with no actionable findings.
- The complete CI matrix passed on final head
`6719fc2bb7a31a0f72ea04c7e525a63dcc6f9105`: general/workspace tests,
serialized server suites, both runner Vitest lanes, Rust and static
checks, all browser shards, typecheck, build, and the canary dry run.
[CI
run](https://github.com/paperclipai/paperclip/actions/runs/37764782334).
- There are no unresolved review threads or merge conflicts.
- Reproduce focused tests with `pnpm --filter
@paperclipai/paperclip-runner exec vitest run
src/contracts/runtime-context.test.ts
src/contracts/native-execution.test.ts
src/drivers/runtime-context-materializer.test.ts`.
- Reproduce restart tests with `pnpm --filter
@paperclipai/paperclip-runner build:rust` followed by `pnpm exec vitest
run
server/src/services/native-runtime/native-runner-restart-recovery.integration.test.ts`.
They use temporary PostgreSQL, real runner processes, and a fake Codex
provider. They do not use paid inference.

## Risks

- The parser now accepts internally consistent saved prompt text that is
absent from the current source. Inputs must come from trusted server
persistence. Content hashes verify consistency; they do not authenticate
authorship.
- Existing execution-schema, ownership, checkpoint, provider,
permission, and session-compatibility checks still apply.
- This change validates the saved base prompt. It does not make all
additional code-generated instruction strings versioned.
- The process-level recovery proof uses Codex. Other provider coverage
verifies the shared input parser and retained provider configuration.

## Model Used

OpenAI Codex, GPT-6 family, with repository inspection, code editing,
and test tools. 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-08 05:57:20 -05:00
DottaandPaperclip bf9dbd18a8 fix(runner): recover incompatible Codex models before launch (#15519)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Runner prepares and saves each task's provider configuration
before launch.
> - A sandbox image can have a supported Codex CLI that is too old for
the selected model.
> - The current version check stops that task even when the image can
run a similar model.
> - This pull request selects a compatible model before it saves a fresh
execution.
> - The task continues with a visible warning, and recovery uses the
saved effective model.

## Linked Issues or Issue Description

- Refs #15053. This fixes the same CLI and model mismatch for fresh
remote Runner tasks. It does not change subscription onboarding.
- Refs #14721. This adds a bounded startup choice for Codex CLI
compatibility. It does not add user-defined fallback chains or quota
failover.
- Related PR: #15399 added the model-specific CLI checks that this
change preserves at launch.

## What Changed

- Check the preinstalled remote Codex CLI before saving a fresh
execution that uses a model with a verified CLI minimum.
- Select the closest compatible older model in the same class, then the
stable Runner default. Consider each candidate once.
- Save the effective model before checkpoint selection. Keep the
requested agent and task settings unchanged.
- Add a task warning and a local `runner.model_fallback` run-log event
with both models and the CLI version.
- Share executable discovery with the launch verifier. Preserve explicit
artifact and install settings, saved executions, and existing artifact
checks.
- Add regression tests and document the selection and warning behavior.

## Verification

- Red: the three new provider-configuration regression cases failed
before the fix. They kept the incompatible requested model.
- Red: both rejected-probe cases failed before the review fix. They now
defer to launch verification.
- Green: targeted provider configuration, remote preflight, task
warning, and launch-verifier tests pass (680 tests).
- `pnpm -r typecheck` passes.
- [Full
CI](https://github.com/paperclipai/paperclip/actions/runs/37713759744)
passes on `eb273fc32661526d90a864b42c73a7da61dd62da`: 47 successful
jobs, including all general and serialized Vitest groups, browser
shards, Runner verification, typecheck, build, and the canary dry run.
- Local extended verification: three serialized shards pass (115
suites). HTTP route tests hit intermittent 15-second timeouts. The
authorization suite passes on rerun (130 tests). The document suite
passes on both master and the PR head in the same isolated setup (6
tests). The local general run was stopped after the equivalent full CI
matrix passed.
- `pnpm build` passes.
- Server typecheck and build pass again after the probe-error review
fix.
- `git diff --check` and `pnpm check:module-boundaries` pass.
- Example: request `gpt-6.1-sol` on Codex 0.158.0 to use `gpt-6-sol`; on
0.156.0, use `gpt-5.6-sol`. The warning names the requested model,
effective model, and CLI version.
- This PR has not been deployed to staging.

## Risks

- A fallback can have different capabilities. The task warning makes the
substitution visible. Later runs can use the requested model after the
image CLI is updated.
- Preparation adds two remote commands for models with a verified CLI
minimum. Failed or invalid version probes retain the existing launch
checks.
- This only handles known CLI and model mismatches before a fresh
provider launch. Authentication, capacity, and artifact failures keep
their existing behavior.
- No database migration is required.

## Model Used

OpenAI GPT-6 through Codex, with tool use and code execution. This
session does not expose the exact deployment model ID, context window
size, or reasoning setting.

## 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-08 04:57:26 -05:00
Devin FoleyandPaperclip 5717523b9e fix: retain the original repository for reused task workspaces (#15528)
Apply the reviewed change for fix: retain the original repository for reused task workspaces.

Validation: required local typecheck and tests, passing CI, Greptile 5/5, and independent review of the exact source head.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-07 19:52:30 -07:00
DottaandPaperclip dd777f4b73 feat(dot): complete onboarding and expand governed Runner capabilities (#15414)
## Thinking Path

> - Paperclip manages AI agents, their work, and their permissions.
> - Paperclip Runner supplies the same admitted tool authority to each
provider.
> - The Dot provider in #15402 needs reliable onboarding and useful
agent capabilities.
> - An idle Dot could not start work, assign a human, read skills, or
produce a workspace artifact.
> - Pairing also relied on a second configuration save before ordinary
admission could work.
> - This pull request adds governed idle admission and shared Runner
tools, and completes pairing atomically.
> - Operators can test Dot with fresh data while keeping normal company,
approval, budget, and run ownership checks.

## Linked Issues or Issue Description

**Subsystem affected**

Paperclip Runner, dedicated Dot MCP access, OAuth onboarding,
experimental settings, and empty worktree startup. This PR builds on
merged provider PR #15402. It reuses the merged MCP gateway from #14846
and assistant connection work from #14933 and #15380.

**Problem or motivation**

An idle Dot could see assignments but could not act on a conversation
request until someone created a task first. Its Runner catalog could not
assign tasks to humans or read pinned skills and workspace files.
First-time OAuth discovery and pairing also needed browser fixes, and a
completed pairing did not persist its binding reference on the agent.

**Proposed solution**

Keep Dot within the existing Runner. Admit a visible agent-authored
intake task for idle requests. Add people, human assignment, cross-task,
skill, and optional sandbox workspace tools through shared authority.
Relay assigned app calls through the configured MCP gateway. Add lease
renewal and follow-up references. Save pairing and its configuration
revision atomically. Show prerequisites and provide a complete copy
prompt.

**Roadmap alignment**

This extends the experimental provider in #15402. It uses the existing
governed gateway, task model, skills, artifact path, and native Runner.
It adds no separate execution subsystem.

## What Changed

- Add a standalone OpenAI Dot agent choice with an independent
experimental opt-in. It works with the general Runner option off.
Require Assistant connections (MCP), authenticated sign-in, and public
HTTPS for pairing.
- Use Dot’s own option for company package import. Allow an unpaired Dot
configuration to save after external billing acknowledgement; task
admission still requires pairing. Prepare the shared dev binary for
Dot-only opt-in.
- Label saved Dot agents as OpenAI Dot. Use prerequisite-check copy in
setup and runtime configuration.
- Route Dot creation directly to pairing after explicit external billing
acknowledgement. Hide local CLI, model, and harness setup for Dot.
Preserve the shared Runner implementation and canonical API type. Other
Runner providers still require their general opt-in.
- Add an empty worktree option with fresh signing keys and no production
data copy.
- Fix public-client OAuth negotiation, discovery compatibility, and
optional separate browser authorization origin.
- Add one-use pairing consent preview, clear copied setup instructions,
and atomic binding persistence and cleanup.
- Add idle request admission with stable request IDs and normal
scheduling, permissions, budgets, and task ownership.
- Add identity and people discovery, human task assignment and
reassignment, and authorized cross-task comments and documents.
- Read assigned skill files from pinned manifests. Relay assigned app
calls through the merged gateway without exposing credentials.
- Add an off-by-default workspace bridge. Constrain paths and writes.
Run commands in a deny-by-default OS sandbox with no network or injected
credentials. Reserve mutations before effects and never blindly repeat
uncertain work.
- Add rolling lease renewal, task pagination, bounded operation limits,
and deduplicated follow-up references without comment bodies in
webhooks.
- Add an off-by-default attachment reading setting. Restrict reads to
files on the current assigned task. Verify size and hash, cache bounded
verified copies per run, paginate text or binary bytes, and recheck live
authority before returning.
- Keep file grants operator-owned. Reject agent self-grants across
configuration routes. Preserve attachment consent in create/import
forms. Close generic API file bypasses while retaining current-run
response snapshots and permitted uploads.
- Keep provider limits explicit. Do not inherit a Dot binding,
attachment permission, or workspace permission when hiring another
agent.
- Include the required Markdown format in cross-task document writes and
validate the API title limit. Verify real creation and revision
persistence.
- Restrict command execution to Linux bubblewrap with descendant
containment. macOS retains workspace file tools and artifact publishing,
while refusing command calls. Explain the platform limit in setup.
- Exclude Paperclip instance state from workspace files, uploads,
artifact publication, and sandbox commands. Protect nested directories
and case variants. Fail closed when the directory protection scan
exceeds 4,096 directories.
- Add static UI compression for slow public tunnels. Document setup, the
complete tool inventory, and qualification limits.

## Verification

- Merge preparation on `00ca2c75b` integrates merged base #15402 and
master `fc6304dfe`. The ancestry commit preserves the reviewed follow-up
source tree. The subsequent security fix excludes instance state from
file tools, uploads, artifact publication, and sandbox commands. It
preserves private task authorization and task monitors. It regenerates
the combined tool catalog, seeded catalog digest, and protocol manifest.
Workspace typecheck, full build, and UI token gates pass. All sixteen
real Dot broker cases and 93 company import cases pass after the review
fixes and creator-attribution test correction. The exported
human-assignment catalog and Unicode page boundaries are also fixed. All
ten catalog tests and nine workspace/skill bridge tests pass. All 35
workspace bridge and authority tests passed after the instance-state
fix, including real macOS commands in that intermediate version. The
subsequent document and descendant-containment fixes pass 44 focused
tests across bridge, authority, and setup UI, with six Linux command
cases skipped on macOS. Real cross-task documents pass the route
validator and persist two revisions. macOS refuses command execution and
does not advertise the tool. Full workspace typecheck and build, changed
server/UI typechecks, and token gates pass again on the final commit.
Greptile rates final head 00ca2c75b 5/5 and its completed check
concludes success; all review threads are resolved. All 58 current-head
checks are complete: 54 passed and 4 intentionally skipped. This
includes full tests, typecheck, build, Runner, browser E2E, release
verification, and Canary Dry Run. The older full local root attempt
finished with 16,602 passes, 93 skips, and ten failures across two
suites: it began before source edits and retained earlier imported
implementations while loading later tests. Both suites pass a clean
final-head rerun (25 passed, six Linux-only command cases skipped on
macOS). This mixed-source full attempt is not a final-head full-suite
pass; use the fresh CI evidence below.
- Full workspace typecheck and build pass for the standalone Dot change
on head `392d54f80`. UI token gates are clean. The full workspace
typecheck passed before the final importer UI edit; the changed UI
typecheck, build, and token gates pass again on the final commit. The
server build passes for its unchanged final source.
- Standalone selection, creation, settings, harness visibility,
inventory, and runtime admission checks pass. OAuth onboarding and the
real Rust/PostgreSQL broker suite pass 27 cases with the general Runner
option disabled. Dot and MCP revocation still block pairing; other
Runner providers remain disabled. Create, hire, conversion, and
inherited-hire route regressions pass 68 cases. The runtime selection
suite passes 20 cases. The setup UI suite passes 50 cases. Company
import and dev binary checks pass 97 cases. Import UI checks pass 29
cases, including Dot-only selection, preservation of imported Dot
agents, generic Runner fallback, canonical configuration serialization,
and required billing acknowledgement. A read of the synthetic instance
reports the native binary required with Dot enabled, the general rollout
disabled, and no persisted native work.
- The latest attachment, operator-consent, generic API file-guard, and
bridge checks pass 80 tests. Cache and native lifecycle checks pass 550
tests; create/import builders pass 45 tests; attachment setup UI checks
pass 16 tests. The real Rust/PostgreSQL Dot broker suite passes 15
cases.
- Earlier authority, human assignment, pinned skill, confinement,
cancellation, inheritance, onboarding, replay, OpenAPI, and gateway
regressions pass their focused rechecks. Workspace writes reject
concurrent stale hashes.
- In the live empty test-drive, turn the general Runner option off and
leave Dot and MCP on. Add agent shows a separate OpenAI Dot choice.
Create rejects missing billing acknowledgement, saves the canonical Dot
configuration, and opens pairing. The existing paired Dot remains ready
and passes its prerequisite checks. No new plugin pairing was needed for
this UI change. The final browser import preview keeps a Dot source
agent as OpenAI Dot, falls back a generic Runner agent while its switch
is off, and offers Dot independently.
- Real Dot completed OAuth, signed MCP Events readiness, and an
event-only assigned document task in an empty synthetic instance.
Pairing saved its binding without a second configuration save.
- Real Dot verified human assignment, cross-task comments and documents,
pinned skill reading, sandbox commands, lease renewal, follow-up input,
and a downloaded artifact whose bytes and hash matched its receipt. An
idle conversation request created an intake, created a task for its
human owner, continued after a definite missing-file read error, and
finalized Done with exit code 0.
- After operator approval, real Dot read a synthetic assigned-task
attachment and wrote its file-only random proof into an agent-authored
document. Its first test required accepting review because the existing
document tool removed the final newline.
- On head `2626c8f9b`, real Dot read a 13,849-byte synthetic attachment
in two pages, used `expectedSha256` on page two, saved exactly its final
random marker, verified readback, and finalized Done with exit code 0. A
direct inbox check was required for this attachment qualification; it
does not claim event-only delivery.
- Previous head `392d54f80` passes all 55 checks (53 passed, two
intentionally skipped), including the full test, typecheck, build,
native Runner, browser, and release verification gates. Greptile rates
this head 5/5; all review threads are resolved.
- Head `2626c8f9b` passed all 56 checks: 54 passed and two intentionally
skipped. This includes full typecheck, build, native Runner, server
tests, serialized suites, browser E2E, and Canary Dry Run. The unchanged
Cursor managed-runtime test exceeded its five-second deadline on the
first attempt; its focused local suite passed all eight cases, and the
single CI rerun plus dependent verify gate passed.
- A prior full local serial test attempt reported 19 failures (16,141
passed, 88 skipped) and stopped before later wrapper groups. It began
before the final source edits. Every failed suite has a passing fresh
recheck; the macOS snapshot stress case passes alone in 227 seconds. The
previous head `000fb9261` passed all 56 CI checks. PRs leave
`pnpm-lock.yaml` unchanged; CI and the refresh bot own dependency
resolution.

## Risks

- Dot remains off by default. Its own opt-in does not enable other
Runner providers. It still requires the MCP option; disabling Dot blocks
new work while keeping existing recovery and saved bindings.
- Dot requires a stable public HTTPS origin. Its base provider in #15402
is merged. Temporary tunnels are useful for testing but are not
permanent deployments.
- Idle intake creates a visible agent-authored task. It does not
fabricate a human message or bypass ordinary admission.
- Workspace commands require Linux bubblewrap with a private PID
namespace; deployment qualification is still needed. macOS file tools
and artifact publishing remain available, but commands are disabled
because sandbox-exec does not contain detached descendants. There is no
unrestricted fallback. Command protection fails closed above 4,096
workspace directories. The historical macOS command walkthrough does not
qualify the current Linux implementation.
- Provider model choice, token usage, cost, native thread control, and
global external stopping remain unavailable. Known Paperclip budget
gates still apply.
- The workspace bridge and attachment reader are separate opt-in
settings. Reading assigned task files sends their contents to OpenAI.
Revocation prevents future reads but cannot withdraw bytes already sent.
Files are read on request; automatic inbound attachment staging remains
disabled.
- An existing event registration can retain earlier instructions that
prohibit extra tasks. Dot asked for permission before a second intake
after the final event-only bootstrap; that extra no-nudge continuation
is not live-qualified under that earlier registration. The later
attachment qualification submitted normally through the composer. The
revised onboarding prompt describes the new idle entry point, and its
protocol polling path is tested.
- OpenAI event delivery can be delayed; a webhook acknowledgement is not
proof that Dot has begun work.
- A running Dot can retain an old plugin catalog after tool refresh.
Refresh and actual tool exposure must be checked before using new
top-level actions.
- Hosted and remote controller modes are not qualified.

## Model Used

OpenAI Codex, based on GPT-6. The exact deployment ID and context window
size are not exposed in this session. Capabilities used: reasoning,
repository editing, code execution, test inspection, and browser
control.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either linked existing issues or 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 tests locally and they pass (focused suites and all
fresh failure rechecks pass; the earlier full attempt is disclosed
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-07 19:44:17 -05:00
DottaandPaperclip f669194298 fix(runner): propagate configured environment to future turns (#15451)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runners start provider processes and enforce a separate tool
environment policy.
> - The server resolves task environment bindings at each run boundary.
> - Fixed launch allowlists dropped custom variables after resolution.
> - Warm process reuse and a blanket fingerprint exclusion also hid
configuration changes.
> - This pull request carries a bounded, server-selected list of task
variable names through each process boundary.
> - The benefit is that later turns and tool commands receive configured
values while ambient host secrets stay excluded.

## Linked Issues or Issue Description

**What happened?**

A native Codex agent could not use configured task credentials. Adding
the variables in Settings did not fix the next turn. The provider
sanitizer, runner launch, Rust provider launch, and shell policy each
used fixed allowlists. Effective config fingerprints also excluded all
variables with the `PAPERCLIP_` prefix.

**Expected behavior**

Explicitly bound task variables must reach provider processes and tool
commands. Added, changed, and removed values must take effect at the
next run boundary. A running turn keeps its original configuration.

**Steps to reproduce**

1. Start a native Codex task without a custom environment binding.
2. Add a fake `PAPERCLIP_PAGE_BUCKET` value and a fake Pages credential
binding in Settings.
3. Continue the task and inspect the tool environment.
4. Before this fix, those values are absent even from a fresh runner
launch.

**Paperclip version or commit**

Reproduced at `b31558064`. The fix is rebased on current master.

**Deployment mode**

Self-hosted server with a native process runner.

Related changes: [the legacy Codex MCP environment
fix](https://github.com/paperclipai/paperclip/pull/13321) and [ambient
server-secret
exclusion](https://github.com/paperclipai/paperclip/pull/12870). These
affect different launch paths. This change preserves their credential
boundaries.

## What Changed

- Capture scoped task bindings after resolution, before managed provider
credential injection. Mint and validate the names-only projection at
native dispatch before host inheritance. Legacy adapters retain their
previous environment limits.
- Strip user-supplied projection markers from agent, environment,
project, and routine config.
- Carry selected values through the Codex, ACPX, OpenCode, runnerd, and
Rust subprocess launch boundaries.
- Add selected names to native and ACPX Codex shell include lists. Keep
selected values out of command arguments, including selected bootstrap
values.
- Reject malformed projections, reserved authority and loader names,
missing values, null bytes, and oversized input.
- Replace a retained native process when projected values change. Keep
unchanged processes reusable.
- Fingerprint custom namespaced variables while excluding known
generated runtime variables.
- Document next-run behavior and add regression coverage.

## Verification

- Red: the permanent reproduction failed at four launch/tool boundaries
and the namespaced fingerprint check. Two control checks passed.
- Green: the initial regression plus existing Codex environment and
shell tests passed (39 tests).
- Server config resolution, fingerprints, and native-session suites
passed (653 tests), including addition, rotation, removal, and unchanged
warm-session reuse.
- Rust regression tests passed. A real shell child received added and
rotated values, then lost them after removal. Unselected host variables
stayed absent.
- `pnpm -r typecheck` and `pnpm build` passed after rebase. The full
`pnpm test:run` was attempted but could not complete: fresh embedded
PostgreSQL databases fail during bootstrap on this macOS host. An
isolated suite and a disposable native `initdb` probe reproduced the
failure before test execution. `shmget` reports `No space left on
device` because the host has exhausted shared-memory IDs. This is not
disk exhaustion. The run was stopped after confirming the external setup
failure. CI results will be recorded separately.
- Runner boundary suites: 361 tests passed. Two process-launch errors
during concurrent binary staging passed on isolated rerun.
- Rust Codex provider and process supervisor integration suites: 97
passed, 2 intentionally ignored.
- ACPX shell and selected-bootstrap argv regressions: 3 failed before
the fix, then all 55 relevant tests passed.
- Review compatibility regression: 129-variable and large-value legacy
configurations failed before the correction and passed after moving
native-only validation to dispatch.
- Final review head `3f11e8d25`: repository typechecks and production
build passed. CI completed its implementation checks; one general-server
shard hit SQL `40P01` in `heartbeat-runtime-skills.test.ts` during its
`beforeEach` table truncate (1,199 tests passed in that shard). The
shard passed on its single rerun. All CI checks for this head are green.
Greptile reviewed this head at 5/5 with no new actionable findings; the
compatibility thread is resolved.
- No live provider credentials or model calls are required by these
tests.

## Risks

- Configured task credentials now reach the tools they were configured
for. The controller selects names only after existing scope and
secret-binding authorization.
- TypeScript and Rust validate the same bounded projection. Their
reserved-name rules must stay aligned.
- A changed projection replaces an idle provider process. Unchanged
values preserve reuse. Active turns retain their original environment.
- No database migration or API schema change.

> This fixes existing runner configuration behavior. It does not add a
new roadmap capability.

## Model Used

- OpenAI GPT-6 (Codex), with reasoning, local code execution, and
repository tools. The session does not expose a more specific API model
identifier 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-07 10:16:49 -05:00
DottaandPaperclip 1640c5b6ab feat(ui): render HTML artifacts in a secure sandbox (#15447)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents deliver reports as task attachments and workspace files.
> - The board already renders Markdown, but it shows HTML reports as
source or rejects their preview.
> - Reports can need inline scripts to build charts and tables.
> - Artifact scripts must not read board cookies, storage, or the parent
page.
> - This pull request adds an opaque-origin HTML preview and view
controls beside Download.
> - Users can explore a report, inspect its source, and download the
original file.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The task attachment panel and workspace file viewers.

**Subsystem affected**

ui/ and the server workspace file preview service.

**Current behavior**

HTML attachments show source text. Workspace HTML files cannot be
previewed.

**Proposed behavior**

Render self-contained HTML reports in a sandboxed iframe. Place eye and
code controls beside Download. Preserve the original file for raw view
and download.

**Reason and benefit**

Users can read and filter agent reports in Paperclip without giving
artifact scripts access to the board session.

**Breaking changes**

HTML previews now open rendered. Scripts and styles must be embedded in
the report. Remote resources, API requests, forms, popups, and host
navigation are blocked. Workspace HTML content uses the existing bounded
UTF-8 JSON response.

**Additional context**

Related closed proposals: #3293 and #4857. This change uses the current
attachment and workspace viewers and adds no report-serving endpoint.
The Artifacts and Work Products roadmap item is complete; this improves
its existing preview behavior.

## What Changed

- Add a shared HTML iframe renderer with `sandbox="allow-scripts"` and
no `allow-same-origin`.
- Install a restrictive CSP before artifact markup. Keep inline report
scripts and styles.
- Add shared rendered/raw icon controls beside Download in the
attachment panel, workspace panel, and file sheet.
- Return workspace HTML as bounded text inside JSON. Keep download and
path-access protections.
- Add Storybooks for reports, security probes, workspace viewers, a task
journey, and mobile layouts.
- Document the security boundary and browser test command.

## Verification

- `pnpm -r typecheck` and `pnpm build` pass.
- Token gates and the static Storybook build pass.
- Four browser tests pass. They cover report filters, raw mode, task
entry, workspace viewers, cookies, storage, host DOM, resource requests,
forms, popups, and host navigation.
- The focused UI suite passes 26 tests. The file-resource server suite
passes 36 tests.
- Local full-stack acceptance passes with an actual 52 KB HTML report.
Its chart and filter render. Raw mode preserves the source. Download
bytes match the original file.
- The complete local UI suite passes: 698 files and 7,754 tests.
- `pnpm test:run` was attempted. Its server group recorded two unrelated
timeouts and eight connector failures. All failed cases pass in isolated
reruns, including the complete 388-test connector suite. The remaining
local run was stopped after the full CI test coverage passed, to release
test database resources. The full local command did not complete
cleanly.
- The separate local CLI group passes 511 tests. Three worktree database
cases fail to start embedded PostgreSQL because this Mac has exhausted
its shared-memory allocation. One isolated rerun fails at the same
database startup step. No CLI code was changed. The corresponding CI
test jobs pass.
- All 56 PR checks are clean on
`c771255f1a2e86bd8825f22eafb5d14a5e342cce`. Greptile gives 5/5 with no
actionable findings. The security scan passes. The branch has no merge
conflict.
- Review the **HTML artifacts** section in Storybook. Run `pnpm exec
playwright test --config tests/html-preview/playwright.config.ts` for
the browser checks.

## Risks

- Never add `allow-same-origin` to this iframe. Its opaque origin is the
cookie, storage, and host-DOM boundary.
- Reports that depend on CDN assets need to embed their dependencies.
- The frame can navigate itself. Sandbox restrictions remain after
navigation. This is not full network isolation.
- Inline scripts can consume browser resources. This change does not
isolate CPU or memory use.
- No database migrations or API shape changes are required.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository editing, code
execution, and browser tool use. The runtime does not expose a more
specific model ID or context window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [ ] I have run tests locally and they pass — feature and UI checks
pass; the full local run has the infrastructure limits recorded above.
All CI test jobs 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-07 09:01:05 -05:00
DottaandPaperclip 3a726e676f feat: enforce private task permissions across execution and data (#10633)
Enforce private task and project access across direct reads, search, execution, files, plugins, live delivery, and sharing mutations. Preserve downward-only sharing, current responsible-user authorization, and audited emergency access. Bind historical draft assets with migration 0314.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-07 07:06:40 -05:00
DottaandPaperclip b508a05c43 feat: add internal agent complaints and suggestions (#15367)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents use legacy skills or native runner tools to work on tasks.
> - Those agents can encounter friction that does not belong in the task
thread.
> - A complaint should preserve the raw reaction. A suggestion should
describe an improvement.
> - This pull request adds attributed local storage and both submission
paths.
> - Agents can submit feedback once and continue their primary work.

## Linked Issues or Issue Description

**Subsystem affected**

Server, database, shared contracts, runtime skills, and native runner
tools.

**Problem or motivation**

Agents have no default internal channel for incidental complaints and
suggestions. Sending this feedback through task comments adds noise and
can alter task workflows.

**Proposed solution**

Store free-form feedback in the current instance database. Derive agent,
run, company, and task attribution from active authority. Provide
default legacy skills and provider-neutral native actions. Keep the
instructions close to Warp's MIT-licensed originals.

**Alternatives considered**

Task comments and external Slack delivery add unwanted side effects.
Mandatory suggestion fields and short editorial limits would discard
useful feedback. This release has no listing API, UI, read tool,
automatic triage, or external forwarding.

**Roadmap alignment**

This is a maintainer-requested addition to the existing runtime skills
and runner tool paths. It does not duplicate a listed roadmap milestone.
Searches for complaint tooling, suggestion-box, and agent commentary
found no overlapping public PR or issue.

## What Changed

- Add the company-scoped `agent_commentary` table, shared validation,
and idempotent migration `0310`.
- Add one transactional service and the agent-only POST route. Validate
active authority before writes or replay. Redact known credentials.
Commit a content-free audit with each new record.
- Add `submit_complaint` and `submit_suggestion` to standard, ask, and
planning modes. Keep review, revocation, and completion restrictions.
Store replay identity on the commentary row.
- Mount `complain` and `suggestion-box` by default for legacy agents.
Bundle a dependency-free Node.js stdin helper in the operational skill
and allow its POST through the sandbox bridge.
- Preserve Warp's complaint voice and suggestion guidance, with
attribution and local transport adaptations. Keep source attribution and
MIT notices in each skill's LICENSE, outside runtime instructions.
- Document custom-runtime HTTP use and database inspection. Add
real-database tests and a repeatable live Codex smoke for local and
Daytona execution.
- Pin the lagging-source migration fixture before the identity-repair
migration so later migrations preserve its regression coverage.

## Verification

- Personally ran real Codex submissions in all four environments on
2026-10-06. Local runs passed at 20:35 UTC. Daytona native passed at
20:31 UTC; Daytona legacy passed at 20:33 UTC. Each stored exactly two
rows with company, agent, run, and task attribution, wrote the
continuation marker, exited zero, created no task comments, and left
task status unchanged. Each recorded two content-free activity entries.
- Daytona used production provider hooks, real remote execution and file
transfer, the legacy queue callback bridge, and native private WebSocket
ingress. The current Linux runner was built from `abf47b595`, staged,
and verified against controller contracts. Both sandboxes were confirmed
deleted. This is a focused feedback transport smoke; it does not claim
full Runner E2E catalog or browser qualification.
- The immutable base image and Linux binary digest are recorded in [the
verification
documentation](https://github.com/paperclipai/paperclip/blob/codex/agent-commentary/doc/agent-commentary.md#verification).
The smoke script can save content-free JSON evidence. No credentials or
feedback bodies are in these reports.

| Environment | Runner | Complaint row | Suggestion row |
| --- | --- | --- | --- |
| local | legacy Codex | `59413a00-1de2-4bb1-bcc6-9c4b54c64aa6` |
`3db2364d-3e15-4f47-846f-875d3902999d` |
| local | native Codex | `5da22b5f-41df-4de5-8ba0-d9345ab01267` |
`2d5abe17-dd41-403c-a5ee-4729f2d58921` |
| daytona | legacy Codex | `27c9d0aa-8477-409f-9da0-e8ffa48dee50` |
`209681c9-d1e9-4ce1-999e-48fa07692389` |
| daytona | native Codex | `6eb001bb-4bcf-43f7-8717-f662f53dc7c3` |
`77c383d8-a997-49e5-a33e-25c70e15c0b2` |

- Run the local check with `node cli/node_modules/tsx/dist/cli.mjs
server/scripts/verify-agent-commentary-live.ts`. The documentation gives
the Daytona invocation. Both use disposable instance databases and
normal Codex provider usage.
- Repository `pnpm -r typecheck` and `pnpm build` passed after the test
extension. The build includes runner generation, contracts, and replay
checks. The smoke scripts also passed a separate TypeScript check. The
lagging-source migration regression passed. All equivalent current-head
Vitest CI shards passed. The local monolithic `pnpm test:run` invocation
was stopped after CI supplied that coverage; it did not complete
locally.
- Focused tests cover company isolation, spoofing, revoked credentials,
stale ownership, post-finish rejection, concurrent replay, conflicting
keys, atomic rollback, and deletion through existing services. Boundary
tests cover empty text, Unicode, text beyond 8,000 characters, and the
524,288-character ceiling without truncation. Mounting tests cover
Codex, Claude, and sandbox staging. Helper tests cover standalone Node
execution, stdin, invalid UTF-8, redirects, HTTP failure, and its
deadline. Privacy and bridge tests cover successful and rejected
requests.
- Instructions were compared with Warp's originals. MIT notices and
source credits live only in LICENSE files. Native tools preserve
truthful disclosure when asked, without routine announcements.
- [Full
CI](https://github.com/paperclipai/paperclip/actions/runs/37508559190)
and Greptile 5/5 passed on the earlier feature commit `5209c3501`. The
later head found the migration-fixture assumption fixed in this update.
On `8a4965164`, all 55 check contexts passed after one browser shard
rerun. Its initial reviewer signoff failure also passed an isolated
local browser run (1 test). Greptile scored that head 5/5 and identified
one smoke cleanup gap. `6ecbafb0b` fixes failed-acquisition cleanup with
four passing tests and a passing smoke-script typecheck. Fresh CI is
pending for this final test-only fix. No commentary production code
changed during verification.

## Risks

- Feedback is internally attributed. It is not anonymous. Existing
redaction removes known credentials, but agents must still omit
sensitive content. Normal provider transcripts can include their
submitted arguments.
- Default skill availability changes for existing legacy agents. Runtime
policy filtering still applies. The helper uses the existing Node.js
runtime with no extra dependencies; custom runtimes can call the HTTP
endpoint.
- Feedback is removed with its run, agent, or company. Task deletion
clears only the issue pointer. Normal database backups include the
table.
- The migration is additive and has no backfill. Writes serialize on the
active run for replay consistency. No server suggestion quota is
imposed.

## Model Used

OpenAI `gpt-6-astra` through Codex, with `xhigh` reasoning effort and a
reported 258,400-token context window. Capabilities used: repository
inspection, code execution, and live runtime verification. No subagents
were used.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-06 16:14:06 -05:00
DottaandPaperclip f2715e02bb fix(native): surface model capacity errors and retry automatically (#15347)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runs preserve provider events and results, then decide task
state.
> - Codex can fail a turn because the selected model is temporarily at
capacity.
> - Paperclip displayed a generic native-session failure and left the
task in recovery.
> - A known capacity failure needs a clear message and a durable delayed
retry.
> - This pull request uses committed terminal evidence, the
status-effect ledger, and existing dispatch gates.
> - The task can continue automatically without an unbounded retry loop
or a model switch.

## Linked Issues or Issue Description

Related: #13993 adds launcher capacity deferrals before provider
startup. This change handles a committed native Codex `serverOverloaded`
terminal after provider work has started.

**What happened?**
A native Codex turn ended with `codexErrorInfo: serverOverloaded` and
“Selected model is at capacity. Please try a different model.” Paperclip
saved the result, showed a generic failure, and required recovery
instead of waiting and retrying.

**Expected behavior**
Show the capacity error directly. Schedule bounded retries after a short
delay. Preserve saved work and honor current execution gates.

**Steps to reproduce**
1. Run a native Codex task.
2. Commit a `turn.failed` event with `serverOverloaded`, then accept a
failed result for the same turn.
3. Inspect the task error and its recovery state. The regression test
reproduces this without a paid provider call.

**Paperclip version or commit**
Reproduced against master `16b7db35ffa0f9a95913c8cbdeea3d595435691f`.

## What Changed

- Classify capacity failures from committed runner events and the pinned
execution identity. Preserve accepted results and display the specific
capacity error.
- Atomically persist one scheduled successor with the status decision.
Retry after one minute, then two minutes. Share the existing failure
budget and stop after two automatic retries.
- Reuse dispatch gates for ownership, task holds, dependencies, budget,
and locks. Wait for predecessor execution, finalization, and cleanup
before claiming a retry.
- Preserve pending reviewer authority and suppress retries after
reassignment or a successor claim.
- Consume the failed run's resume receipt and delivered wake input.
Rebuild ordinary continuation from the failed run so explicitly resumed
tasks can retry without borrowing one-run authorization.
- Label scheduled retries “Model at capacity.” Add a Storybook example
and avoid duplicate punctuation in the existing retry card.
- Add regression coverage and document the runtime contract.

## Verification

- Targeted recovery and UI suites: 125 tests passed. Additional final
cleanup and lock regressions passed.
- Latest-head continuation and authorization regressions: 57 tests
passed, including all four capacity integration tests against an
isolated PostgreSQL database.
- Rechecked all four capacity integration tests with the full runner's
isolated `PAPERCLIP_HOME`, config, temporary directory, and serial fork
settings: passed.
- `pnpm -r typecheck`: passed. Final server typecheck passed.
- `pnpm build`: passed.
- `pnpm check:token-gates`: passed.
- Browser: checked the real Storybook card. It shows the capacity
message, automatic retry time, and existing Retry now action.
- `pnpm test:run`: attempted and restarted after an interruption. The
resumed run started before the final review correction and was stopped
after recorded workspace/native test failures and the five-minute Git
streaming timeout already documented on master. Exit 130; no complete
local full-suite pass is claimed. Current-head isolated capacity tests
and the complete CI suite pass.
- A combined local recovery-suite attempt also hit PostgreSQL
initialization failures at this macOS host's global shared-memory limit
(32 slots). The focused recovery suites passed separately; final-head
capacity tests also pass with the full runner's isolated environment
settings.
- Latest-head GitHub checks: all 56 checks green, including general and
serialized test shards, browser E2E, typecheck, build, Runner
verification, and canary dry run. No merge conflicts.
- Greptile: 5/5 on `813a470b8c18c05aeb7e31e63e573c3a3a2f5cac`, with zero
unresolved findings after fixing the resumed-task continuation issue.

## Risks

- Capacity retries can repeat a task turn after partial work. They start
a fresh provider session with task history and wait for predecessor
cleanup. They do not resume the failed turn.
- Retries retain the configured model unless an operator changes
configuration. Persistent overload consumes the existing failure budget
and then needs an explicit retry or model change.
- Only run-bound native Codex `serverOverloaded` failures qualify.
Usage-limit exhaustion, model/account incompatibility, unbound text, and
unknown provider failures retain their current recovery behavior.
- No schema migration is required.

## Model Used

- OpenAI GPT-6 through Codex. The exact model ID and context-window size
are not exposed to this session. Used reasoning, repository tools, code
execution, and browser verification. No subagents.

## 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-10-06 10:59:18 -05:00
DottaandPaperclip 9b3fe260ba fix(tasks): surface Codex ChatGPT model rejection (#15299)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for work.
> - Native Runner runs report provider errors and can also save a structured failure result.
> - Codex rejects a model that the user's ChatGPT account cannot use.
> - Master now diagnoses this rejection, but the task's compact run data omits its message. The thread can still call it a generic run failure.
> - Users need the account restriction and a clear step to repair the model selection.
> - This pull request shows the existing diagnosis as “Model unavailable” on the task.

## Linked Issues or Issue Description

**What happened?**

Codex returns HTTP 400 with `invalid_request_error` and the message `The 'gpt-6.1-sol' model is not supported when using Codex with a ChatGPT account.` Master now stores an actionable diagnosis for this rejection. The task thread still labels it “Run failed” and does not receive its error text in compact run data.

**Expected behavior**

Show the account restriction on the task and in the run error. Tell the user to choose a supported model or clear the task's model override before retrying.

**Steps to reproduce**

1. Use a Native Runner Codex agent signed in with a ChatGPT account.
2. Select a model that produces the rejection above and start a task.
3. Let the runner save its generic failed result. Inspect the task's failure marker and recovery notice.

**Additional context**

Refs: #15304. That merged PR diagnoses the provider failure and preserves worker and review recovery rules. This PR adds its task-facing message and guidance without changing that diagnosis or those rules.

Refs: #13134. That PR improves model discovery for ChatGPT accounts. This PR exposes the rejection when a configured model still fails at execution time.

## What Changed

- Return a bounded model rejection message in compact issue-run data.
- Show “Model unavailable” and model-change guidance in the task thread and recovery notice.
- Add database and UI regression tests, including both the original rejection text and master's fixed diagnosis. Document the new failure message.

## Verification

- Focused merged-branch validation: 279 tests passed across activity service, native provider failure observation and PostgreSQL integration, TaskChatThread, and ExecutionBlockerNotice.
- `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates` passed on the merged source tree.
- Greptile reviewed conflict-resolution commit `1db39c4e636a92e2e76ba224b71c6f1e2f556c81` at 5/5 with no findings or inline comments.
- All 55 check runs completed without failure on that commit. The two optional Storybook jobs were skipped. The legacy Snyk status passed. The branch has no merge conflicts.
- UI regression assertion: the task's failure marker says “Model unavailable” and retains the account restriction. It no longer says that this failure happened after a final response.

## Risks

- Provider recognition and recovery are owned by the existing master implementation. This PR exposes only bounded error text for failed runs with `native_provider_model_rejected`.
- Historical runs with the generic `adapter_failed` code are not reclassified. No stored run is rewritten.
- Existing retry and reconciliation gates remain in place. No schema migration or model configuration change is required.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, code execution, and browser inspection. The exact deployment model ID and context window are not exposed in this session.

## Checklist

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

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 08:05:25 -05:00
Devin FoleyandPaperclip 858094ba81 Fix browser polling for unsaved agent chats (#15298)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat uses the shared task surface and browser panel.
> - An unsaved chat has a temporary ID instead of a stored task UUID.
> - The browser poll sent that ID to a PostgreSQL UUID query and
returned a server error.
> - This pull request waits for a saved task and validates task IDs
before the query.
> - Saved chats keep their browser tools and access checks.

## Linked Issues or Issue Description

Refs #14331. That report describes the same draft-ID problem in email
requests. This change covers the browser routes; it does not change
email behavior.

Opening an unsaved Agent Chat sends `chat:<agent-id>` to
`/issues/:issueId/browsers` every three seconds. PostgreSQL rejects this
as a task UUID. The draft is only a UI view model. The first send or
upload creates its stored task.

## What Changed

- Disable browser polling for unsaved chat IDs. Resume polling when the
chat has a task UUID.
- Return the existing task-not-found response for malformed task IDs
before database access. Keep board authentication first and company and
credential checks unchanged.
- Test all six task browser routes, draft-to-saved polling, normal
tasks, saved chats, and denied access. Keep canonical UUID v4, v7, and
nil values queryable.
- Document the draft and saved-chat browser contract.

## Verification

- `pnpm install --frozen-lockfile` passed with pnpm 9.15.4 and Node
24.21.0.
- `pnpm exec vitest run
server/src/__tests__/browser-use-route-scope.test.ts
server/src/__tests__/browser-use-connection.test.ts` passed all 35
tests.
- `pnpm exec vitest run ui/src/hooks/useTaskBrowsers.test.ts` passed all
5 tests.
- Independent review passed 14 hook and route tests plus both real task
and saved-chat authorization cases.
- `pnpm check:token-gates` and `git diff --check` passed.
- Full workspace `pnpm -r typecheck` and `pnpm build` passed.
- Full Linux CI passed on `dafff44a32`: 53 successful checks and two
intentional Storybook skips. This includes all general and serialized
test groups, UI and browser tests, typecheck, build, and the canary dry
run. No CI retries were needed.
- The full local `TMPDIR=/private/tmp pnpm test:run` started but did not
complete. It was stopped after full Linux CI passed. Before the stop,
three company-skills cache cases failed on macOS. A focused rerun
reproduced all three as `EACCES` while renaming immutable cache staging
directories. The test, company-skills service, and runtime cache files
are byte-identical to the baseline previously reproduced on `e99854249c`
for #15291. Other local groups were not reached; the full Linux CI run
provides aggregate coverage.
- Greptile scored the exact head `dafff44a32` 5/5 with no findings or
unresolved review threads.

## Risks

- Malformed task IDs now return 404 instead of reaching PostgreSQL and
returning 500. The route does not map draft IDs to agents or tasks.
- No schema, browser provider, task creation, or authorization policy
changes.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository editing, code
execution, and independent agent review. The exact deployment model ID
and context window are not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub references)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass (focused suites; full local
run limitations are reported 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-05 19:41:52 -07:00
DottaandPaperclip 45862dd210 docs: add a product feature map (#15288)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Its user journeys span tasks, agents, projects, connected apps,
governance, and CLI operations.
> - Existing tests do not provide a shared index of entry points and
verification steps.
> - Contributors need to see which surfaces a change affects and what
evidence exists.
> - This pull request adds an optional product feature map with recipes
and explicit coverage gaps.
> - The map adds no CI checks or required maintenance for future pull
requests.
> - Contributors can use it to find verification steps and state what
they checked.

## Linked Issues or Issue Description

**Issue type**

Missing documentation.

**Where is the issue?**

User-journey verification guidance in AGENTS.md and doc/DEVELOPING.md.

**What's wrong?**

There is no shared index of product features, user entry points,
available test evidence, and remaining coverage gaps. Shared components
can hide differences between their hosts.

**Suggested fix**

Add a documentation-only capability index and verification recipes. The
format takes inspiration from [Omnigent's feature
map](https://github.com/omnigent-ai/omnigent/tree/91acfbbb59f6fc210ff95a9e9428aadd62e06582/feature-map).
The recipes describe Paperclip's own behavior and tests.

Searched GitHub PRs and issues for `feature map` and `feature-map`. No
duplicate change was found. Checked ROADMAP.md. This PR documents
existing capabilities.

## What Changed

- Added 35 feature recipes, 171 named sub-features, and 91 entry points
across product, CLI, operator, and developer surfaces.
- Each recipe describes setup, expected results, existing automated
evidence, manual verification, and coverage gaps.
- Added a dated source snapshot of 185 non-test page TSX modules in 15
areas. The snapshot describes documentation coverage, not runtime
health.
- Included entry points within existing pages, CLI/API operations, and
experimental surfaces. Identified helper-only test evidence where a
rendered journey has no automated proof.
- Linked the map from AGENTS.md and doc/DEVELOPING.md as an optional
reference.
- The final diff contains only Markdown and the inventory JSON. It adds
no checker, tests, package commands, workflows, dependencies, scheduled
work, or mandatory inventory updates.

## Verification

- PASS: local documentation links resolve and the inventory JSON parses.
Confirmed the final PR diff contains only 39 documentation files.
- PASS: `node --test '.github/scripts/tests/*.test.mjs'` — 381 existing
tests after removal of the feature-map tests.
- PASS: `git diff --check`.
- Earlier local build and typecheck passed. The full local test run was
stopped after 26 minutes with failures in unchanged chat-channel and
native-runner integration tests. It did not complete. These application
checks were not repeated for the documentation-only removal.
- [CI on the preceding
head](https://github.com/paperclipai/paperclip/actions/runs/37398407523)
passed all applicable checks. Checks on the final documentation-only
head are pending.
- PASS: Greptile review on final head
`45c4b0aeb26540324825da43e81bee2336ad1c1f` is 5/5. There are no
unresolved findings.
- Live product/provider journeys were not run to author the map. The
recipes identify available evidence and manual steps, not new
qualification results.

## Risks

Low product risk: the PR changes documentation only. Recipes and the
source snapshot can become stale. Maintenance is optional and based on
review. Linked tests do not prove that every documented journey works.
The map states remaining coverage gaps.

## Model Used

OpenAI Codex, GPT-6 family, with repository inspection, reasoning, tool
use, and code execution. The exact serving model ID and context window
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
- [ ] 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 02:08:47 +00:00
DottaandPaperclip 2c43b39167 refactor(ui): share task composer and project/worktree controls (#15091)
Use the shared composer for new tasks, including project and worktree selection, rich mentions and slash commands, and remembered task settings.

Save project preferences after successful task updates. Show known agent models by name and use Default for unknown runtime defaults.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-05 18:06:40 -05:00
DottaandPaperclip 59015846ae fix(chat): keep dismissed task questions in the feed (#15229)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents ask users questions in task chats and Agent Chat.
> - Agent Chat keeps unanswered questions as compact entries in the
feed.
> - Regular task chats still show a pending composer badge after
dismissal.
> - A page reload can also open a dismissed question form again.
> - This pull request applies the same feed behavior to both chat types
and saves dismissal per person and task.
> - Users can continue the chat and return to the original question
later.

## Linked Issues or Issue Description

**What happened?**

Dismissing a question in a regular task chat leaves a pending composer
badge. The question can return after a page reload. The earlier feed
behavior only applied to Agent Chat.

**Expected behavior**

A dismissed question stays in the feed. Its form and pending badge leave
the composer. Reload preserves dismissal. Opening the feed entry
restores the original question and draft answer.

**Steps to reproduce**

1. Open a regular task chat with a pending question.
2. Select an option, then dismiss the form.
3. Reload the page. Check that the composer stays clear.
4. Open the question in the feed. Check that the draft is restored.
5. Submit the answer. Check that the answered receipt appears.

**Paperclip version or commit**

Reproduced on master at `a386a599983519eb1d399f8b770bfccdb2a74762`.

**Deployment mode**

Browser UI in local and authenticated instances. This change does not
depend on the agent adapter.

Related work: Refs #14613, which added the Agent Chat feed behavior.
Refs #9141, which validates real answers on the server. Refs #11434,
which tracks comment-driven changes to interaction state. This PR
changes question presentation only.

## What Changed

- Show compact unanswered question entries in regular task chats.
- Exclude durable questions from composer pending counts and navigation.
- Save dismissal in local storage per person and task. Merge the latest
saved IDs so dismissals from another tab survive reload. A new question
can still open its form.
- Keep the original question pending and answerable. Keep approval and
permission controls.
- Run the question-history regressions in both chat modes. Add reload,
new-question, user/task scope, and stale-tab coverage.
- Share the real-component Storybook fixture. Add a regular task test
drive and an interactive dismissal/answer scenario.
- Update the planning-mode browser test to check a dismissed question in
the feed after reload and on mobile.
- Update the design rules, implementation spec, and preview
instructions.

## Verification

- 329 focused thread, composer, and interaction-card tests pass.
- `pnpm -r typecheck` passes. The UI typecheck also passes after the
review fix.
- `pnpm build` passes for the full repository.
- UI build, Storybook build, and token gates pass. The UI build and
token gates were rerun after the review fix.
- Greptile gives final commit `98f71f221` a 5/5 score. The current-head
check passes, and there are no unresolved review threads.
- All 56 current-head checks are terminal: 54 pass and two conditional
Storybook jobs skip. The CI run includes the full test shards, build,
typecheck, browser tests, aggregate verification gate, and package
canary.
- The stale-tab regression fails in both chat modes before the review
fix and passes after it.
- `pnpm exec playwright test --config tests/e2e/playwright.config.ts
tests/e2e/planning-mode-visual-verification.spec.ts` passes against a
throwaway local server. It checks dismissal, reload, task navigation,
and desktop/mobile planning controls.
- The duplicate local `pnpm test:run` attempt was stopped after the full
CI test suites passed. It did not complete locally.
- Manual browser test: select Green, dismiss, reload, reopen, submit the
saved answer, and inspect the answered receipt. Also send a new message
while the unanswered question remains in the feed. The test drive uses
real UI components with fixture response callbacks.
- To repeat the browser test, run `pnpm storybook`. Open **Chat &
Comments → Task Chat Unanswered Questions → Test Drive**.

## Risks

- Dismissal is a browser-local preference. It does not sync to another
browser or device. Clearing local storage removes it.
- When local storage is unavailable, dismissal lasts for the mounted
thread only.
- Unanswered questions can accumulate in the feed. They stay pending
until answered or resolved through the existing API.
- No database migration, API change, or change to approval permissions.

## Model Used

OpenAI Codex, `gpt-6.1-sol`, with xhigh reasoning, repository editing,
code execution, and browser control. The context-window size is not
exposed in this session.

## Checklist

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

> - Paperclip manages AI agents and the tasks they perform.
> - The native runner saves tool results and completion reports before
it releases a session.
> - Large project discovery responses can exceed the durable command
limit.
> - A shutdown failure can leave a saved answer waiting for workspace
repair.
> - Recovery reused the old assessment for a different status decision,
which violated a database constraint.
> - This pull request bounds discovery responses and lets recovery
commit the saved result after workspace repair.
> - The benefit is a task that reaches its correct final status without
another provider turn.

## Linked Issues or Issue Description

**What happened?**

A native run can save its final answer, fail during shutdown, and leave
the task In Progress after workspace repair succeeds. Reconciliation
tries to reuse the failed-workspace assessment for a new decision. The
one-decision-per-assessment constraint rejects the write. Replaying the
old decision can also retain a fresh coordinator lease. Separately,
retained session cleanup only recognizes the old `adapter_failed` label.

The project-list tool returns full project records, including large
descriptions and workspace configuration. A large response exceeds the
runner's durable command limit. The settlement diagnostic previously
recorded only a failure flag.

**Expected behavior**

Project discovery stays within the command limit. Recovery finishes the
saved result after workspace repair, releases its lease, and preserves
the original error for inspection. It does not repeat provider work or
relax session ownership checks.

**Steps to reproduce**

1. Return large project records from `list_projects` and observe an
oversized semantic result.
2. Persist an accepted native completion result, then record a shutdown
failure.
3. Finalize with a failed workspace, repeat that attempt, then record
successful workspace repair.
4. Reconcile the run. Before this fix, the issue stays In Progress.

**Paperclip version or commit**

Reproduced on `a386a599983519eb1d399f8b770bfccdb2a74762`.

**Deployment mode**

Self-hosted server with Paperclip Runner.

Related transport work: #12208 drains queued events; #12241 resumes
interrupted semantic calls. This change addresses bounded project
discovery and accepted-result finalization.

## What Changed

- Read bounded project summary projections from the database and return
at most 50 authorized summaries with a continuation cursor and explicit
description truncation. Agent and run trust boundaries narrow the
database candidates; project-specific policies still receive full
authorization. Only visible projects determine continuations. The
default project-list API remains unchanged.
- Record bounded, content-free settlement failure causes for command
limits, storage errors, and rejected dispatch.
- Include workspace state in assessment identity. Preserve the initial
assessment for interrupted finalization, and commit replacement
assessment and decision references together.
- Release the coordinator lease when an existing decision is replayed,
without repeating its effects.
- Clear stale errors when recovery succeeds and retain them in
`recoveredExecutionFailure`.
- Accept both current and legacy close-failure labels in the existing
exact-state cleanup path.
- Add regression tests and update the tool contracts and recovery
documentation.

## Verification

- Red: the new project paging, settlement diagnostic, current cleanup
label, and repaired-workspace regressions failed on the original
implementation.
- Green: protocol/catalog/tool checks (117 tests), the full project-tool
and finalizer suites (47 tests), cleanup ownership cases (70 tests), and
cleanup sweep cases (4 tests) pass. Database-backed pagination covers
large descriptions/configuration, complete enumeration, uppercase
cursors, agent/run restrictions, project-policy scope contributions, and
identical results/cursors when hidden projects are added.
- The initial CI failures in interrupted Board waits, contended endpoint
proof, and semantic schema validation were reproduced and fixed; all
affected cases pass locally.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed.
- `pnpm test:run` — started before the review corrections; it spanned
several source revisions and was stopped after reporting old-behavior
and timing failures. It is not claimed green. Fresh project and recovery
suites pass; the recovery suite also passes all 25 cases with the broad
runner’s isolated home/config. The Slack timing case passed in
isolation. Latest-head CI is the authoritative complete test matrix.
- Existing authorization suite — 66 tests passed.
- Latest-head CI on `8e5763d915aa6f375bdab6601996899ea01496fc` — 55
checks passed, 4 intentionally skipped, no pending or failing checks.
- Greptile — 5/5, zero unresolved threads on the same commit.
- `git diff --check` — passed.

## Risks

- `list_projects` now returns summaries. Callers must follow
`nextCursor` and use the authorized project API for full records.
Candidate narrowing is only an optimization: project policy and
responsible-user authorization remain authoritative.
- Assessment identity changes for workspace finalization. Existing
evidence remains intact; no migration is needed.
- Cleanup still requires matching identities, settled tool evidence, and
verified process ownership. Unknown tool outcomes remain blocked from
session reuse.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, code execution, and GitHub
tools. The exact serving model ID and context window are not exposed in
this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-05 10:31:11 -05:00
DottaandPaperclip 6eaf218924 chore: grant Storybook publishing access through CODEOWNERS (#14984)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Storybook previews help contributors review the board UI.
> - The publishing workflow uses the default branch CODEOWNERS file to
authorize users.
> - Tonio and Scott need access to this workflow.
> - This pull request adds both accounts as release documentation
owners.
> - The existing workflow can then authorize both accounts without a
separate user list in code.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Access to the Storybook build and publishing workflow.

**Subsystem affected**

Repository ownership and GitHub Actions authorization.

**Current behavior**

The workflow reads individual accounts from every CODEOWNERS rule on the
default branch. Neither `tonio-alucema` nor `scotttong` is in that file.
Both accounts already have repository admin access, but the workflow
authorization check denies them.

**Proposed behavior**

Add both accounts to the `doc/RELEASING.md` ownership rule. After merge,
both can start and rerun Storybook publishing workflows. A configured
`storybook-deploy` environment reviewer must still approve deployment.
CODEOWNERS membership does not add an account to the environment
reviewer settings.

**Reason and benefit**

Contributors can publish UI previews through the same CODEOWNERS policy
as other maintainers. The authorization code has no account-specific
exceptions.

**Breaking changes**

None. The existing authorization and deployment approval checks remain
in place.

**Additional context**

Related changes: #13226 added the publishing workflow. #13231 added
stable branch bookmarks. A search found no open PR for these permission
changes.

## What Changed

- Add `@tonio-alucema` and `@scotttong` only to the release
documentation ownership rule.
- Test that accounts listed for release documentation can start and
rerun publishing workflows.
- Test that removing an account from CODEOWNERS removes its publishing
access.
- Explain how CODEOWNERS entries and environment reviewers affect
publishing access.

## Verification

- `node --test scripts/__tests__/storybook-deploy.test.mjs`: all 25
tests pass.
- `actionlint .github/workflows/storybook-deploy.yml
.github/workflows/storybook-visual.yml`: passes.
- `git diff --check`: passes.
- GitHub API checks confirm that both accounts have repository admin
access. The deployment environment requires an existing reviewer and
disables administrator bypass.
- Repository-wide typecheck, tests, and build were attempted. They
cannot complete in this worktree because workspace dependencies are not
installed. Typecheck cannot find Node type definitions. Tests and build
cannot load the workspace `tsx` package.
- After merge, run `Storybook Deploy` from `master`, select a source
branch, obtain environment approval, and check the published URLs in the
run summary.

## Risks

Both accounts gain permission to start and rerun Storybook publishing.
Deployment still needs approval from a configured environment reviewer.
No AWS permissions or live GitHub settings change in this PR.

## Model Used

OpenAI GPT-6 through Codex. The exact backend model ID and context
window are not exposed in this session. The agent used reasoning,
repository inspection, code editing, shell execution, and GitHub API
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
- [ ] 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 17:34:37 -05:00
Devin FoleyandPaperclip dd9983b894 fix(adapter-utils): release restore locks when a process crashes (#14869)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent runs restore workspace files and collect instruction-file
changes.
> - Writers to the same target directory must wait for each other.
> - The current lock records a PID, which a new process can reuse after
a crash.
> - A reused PID can keep an orphaned lock alive and make each later run
fail.
> - This pull request makes a SQLite file lock decide ownership. The OS
releases it when the process exits.
> - Later runs can proceed after a crash, and concurrent live writers
remain protected.

## Linked Issues or Issue Description

Refs #10914. This addresses crash recovery. It does not cancel a stalled
operation in a process that is still alive.

Related work: #9667, #14787, and #12187. The earlier attempt in #9667
assumes one live server per lock root. This implementation uses an
OS-backed lock to support concurrent writers without treating a
different process token or an old timestamp as proof of a dead owner. It
retains the private lock root and bounded timeout diagnostics from the
merged changes.

After a process dies while holding a restore lock, a replacement process
can reuse its PID. The existing `process.kill(pid, 0)` check then
reports a live owner forever. Later runs can complete their model turn
but fail during file collection or restore.

## What Changed

- Hold a SQLite `BEGIN IMMEDIATE` transaction for each directory write.
Use the existing built-in `node:sqlite` dependency.
- Keep each lock database on a stable inode. Keep PID and time metadata
only for diagnostics.
- Retain the 30-second asynchronous wait and existing timeout error code
and diagnostic fields.
- Fail closed when an old directory lock exists. Document a
stopped-writer upgrade and rollback procedure.
- Add real child-process tests for crashes, PID reuse, live owners, and
connection cleanup. Cover callback failures, independent targets, stable
inodes, invalid lock files, and ambiguous legacy records.

## Verification

- Before the fix, the crash/PID-reuse test and the live-owner test both
failed. Both pass with this change.
- `pnpm exec vitest run
packages/adapter-utils/src/directory-merge-lock.test.ts
packages/adapter-utils/src/workspace-restore-merge.test.ts`: 56 tests
passed.
- Restore and agent-file working-copy integration tests: 118 tests
passed before the additional connection-cleanup test.
- `pnpm -r typecheck`: passed.
- `pnpm build`: passed.
- Full GitHub CI: all checks passed, including Linux workspace tests,
server test shards, build, typecheck, and browser tests.
- Greptile: 5/5, with no review threads or unresolved comments.
- `pnpm test:run`: started locally, then stopped with SIGINT (exit 130)
after full CI passed. The local serial run did not complete and is not
counted as a full local pass. The completed CI shards provide the
full-suite result.

## Risks

- **Upgrade and rollback require a drain.** Stop every old writer that
shares an instance root before switching protocols. Old and new versions
must not write concurrently.
- Existing legacy `.lock/` directories remain blocking. After all
writers stop, preserve run evidence and move those directories to an
operator scratch directory. The new code does not infer that they are
abandoned from PID or age.
- Never delete or replace a `.lock.sqlite` file while writers can run.
These small files remain after release.
- The shared filesystem must support reliable SQLite locking. Broken
network-filesystem locking is unsupported.
- This change prevents new orphaned ownership. It does not recover file
changes lost during earlier failed collections, or interrupt a live
operation that stalls.
- No application database migration or new native dependency is
required. See `doc/workspace-restore-locks.md` for the procedure.

## Model Used

OpenAI Codex based on GPT-6, with code execution and repository tools.
The exact model variant 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 (focused regression and
integration suites; see the full-suite note 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-01 12:14:48 -07:00
Devin FoleyandPaperclip 6f2ce27ca7 fix(workspaces): prepare checkouts without a local seed config (#14810)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task preparation can create an isolated Git worktree and run its
setup script.
> - The Paperclip repository setup script also prepares a seeded
development instance.
> - A server configured through environment variables can have no local
seed config.
> - This stops ordinary task preparation before the agent starts.
> - This pull request prepares checkout dependencies when no seed source
exists, while preserving errors for invalid sources and existing
development instances.
> - Tasks can start without creating or claiming a seeded development
runtime.

## Linked Issues or Issue Description

**What happened?**

A task with the Paperclip repository fails during setup when the host
has no repository-local or default instance config. The automatic
worktree provisioner requires a seed source even when the task only
needs the checkout.

**Expected behavior**

A plain checkout should prepare its dependencies without a local
development database. A missing custom source, invalid source path, or
existing development instance with a missing source should still fail.
Starting a seeded runtime must still require a valid source.

**Steps to reproduce**

1. Run an environment-configured Paperclip server without a local
instance config.
2. Add the Paperclip repository to a project.
3. Start a task that uses an isolated Git worktree without a custom
provision command.
4. Observe the setup error before agent execution.

**Paperclip version or commit**

Reproduced against `0d3e7bf6ac` with a real script subprocess and
workspace realization regression.

**Deployment mode**

Environment-configured server with external PostgreSQL.

**Additional context**

Searched open and closed GitHub PRs and issues. Related work: Refs
#14795 (seed-source diagnostics) and Refs #11733 (source validation).
This change keeps source validation and seed-readiness checks in place.

## What Changed

- Permit dependency setup when the default seed config is absent
(including the Docker image config path) and the worktree has no
development-instance state.
- Keep missing custom configs, invalid paths, and lost sources for
existing instances as errors.
- Create no config, environment file, or seed manifest for a plain
checkout.
- Keep dependency install failures visible and allow normal instance
setup once a source becomes available.
- Cover the setup script, seed-runtime refusal, and automatic server
worktree realization.
- Document the difference between checkout preparation and
seeded-runtime readiness.

## Verification

- Regression tests failed before the fix for absent-source checkout
preparation and dependency setup.
- `bash -n scripts/provision-worktree.sh`
- `node --test scripts/__tests__/provision-worktree-self-heal.test.mjs`
— 34 passed; 1 existing flock-dependent test skipped on macOS.
- Server regression — 2 passed, covering an unset config and the Docker
image default path.
- `pnpm build` — passed.
- `pnpm -r typecheck` — passed.
- All CI checks passed, including the full test shards, build,
typecheck, browser tests, and canary dry run.
- The first local `pnpm test:run` encountered two chat-test failures
because skill discovery selected an unrelated parent directory. Both
tests pass at the PR commit in a clean temporary checkout. The full
local run was not completed; the redundant clean run was stopped after
the complete CI suite passed.
- `git diff --check` and added-line secrets/PII scan passed.
- Greptile: 5/5, no comments. The branch has no merge conflicts.
- No live tenant deployment or task retry was performed.

## Risks

- A new checkout with no implicit seed config now completes dependency
setup. It has no seeded development instance. A runtime request still
fails until a valid source exists.
- Existing instances and custom source paths retain their failure
behavior. The script does not synthesize a source from environment
credentials or copy a live database.
- No schema, API, or task-setting changes. Revert the commit to restore
the previous setup behavior.

## Model Used

OpenAI Codex (GPT-6), with tool-assisted analysis, code edits, and local
tests. The runtime did not expose a verified 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-01 10:00:25 -07:00
DottaandPaperclip 527e146980 feat(ui): share animated agent setup prompts (#14862)
Use the shared animated prompt-copy control across setup, invitations, webhooks, and task handoffs. Preserve first-click copying, clipboard recovery, and logo continuity. Add Storybook coverage and restore mention icon masks for the current Lucide data shape.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-01 11:46:14 -05:00
Devin FoleyandPaperclip 0dc8d80eea Clarify worktree seed source setup failures (#14795)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Managed worktrees can prepare an isolated Paperclip development
instance.
> - The built-in provisioner requires a canonical registered seed source
config.
> - A missing source currently has the same message as a rejected
symlink or non-regular file.
> - This pull request separates those messages and names the supported
setup choices.
> - Operators can choose the intended setup without changing the
source-validation guards.

## Linked Issues or Issue Description

**What happened?**

A plain repository checkout can select the control-plane instance as its
seed source. If that instance runs with environment-only configuration,
the source config file can be unavailable. The provisioner stops with a
message that also covers noncanonical files and gives no repair
guidance.

**Expected behavior**

The error should identify the selected source and distinguish an
unavailable prerequisite from a rejected file. It should explain that a
seeded development instance needs a canonical registered source. It
should describe the explicit no-op only for a checkout-only worktree.

**Steps to reproduce**

1. Use a plain base checkout with no repository-local config.
2. Leave the control-plane instance config file absent.
3. Run the built-in worktree provisioner against an isolated checkout.

**Paperclip version or commit**

Base commit `c8f874311c`.

**Deployment mode**

Managed local worktrees, including servers configured only through
environment variables.

Related: #11733 adds deeper source-readiness checks. #11735 changes
runtime and seed lifecycle handling. This change only improves the
existing shell guard's diagnostics.

## What Changed

- Distinguish unavailable source configs from symlinks and non-regular
files.
- Identify whether the selected source belongs to the base workspace or
control-plane instance.
- Explain seeded-instance prerequisites and the explicit checkout-only
setup choice.
- Verify failure still precedes target-state creation and CLI
invocation.
- Document the setup choice and its runtime-readiness limit.

## Verification

- `node --test scripts/__tests__/provision-worktree-self-heal.test.mjs`:
21 passed; one platform-gated test skipped because macOS lacks `flock`.
- `bash -n scripts/provision-worktree.sh` and `git diff --check`:
passed.
- `pnpm -r typecheck`: passed.
- `pnpm exec vitest run server/src/__tests__/ai-connections.test.ts`: 50
passed after running the installed PostgreSQL package's own symlink
hydration script in this worktree.
- `pnpm test:run`: attempted, then stopped after unrelated database
suites failed at startup. The offline install had omitted PostgreSQL
native library symlinks. The focused database rerun above verifies the
local repair; the complete suite is delegated to CI.
- `pnpm build`: passed.

- [Required PR
CI](https://github.com/paperclipai/paperclip/actions/runs/36797650741)
passed on `0a3ba63e12`: 50 successful checks and two intentional
Storybook skips. Greptile scored that exact commit 5/5; there are zero
unresolved review threads and no merge conflicts.

## Risks

- Diagnostics only. This does not supply a source config or repair an
existing blocked task.
- The failure predicates and exit status stay unchanged. Symlink and
non-regular-file errors do not recommend skipping setup.
- The checkout-only no-op requires an explicit policy choice. It does
not grant runtime or seed readiness.
- No schema, migration, tenant policy, deployment, or Sentry reporting
change.

## Model Used

OpenAI GPT-6-based Codex, with reasoning, shell tools, and code
execution. The exact serving model ID and context-window size are not
exposed by this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run 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-30 18:35:33 -07:00
DottaandPaperclip e2908fff5c fix: enforce terminal outcomes during recovered sandbox cleanup (#14767)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runners can keep a reusable sandbox warm after successful
turns.
> - Failed turns must stop their sandbox before a later retry resumes
it.
> - Workspace recovery can release a lease outside the executor's normal
teardown.
> - Successful file copy-back can then retain a sandbox even when its
run failed.
> - This pull request checks the durable run outcome at the shared
release boundary.
> - Ordinary teardown and recovery now apply the same retention rule.

## Linked Issues or Issue Description

**What happened?**

A real Daytona verification on `5edf55d73` produced a failed native
turn. The runner process exited, but workspace recovery retained the
sandbox without stopping it. The recovery callback used successful
workspace copy-back to select warm retention. It bypassed the
terminal-state check in normal heartbeat teardown.

**Expected behavior**

Keep a sandbox running only after a successful run. Failed, cancelled,
timed-out, and interrupted runs must convert requested warm retention to
stop-and-retain. Preserve the existing ownership hold before release.

**Steps to reproduce**

1. Persist a terminal failed native run whose workspace copy-back
succeeds.
2. Release its environment lease from the recovery path with a stored
`keep_running` disposition.
3. Observe that the provider receives `keep_running` on the base commit.
4. With this fix, the provider receives `stop_and_retain` and the lease
status follows the durable run outcome.

**Paperclip version or commit**

Base: `5edf55d7350c7f08c9dd132c7e0f1421fa0bf2fb`.

**Deployment mode**

Native runner with a reusable Daytona sandbox.

Related: #14747 retires unsuccessful warm runner sessions. This change
closes the separate recovery lease-release path. Related search found no
duplicate fix.

## What Changed

- Read the durable run status at the shared lease-release boundary.
- Apply the existing terminal-outcome retention rule before calling the
environment runtime.
- Use that same durable status for the lease-state mapping.
- Add five database-backed regressions for four unsuccessful outcomes
and successful warm retention.
- Document the recovery rule.

## Verification

- Before the fix: the four unsuccessful-outcome regressions fail; the
successful case passes.
- After the fix: 163 tests pass across the lease-release, native
lifecycle, and explicit continuation suites.
- Repository typecheck and build pass.
- `pnpm test:run` encountered the existing local
`native-session-resume.test.ts:1125` assertion failure; a focused rerun
reproduced the same failure. This was also recorded before this
follow-up with the unmodified base executor. The full command was
stopped after that confirmation, so later local groups were not
completed.
- All 56 latest-head checks are successful or intentionally skipped (54
passed, 2 skipped), including the complete CI test groups and browser
E2E suite. Greptile is 5/5 on `e7da3b3ad`, with no unresolved review
comments.
- Deployed exact PR head `e7da3b3adbf7a13642c0e56f5b0f0c4666adf358` to
the staging workspace and independently verified the serving commit. A
real failed native turn persisted `keep_running` and completed workspace
finalization, reproducing the recovery-path conditions; Paperclip
automatically issued stop-and-retain, and an independent Daytona read
confirmed `stopped`. No manual stop was used.
- Retried that failed run through the public API after correcting its
temporary API-key credential. The same stopped sandbox resumed
successfully. Three successful turns retained one live runner PID/start
time and the same native, runner, and provider sessions.
- Verified exact canonical note contents, deletion persistence, and an
unchanged 8 MiB binary after every turn. Subsequent checkpoints
copied/hashed only 58 and 87 bytes. After sandbox deletion, canonical
files still matched. Temporary secrets were removed and
agent/configuration policy restored.
- Live acceptance used temporary API-key authentication. The separate
managed-subscription authentication issue and browser Retry control were
not tested by this campaign.

## Risks

- Recovery callers can no longer use stale success status to retain a
failed run's sandbox.
- The existing native ownership hold still blocks release while
ownership is unresolved.
- Successful warm turns and explicit destroy dispositions keep their
existing behavior.
- No database migration, API contract, dependency, or UI change is
included.

## Model Used

OpenAI Codex, GPT-6, with reasoning, tool use, code execution, and test
analysis. 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-09-30 17:20:25 -05:00
Devin FoleyandPaperclip d6d67b00d3 Prevent background workspace scans from refreshing the Git index (#14666)
## Thinking Path

Paperclip runs background workspace scans alongside real Git writers.
`git status` can refresh the index as an optional side effect, taking a
lock that makes another operation fail. Disable optional locking in the
shared scan subprocess so background observation does not compete with
workspace updates.

## Linked Issues or Issue Description

**What existing behavior does this improve?**
Workspace Git scans used by changed-file browsing, cleanliness guards,
and sandbox snapshots.

**Current behavior**
The scan process inherits Git's default optional-lock behavior. Even a
clean `status` can rewrite stale stat-cache entries in the index and
contend with a concurrent writer.

**Proposed behavior**
Always set `GIT_OPTIONAL_LOCKS=0` for the shared scan subprocess while
preserving the selected environment and Git's required write locks.

**Reason and benefit**
Background reads stop creating avoidable index contention. Git documents
this behavior and recommends disabling optional locks for background
status: [background
refresh](https://git-scm.com/docs/git-status#_background_refresh).

**Breaking changes**
None to scan results or required write locking. Later scans may repeat
stat checks that would otherwise have been cached in the index.

Related scan implementation: #11572, #14253. This avoids one known
contention source; it does not identify every historical lock owner or
repair abandoned locks.

## What Changed

- Disable optional locking at the shared scan subprocess boundary,
including explicit caller environments.
- Test a clean status against a deliberately stale index and prove an
ordinary status would rewrite it.
- Test tracked/untracked results with an existing index lock,
preservation of that lock and working files, and continued rejection of
a mandatory-lock write.
- Document the scan behavior and performance tradeoff.

## Verification

- Focused stream, workspace-sync, and scheduler suites: 63 tests passed.
- Full `pnpm -r typecheck` and `pnpm build` passed locally. Final head
`effe6420c77bd18d36af6b093db3a564c04b8b38` 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 had missing embedded-Postgres
library symlinks; the dependency setup was repaired. Duplicate local
full-suite runs were stopped after full CI completed. This PR does not
claim a completed full local suite.
- Review regression: real Git honors the supplied `GIT_CONFIG_*` setting
and the input environment remains unchanged; all four direct subprocess
cases passed.
- Reviewed the diff for secrets, customer data, and internal references.

## Risks

Low risk. Disabling optional index refresh can repeat filesystem stat
work on later scans. Required locks remain enforced; no lock is removed,
no failed reset is retried, and workspace mutation guards are unchanged.
No schema changes.

## 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:28:07 -07:00
DottaandPaperclip 5edf55d735 fix: retire failed warm sessions before sandbox stop (#14747)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runner sessions can stay warm between turns in a reusable
sandbox.
> - Heartbeat stops that sandbox when a turn fails or is cancelled.
> - The native executor treated every returned terminal result as a
successful warm release.
> - A failed session could therefore retain a transport for a stopped
sandbox.
> - This pull request retires unsuccessful sessions before heartbeat
stops their sandbox.
> - A retry can start without inheriting that stale transport.
Successful turns stay warm.

## Linked Issues or Issue Description

**What happened?**

A structured failed or cancelled terminal result did not throw. The host
kept its native session in the warm cache even though heartbeat stopped
the reusable sandbox. Later session retirement could use the stopped
provider transport and reject the retry.

**Expected behavior**

Retire the unsuccessful session and collect its managed files before
returning to heartbeat. Keep successful sessions warm.

**Steps to reproduce**

1. Run a native session with a warm lifecycle and a reusable sandbox.
2. Return a structured failed or cancelled result from the provider.
3. Stop the sandbox after the executor returns.
4. Retry with a changed native session identity.
5. Verify that the previous session was closed before step 3 and is not
closed again during retry.

**Paperclip version or commit**

Developed from `b54b2dc35`, the current `origin/master` at
implementation time.

**Deployment mode**

Native runner with a reusable Daytona sandbox. The same warm-session
release path also serves local providers.

Related work: #14735 added incremental managed-file checkpoints for warm
turns. #14734 preserves tool outcomes during shutdown. This change fixes
the host's handling of unsuccessful terminal results.

## What Changed

- Retain a warm session only when its terminal run state is `succeeded`.
- Use the existing failed-session retirement path for structured
failures and cancellations.
- Preserve the existing checkpoint-before-retirement path, including
when provider shutdown fails. Collect stopped files after successful
shutdown, including edits made during shutdown.
- Retire the warm owner if the checkpoint or its receipt callback
rejects, then propagate the initiating error.
- Add ten regression cases for failure and cancellation, with and
without managed files. They check cleanup order, cache removal, retry
with a new session identity, and edits preserved when close rejects.
- Document the lifecycle rule.

## Verification

- The failed and cancelled managed-file regressions fail on unpatched
master because the provider is not closed.
- All 516 native executor tests pass, including ten new regressions.
- `pnpm -r typecheck` and `pnpm build` pass. `pnpm test:run` finished
its general-server group with 14,537 passed, 75 skipped, and one
existing failure in `native-session-resume.test.ts`
(`retainedNativeCleanupJournalMatches`, line 1125). A separate run using
the unmodified `origin/master` executor fails the same assertion. The
command stops before later local groups; all equivalent CI groups pass
on this head.
- All 56 PR checks are successful or intentionally skipped. Greptile
reviewed this head at 5/5 with no remaining findings.
- A real Daytona public-API probe forced a Codex authentication failure,
waited for a confirmed sandbox stop, corrected the credential, and
retried successfully in the same resumed sandbox. It verified the agent
note in canonical storage and deleted the test sandbox.
- Pumpkin staging on this exact commit: forced a structured
authentication failure, confirmed sandbox stop, corrected the
credential, and retried successfully in that same sandbox. Three
successful turns kept the same live runner PID/start ticks, native
session, runner instance, and provider session. Canonical downloads
verified the note, all 8 MiB binary bytes, and deletion persistence.
Subsequent checkpoints hashed/copied only 52 and 78 bytes. After sandbox
deletion, canonical files still matched. Temporary secrets, agent
configuration, and test policy were cleaned up or restored.
- Unpatched live probes with both 5-second and 90-second retry delays
also succeeded. The unit regressions prove incorrect retention; the
original stopped-lease exception was not reproduced in those probes. The
staging recovery campaign used the public retry API after an explicit
reset of the disposable task’s already-deleted old sandbox/session. The
UI did not expose a Retry control on the inspected task or run detail
views.
- Temporary API-key authentication was used for the campaign. This
change does not repair the original managed-subscription authentication
401.

## Risks

- Failed and cancelled turns now close their provider sooner. Successful
warm-turn behavior is unchanged.
- Cleanup uses the existing failed-session path. Its existing handling
of cleanup errors is unchanged.
- No database migration, API contract change, or dependency change is
included.

## Model Used

OpenAI Codex, GPT-6, with reasoning, tool use, code execution, and test
analysis. 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 (516 relevant executor
tests; the full local suite has the independently reproduced baseline
failure documented above)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-30 15:36:06 -05:00
DottaandPaperclip 1b48e73e0b feat(ui): add secondary navigation for agent chat (#14706)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat already provides a persistent conversation with each
agent.
> - Its shortcuts share the primary navigation and do not give chats a
dedicated place.
> - People need to find agents, start a chat, and switch conversations
without moving the page layout.
> - This pull request adds a secondary chat sidebar and a landing page
around the existing chat surface.
> - The same conversation, composer, history, and context panel remain
in use.

## Linked Issues or Issue Description

Refs #13283 and #13420. This extends the existing experimental Agent
Chat navigation after review of the component and page stories. It
supports the CEO Chat roadmap item through the existing task-backed
conversation model.

**Subsystem affected**

The board UI and the company-scoped conversation list API.

**Current behavior**

Chat shortcuts sit inside the primary navigation. There is no dedicated
landing page with a searchable conversation list. A separate landing
header also moves the sidebar when an agent is selected.

**Proposed behavior**

Show a Chat entry in primary navigation. Keep a searchable agent sidebar
beside the chat content. The plus button starts or reopens the current
user's single conversation with that agent. Keep the header and sidebar
in the same positions before and after selection.

**Reason and benefit**

People can find agents and return to persistent conversations without
leaving the chat area or creating duplicate chats.

**Breaking changes**

The experimental chat navigation changes. Explicitly adding a chat now
resolves its conversation immediately. Direct visits to unused agent
chat URLs remain read-only. The existing per-agent routes and message
contracts remain compatible. No database migration is required.

## What Changed

- Add an account- and company-scoped conversation list endpoint with the
existing access checks, feature gate, and OpenAPI entry.
- Add the live secondary sidebar, landing page, avatars, search, loading
states, errors, and retry controls.
- Make the agent picker wait for chat creation and display failures.
Existing agents reopen the same conversation. A dismissed selection
cannot close a reopened picker or navigate over a newer choice.
- Preserve recent-activity ordering and terminated agents’ chat history.
Scope live list refreshes to the current user’s conversation events. A
failed historical-agent lookup leaves healthy chats usable and offers a
focused retry.
- Keep the sidebar and header stable across chat routes. Keep mobile
selection in the navigation drawer.
- Use the production components in Storybook. Prepare the theme and
mobile viewport before mounting the page to avoid the startup flash.
- Update product documentation, the design guide, and navigation tests.
Replace old browser expectations for stars and recent shortcuts with
persistent conversation and layout coverage.

## Verification

- `pnpm -r typecheck`, `pnpm build`, and `pnpm check:token-gates` pass
after rebasing onto master.
- Focused UI tests pass, including 105 sidebar, picker, and live-update
checks after review fixes. The 33 conversation service and route tests
and 10 OpenAPI checks pass, including ownership, feature gating, and
concurrent creation.
- The full local test run passed 14,163 server tests before three
environment or timeout failures. The embedded Postgres startup,
connector socket, and native runner failures all passed direct reruns.
- Browser test-drive verification covers a real provider reply, add and
reopen, persisted history after reload, no-match search recovery, mobile
drawer dismissal, and top-aligned context panels.
- Browser measurements confirm that the sidebar has the same position
and dimensions on the landing page and an agent conversation.
- Storybook builds and its add-and-reopen interaction passes.
- The revised browser regression passes locally against a freshly built
throwaway instance. It covers stable sidebar geometry, add/reopen
uniqueness, drafts, search, history, and terminated-agent history after
reload. The full CI browser suite also passes.
- Latest commit `b323577d9523180104df4000eaceedea2772608c`: all 54
completed checks pass, including the complete server/workspace/browser
suites, aggregate verification, build/typecheck, security scans, and
canary packaging. The two Storybook jobs are skipped by their workflow
conditions. [CI
run](https://github.com/paperclipai/paperclip/actions/runs/36714052050).
- Greptile reviewed this same commit at 5/5 with no remaining actionable
findings; all review threads are resolved.
- Reviewer path: enable Agent Chat, click Chat, use plus to choose an
agent, send a message, switch away, and reopen that agent. One
conversation must remain, with its history intact.

## Risks

- The new sidebar lists persistent conversations instead of starred and
recent shortcuts.
- Chat creation is asynchronous. Errors stay visible in the picker, and
delayed responses cannot navigate into a previous company or account.
- The shell adjustment is limited to chat routes and preserves the
existing conversation implementation.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, and browser
tools. The session does not expose the exact API model ID or
context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#123` / `Refs #123` 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-30 07:35:32 -05:00
DottaandPaperclip 81a52eb740 fix(ui): allow touch scrolling in new-task pickers (#14599)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The new-task composer lets users select an assignee and override its
model.
> - On phones, these selectors open as large sheets outside the task
dialog DOM.
> - The parent dialog's scroll lock cancels touch drags in those sheets.
> - This pull request gives each mobile sheet its own modal scroll
boundary.
> - Users can scroll to an option, select it, and continue editing their
task.

## Linked Issues or Issue Description

**What happened?**

An iPhone Safari user could not drag through the assignee or model list
in the new-task composer. The list stayed at the top. A touch-enabled
Chromium reproduction also showed canceled touchmove events and an
unchanged scroll position.

**Expected behavior**

A finger drag scrolls the list. A tap selects an option. Closing the
picker preserves the task draft and selected values.

**Steps to reproduce**

1. At phone width, open New Task in a company with enough agents to
overflow the picker.
2. Open Assignee and drag upward through the list.
3. Select a Codex agent, open Codex options, choose Custom, and open the
model selector.
4. Repeat the drag with enough models to overflow the available
viewport.

**Paperclip version or commit**

Reproduced on `e5bf9d49a`. The fix is rebased onto `b3eb03fcb`.

**Deployment mode**

Local development in an isolated test instance. The user reported iPhone
Safari. Browser automation uses native Chromium touch input at phone
dimensions; a physical iPhone was not available.

Related: #14250 introduced the large mobile entity picker sheets.
Duplicate search found no existing fix for their touch scroll boundary.

## What Changed

- Use modal Radix popovers for mobile entity sheets. Their lists can
scroll while the background stays locked.
- Suppress opening when Radix restores trigger focus after dismissal.
Escape and outside taps now close the picker without reopening it.
- Add a failing-before/fixed-after regression for a mobile sheet inside
a parent dialog.
- Add a browser test for native touch scrolling in both lists, tap
selection, draft retention, close-button/Escape/outside dismissal, and
desktop mouse/keyboard selection.
- Document the browser test command.

## Verification

- Passed `pnpm -r typecheck`, `pnpm build`, and `pnpm
check:token-gates`.
- Passed 41 focused tests for `InlineEntitySelector` and
`NewIssueDialog`.
- Passed the new browser test against a disposable instance running this
worktree. It uses 22 real fixture agents and a fixed 24-model catalog.
It covers 390×844 and 390×430 phone viewports and a 1280×900 desktop
viewport.
- Inspected the rendered new-task form and both selectors. Selections
returned to the draft with its title intact.
- `pnpm test:run` was attempted and stopped after confirming that local
database suites were skipping because macOS has exhausted its system
semaphore limit (`initdb`: `could not create semaphores: No space left
on device`). It did not complete locally. The complete test matrix
passed in Linux CI, including all 71 tool-gateway tests.
- All 150 browser tests passed in CI, including the new native-touch
regression.
- Greptile reviewed the latest commit at 5/5. Its desktop focus finding
is fixed and the review thread is resolved. All checks on
`2ab22727ca768b4134c9c840bbc8e4c80d7da674` are complete: 53 passed, 2
intentionally skipped Storybook deployment checks, and the Snyk status
passed.

## Risks

Low risk. Mobile selectors now own focus and scroll isolation. This
changes their modal behavior, so the tests cover nested dismissal and
focus return. Desktop selectors remain non-modal. No schema, API, or
dependency changes.

## Model Used

OpenAI Codex (GPT-6), with reasoning, repository inspection, code
execution, and browser testing. The exact backend deployment 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-29 13:37:03 -05:00
DottaandPaperclip 29c8fb0b66 fix(composer): match effort options to adapter execution (#14576)
## Thinking Path

> - Paperclip is an open source control plane for AI agents.
> - The issue composer lets operators choose a model and effort for a
task message.
> - The picker must show only effort levels that the selected adapter
can execute.
> - The Codex Runner fix in #14568 exposed similar gaps in other
adapters.
> - Grok hid a supported control. Claude used one range for all models.
Kimi ACP showed a control that it ignored.
> - This pull request aligns the picker with each adapter and adds
matching stories.
> - Operators can see and save supported effort settings without false
controls.

## Linked Issues or Issue Description

**What happened?**

The composer hid Grok effort. It showed an incomplete effort range for
some Claude models and a slider for Claude Haiku. It showed Kimi effort
on the default ACP engine even though that engine drops the value.

**Expected behavior**

The composer should show only effort levels supported by the selected
model and execution engine. Grok effort should reach its adapter as
`reasoningEffort`.

**Steps to reproduce**

1. Select a Grok agent and `grok-4.7`. Observe that the picker has no
effort slider.
2. Select Claude Sonnet 5 or Haiku 4.5. Observe the generic low to high
slider.
3. Select a Kimi agent on ACP. Observe the slider even though ACP
ignores effort.

Related fix: #14568.

## What Changed

- Use Claude and Grok adapter capability helpers in the production
picker and Storybook preview.
- Map Grok composer effort to `reasoningEffort` in per-message
overrides.
- Show Kimi effort only when its agent uses the CLI engine, including
when it runs its default model.
- Show Grok effort when it runs its default model.
- Add design and production stories for Claude, Grok, and Kimi ACP and
CLI cases.
- Document the picker rules and add focused tests.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat/composer-run-settings.test.ts`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm check:token-gates`
- `pnpm -r typecheck`, `pnpm test:run`, and `pnpm build` passed on the
first commit.
- The focused test, UI typecheck, token check, and Storybook build
passed again after the review fixes.
- Browser smoke: production stories show effort for default Grok and CLI
Kimi, and hide it for ACP Kimi and Claude Haiku.

## Risks

- Existing Kimi ACP agents lose a slider that could not change
execution. Their stored effort override remains unchanged until the next
edit.
- Claude and Grok ranges follow their adapter catalogs. A provider can
change model support before the catalog is updated.

## Model Used

OpenAI Codex based on GPT-6. The exact runtime model ID and context
window are not exposed in this session. Reasoning, tool use, and code
execution were used.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-29 10:34:29 -05:00
da887ea3e9 fix(runner): honor Codex effort selected in composer (#14568)
## Thinking Path

> - Paperclip manages AI agents that work on assigned tasks.
> - The task composer lets a person choose an assignee, model, and
effort for the next run.
> - A Paperclip Runner agent can use Codex as its provider.
> - The composer hid Codex effort for that agent because it checked only
the older Codex adapter.
> - The native Runner input also did not carry an effort choice to
Codex.
> - This pull request carries the chosen effort from the composer to
each Codex turn.
> - People can now select a supported effort and get the effort they
selected.

## Linked Issues or Issue Description

Refs #14322

**What happened?**

The composer showed a model but no effort slider when the assignee used
Paperclip Runner with the Codex provider. A task-level model override
also did not reach the native Runner input.

**Expected behavior**

The composer shows effort choices for a known Codex model. The next
native Codex turn uses the selected model and effort.

**Steps to reproduce**

1. Open a task composer.
2. Select an agent that uses Paperclip Runner with the Codex provider.
3. Select a known Codex model such as `gpt-6-astra`.
4. Open the assignee and model picker. The effort slider is missing
before this change.

## What Changed

- Show known Codex effort levels for Paperclip Runner Codex assignees.
- Save the task effort override in the native run input and send it to
Codex on each turn.
- Apply the task's merged model and effort overrides when the native run
starts.
- Apply a task model override for OpenCode Runner without changing the
agent's provider.
- Add Runner effort tests and desktop and mobile Storybook cases.

## Verification

- `pnpm -r typecheck` passed.
- `pnpm build` passed.
- `pnpm build-storybook` passed.
- `pnpm check:token-gates` passed.
- Focused UI, server, Runner contract, and Codex driver tests passed.
- The full CI test matrix, build, typecheck, and canary dry run passed
on the latest head.

## Risks

- Native Runner inputs add an optional Codex effort field to the current
v5 input. Older inputs keep their previous behavior.
- A known model rejects an effort that its catalog does not support.
Unknown models do not show a slider.

> This fixes an existing composer bug. I checked `ROADMAP.md`; it does
not describe this bug as planned work.

## Model Used

OpenAI Codex, GPT-6. The exact deployment ID and context window are not
exposed in this session. The model used reasoning, code execution, and
repository tools.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: OpenAI GPT-6 Astra <noreply@openai.com>
2026-09-29 09:41:05 -05:00
DottaandPaperclip 61b3fd57a6 fix(ui): recover gracefully during server restarts (#14560)
Show a clear reconnecting state during server restarts and retry safe access
checks every five seconds. Preserve open drafts, wait for initial startup
readiness, and keep authentication failures separate from temporary outages.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-29 08:31:05 -05:00
Devin FoleyandPaperclip 53aad90b9e fix: retry sandbox ACP input delivery after gateway failures (#14485)
## Thinking Path

> - Paperclip coordinates agent work through execution adapters.
> - Sandbox ACP sessions send ordered input through a remote file queue.
> - A temporary provider 502 currently closes the session during an
input upload.
> - A lost response can occur after the sandbox has consumed the
message, so a blind retry can duplicate input.
> - This pull request retries gateway failures with the same sequence
and drops consumed sequences at the receiver.
> - The session can continue through a brief provider failure without
repeating a tool call.

## Linked Issues or Issue Description

**What happened?**

A sandbox ACP run can fail with `ACP agent disconnected during request
(connection_close, exit=null, signal=null)` when a provider input upload
returns HTTP 502. The bridge destroys its local socket on the first
failure and can discard the diagnostic before the proxy reads it.

**Expected behavior**

A temporary gateway failure should get a bounded retry. A lost response
after successful delivery must not duplicate input or reorder later
messages. Permanent failures must still close the session.

**Steps to reproduce**

1. Run the real sandbox process bridge with an echo child and a local
test runner.
2. Inject a provider 502 before preparation, after a chunk upload, or
after final publication and consumption.
3. Send the next input message. Before this change, the connection
closes instead of delivering it.

Searched open and closed PRs for `ACP disconnect`, `bridge retry`, and
`502 sandbox`. Related work: #13287 covers shutdown after bridge loss;
#13793 covers large launch envelopes. This change covers ordered input
delivery within a running legacy ACP session.

## What Changed

- Retry input uploads up to three times for recognized Daytona and
Cloudflare HTTP 502, 503, and 504 diagnostics, with 250 ms and 500 ms
delays.
- Give each upload separate temporary paths and discard already-consumed
input sequences, including late publication from an earlier attempt.
Clean failed attempts in the background without removing a published
message or another attempt’s files. Cleanup cannot delay retries or
shutdown.
- Keep later input behind the retry. Stop queued input on permanent
failure and flush a fixed diagnostic before closing the socket. Neither
failure-diagnostic persistence nor shutdown-warning persistence can
block teardown.
- Add real-process regression tests for lost responses, late
publication, retry exhaustion, immediate permanent failure, and
diagnostic redaction.
- Give accepted run-log file appends up to three seconds to drain before
finalization computes the size, hash, and durable copy. Close the run
handle to later appends. This waits only for file writes, independently
of later DB progress or live-event persistence. If writes remain
stalled, return null size/hash metadata and skip the final durable copy
so the run can settle. Late writes cannot restart mirroring.
- Preserve legacy comment attribution when final log size is unknown by
reading existing entries within the unchanged 2 MB scan limit. Storage
errors or a three-second read deadline return the evidence already read
instead of failing the comment listing; pagination stops at the
deadline. The deadline requests cancellation of the underlying local
stream or S3 HEAD, GET, and response stream. A separate response timeout
returns partial evidence even when filesystem I/O delays cancellation;
late reads cannot append evidence or start another page. Each listing
retains its existing batches of eight reads, without a shared admission
cap that skips readable logs under contention.
- Document the retry and log-finalization boundaries in the development
guide.

## Verification

- Final commit `347daa564b`: [Linux
CI](https://github.com/paperclipai/paperclip/actions/runs/36506995168/attempts/2)
passed. Greptile Apex review 13 scored this commit 5/5 with no new
findings; all 12 review threads are resolved.
- The final CI run initially hit a Cursor test timeout and four Discord
credential-lock contention failures. All five cases passed in isolation.
The two failed shards and their aggregate gate passed on retry without a
code change. Those intermittent failures are not claimed fixed by this
PR.
- `pnpm --filter @paperclipai/adapter-utils typecheck` passed.
- `pnpm exec vitest run
packages/adapter-utils/src/execution-target-stdin-race.test.ts
packages/adapter-utils/src/execution-target-sandbox.test.ts
packages/adapter-utils/src/sandbox-callback-bridge.test.ts`: 262 tests
passed on the final implementation, including 21 new regressions. The
original three fault-injection cases failed before the fix.
- The regressions cover failed and indefinitely stalled cleanup,
Cloudflare gateway responses and retry exhaustion, permanent errors that
must not retry, and teardown while failure logging remains indefinitely
stalled. Seven Apex regression cases failed before the review fixes.
Adapter-utils typecheck and build passed again after the final review
change.
- `pnpm exec vitest run server/src/services/run-log-store.test.ts
server/src/services/run-log-store-cancellation.test.ts`: all 25 tests
passed, including four new regressions that failed before the
finalization fix. They cover delayed and failed appends, late-write
admission, agreement between the local bytes/summary/durable copy, and a
stalled append that exhausts the three-second budget. The timeout case
verifies unknown metadata, no final upload, and no mirror restart after
late completion. New cancellation tests use the real AWS SDK against a
local HTTP server. They verify that stalled HEAD, GET, and response-body
connections close on abort and that a subsequent read succeeds. Local
range and already-aborted read cases also pass.
- `pnpm exec vitest run server/src/__tests__/issues-service.test.ts -t
'readIssueCommentRunLogText|deriveIssueCommentRunLogAttribution'`: 14
targeted tests passed. The null-size reader case, both storage-error
cases, the stalled-read case, and the cancellation/concurrent-listing
cases failed before their fixes. The new regressions verify that
timed-out reads are cancelled, subsequent listings recover, and two
concurrent listings both retain their attribution markers. A read that
ignores cancellation still returns partial evidence at three seconds and
cannot resume pagination when it finishes; this regression failed before
the response-timeout fix.
- `pnpm --filter @paperclipai/server typecheck` and `pnpm --filter
@paperclipai/server build` passed after the response-timeout change.
- Full `pnpm -r typecheck` and `pnpm build` passed earlier in this PR;
the affected packages were rechecked after review fixes.
- Full local `pnpm test:run` failed in the general-server group: 511
files passed, 40 failed, and 158 were skipped. Failures include embedded
PostgreSQL initialization, read-only cache directory renames, a macOS
long-path fixture, and a workspace exposure assertion. The PostgreSQL,
cache-permission, and long-path failures also reproduce with both
changed implementation files restored to baseline commit `24c58e479a`.
The exposure suite passes in isolation both on baseline and the fixed
branch (28 passed, 3 skipped). CI runs the full suite on Linux. Later
local test groups were not reached.
- An earlier CI run hit the Telegram retry-timing failure fixed upstream
in #14501. The branch includes that master fix. The selected recovery
test passed against a fresh, migrated PostgreSQL 16 database. The
embedded PostgreSQL runner is unavailable on this Mac; the isolated
database was stopped and removed afterward.
- No live agent turn was replayed. The tests use local child processes
and injected provider failures.

## Risks

Retries are restricted to recognized Daytona SDK and Cloudflare bridge
gateway-error messages, which survive plugin RPC serialization. Other
errors fail immediately. Temporary upload paths are now unique for all
command-managed queue writes. Receiver sequence checks prevent duplicate
input; retries do not restart an agent turn. Cleanup and failure logging
are nonblocking and best effort; session teardown remains the final
cleanup boundary. Log finalization now drains accepted local file writes
for at most three seconds and ignores later appends on the closed run
handle. A timeout leaves final size/hash unknown and skips the final
durable upload; an existing partial mirror may remain available, but it
is not claimed as a verified final snapshot. It does not wait for later
DB progress or live-event persistence. Optional attribution keeps
partial evidence when a read fails or times out. Cancellation closes S3
requests and response streams. Local filesystem I/O may finish after the
caller deadline, but a late read cannot change the returned evidence or
continue pagination. Later listings can retry after storage recovers.
There is no schema, authentication, or permission change. Revert this
commit to restore the previous behavior.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, repository inspection, code
editing, and local test execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-28 19:15:33 -07:00
Devin FoleyandPaperclip ea371b9684 fix: retain project defaults in partial workspace overrides (#14502)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Project workspace policies define how isolated worktrees are set up.
> - Tasks can override a branch without providing every setup field.
> - The resolver currently replaces the entire project strategy with
that partial override.
> - Losing an explicit setup command can run the repository fallback
script and block the task.
> - This pull request keeps enabled project defaults when the task uses
the same strategy type.

## Linked Issues or Issue Description

**What happened?**
A project uses `git_worktree` with `provisionCommand: "true"`. A task
overrides only `baseRef`. The resolver drops the command. Worktree
creation then invokes `scripts/provision-worktree.sh`, which can fail
because its required setup is absent.

**Expected behavior**
A branch override keeps the project's provision, runtime provision, and
teardown commands unless the task explicitly overrides them. A different
strategy type must not inherit those commands.

**Steps to reproduce**
Configure the project with an enabled `git_worktree` strategy and
`provisionCommand: "true"`. Give the task an isolated workspace with a
`git_worktree` strategy and a different `baseRef`. Add a failing
repository fallback provisioner. Before this change, worktree creation
invokes that script. After this change, it uses the project's explicit
command and succeeds.

Related: #4968 concerns agent strategy and working-directory fallback.
#13903 concerns gated API fields and reusable-workspace updates. #11091
concerns provision hooks on workspace reuse. None fixes partial task
overrides discarding project defaults.

## What Changed

- Merge a partial task strategy over the enabled project's strategy only
when their types match.
- Preserve explicit null values when parsing nullable strategy fields,
so they can clear project values.
- Keep explicit empty-string overrides and agent fallback behavior.
- Exclude disabled project strategies and avoid an inherited branch
template when a task pins an existing branch.
- Add policy regression coverage and a real Git worktree test with a
failing fallback script.
- Document inheritance, explicit clearing, and no-op provisioning in the
development guide.

## Verification

- Policy regression: eight failures before the fix; all 41 policy tests
pass after it.
- Real worktree regression: passes and creates a worktree using the
task's base branch without invoking the failing fallback provisioner.
- `pnpm -r typecheck`: passed.
- `pnpm build`: passed.
- `pnpm test:run`: general-server phase completed with 13,873 passed, 86
skipped, and 14 failures in unchanged macOS skills-cache and Git
long-path tests. The same failures reproduce on unmodified base code.
The command stops at that phase, so no full local pass is claimed.
- CI initially failed the existing Telegram subscription recovery test
on a 15-second timeout. The separate fix and investigation are in
#14501. A serialized job also lost its runner; GitHub reported lost
communication, and that job was rerun without source changes. All 52
final-commit checks pass, with two intentional skips. Greptile is 5/5,
with no unresolved comments or merge conflicts. The chat shard passed on
one unchanged rerun. The timeout cause remains unproven; #14501 adds
phase diagnostics for a recurrence.

## Risks

Tasks that specify a partial strategy now retain the project's omitted
fields, including setup and teardown hooks. This is the intended
behavior change. Inheritance requires an enabled project policy and
matching strategy types. Explicit task values still win. Null and empty
commands restore existing runtime defaults; they do not guarantee that
no script runs. Use `"true"` for an explicit no-op provision command. No
migration, live configuration change, or task replay is included.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, terminal tools, and code
execution. The context window size is not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes:` / `Closes`
/ `Refs` OR (b) described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub references)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run focused tests locally and they pass; full-suite status
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-09-28 18:09:20 -07:00
Devin FoleyandPaperclip faf72cb1d5 fix: preserve company context across browser hot reload (#14482)
## Thinking Path

> - Paperclip uses a shared company context for browser providers and
consumers.
> - Vite can load a new consumer module while an older provider is
mounted.
> - Recreating the context disconnects that consumer from the mounted
provider.
> - The consumer then reports a missing provider even though one is in
its React ancestry.
> - This change preserves the context object across development module
refreshes.
> - Bounded global error diagnostics distinguish development bundles and
otherwise context-free promise rejections.

## Linked Issues or Issue Description

**What happened?**
A refreshed company consumer can throw `useCompany must be used within a
CompanyProvider`. A real Vite and Chromium reproduction confirms that a
retained provider and a refreshed consumer can hold different context
objects. Global promise rejections also lack the bounded document state
already attached to React boundary errors.

**Expected behavior**
A refreshed consumer should read the mounted provider. Error reports
should identify the loaded bundle mode and bounded browser state while
preserving monitoring opt-in, sign-out, and privacy behavior.

**Steps to reproduce**
Run `pnpm test:e2e:browser-context`. The isolated Vite fixture renders
the real CompanyProvider, imports a new timestamped consumer module, and
renders that consumer below the retained provider. The test fails before
the context change and passes after it. The SDK regression invokes its
real unhandled-rejection handler with an undefined reason.

## What Changed

- Keep the React context object in Vite's per-module `hot.data`. Account
values stay in React.
- Add an isolated browser regression with mocked API responses and no
live instance, discovered by the existing Chrome CI shards.
- Add document-state diagnostics to global errors while preserving
earlier boundary snapshots.
- Tag events with development or production bundle mode and the type of
an unhandled rejected value.
- Document the new test command and diagnostic fields.

## Verification

- Company context, browser context, and Sentry suites: 59 passed.
- `pnpm test:e2e:browser-context`: passed in Chromium. The original
context code fails the reproduction.
- Real SDK tests preserve DSN/sign-out behavior and omit request
context, breadcrumbs, and private DOM data.
- `pnpm check:token-gates`: passed.
- `pnpm -r typecheck`: passed.
- `pnpm build`: passed.
- Local `pnpm test:run` exited in the general-server phase: 13,819
passed, 86 skipped, 21 failures in unchanged filesystem and host-port
suites. Cache permission and long-path failures also reproduce on the
unmodified base; seven other failures involve local runtime port
ownership. This is not a full local pass.
- Full Linux CI and review passed at a0b5270662 (53 successful checks;
two conditional checks skipped). Three jobs interrupted by a runner
shutdown passed on rerun. Greptile is 5/5 with no unresolved comments.
The real browser regression also passed in the normal Chrome CI shard
(3.2 seconds).
- Code-owner approval remains required because the dedicated test
command changes `package.json`.
- Scanned the diff and PR text for credentials and private data before
pushing.

## Risks

The context cache applies only to development hot reload. It retains the
context object, not account state. Production continues to create an
ordinary React context. The diagnostic hook adds only bounded state and
type values, preserves boundary snapshots, and returns the original
event if enrichment fails. It does not suppress errors or restore raw
breadcrumbs. The global rejection diagnostics do not identify the
promise's originating operation by themselves.

## Model Used

OpenAI GPT-6 through Codex, with repository inspection, code editing,
and command execution. The runtime does not expose a more specific model
revision or context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-28 16:15:14 -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 270afd2fb8 feat(ui): show running commit in staging account menu (#14410)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The account menu shows the signed-in user's identity.
> - Staging users need to know which server commit is running after a
deploy.
> - The health endpoint already returns that commit, but the menu does
not show it.
> - This pull request adds the short commit below the email on staging
hosts.
> - Users can open the menu to check a deploy without opening deployment
tools.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The account menu on staging instances.

**Current behavior**

The menu shows the user's name and email. It does not show the running
server commit.

**Proposed behavior**

On `*.staging.paperclip.app`, show `SHA 8751e2d` below the email. Use
the current `/api/health` commit. Show the full SHA on hover and link to
the commit on GitHub. Refresh the health query when the menu opens. Hide
the label on other hosts and when commit metadata is unavailable.

**Reason and benefit**

A user can confirm which commit a staging instance runs after an
automatic deploy.

**Breaking changes**

None. The server already returns the commit field.

Refs #14060 for related account-menu work. This change adds deployment
information only.

## What Changed

- Add the existing health response commit field to the UI type.
- Share the staging host check and a separate health query across both
account-menu variants. A menu refresh failure leaves the access gate
health state unchanged.
- Show a short SHA below the email. Link to the full commit on GitHub
and include the full SHA in its accessible name and hover title.
- Document the staging label and cover staging hosts, other hosts,
missing metadata, refresh on reopen, and request failure isolation.

## Verification

- `pnpm exec vitest run ui/src/components/SidebarAccountMenu.test.tsx` —
24 tests passed.
- `pnpm check:token-gates` — passed.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed. The UI build and typecheck also passed again
after review fixes.
- Full test matrix — passed on the latest commit in
[CI](https://github.com/paperclipai/paperclip/actions/runs/36447810742).
The local `pnpm test:run` was stopped before completion after CI
finished the same suites. The focused local tests, full local typecheck,
and full local build passed.
- Browser shard 6 passed on one rerun. Its first attempt lost part of
the draft text in the existing attachment-receipt reload test. No code
changed for the rerun.
- Rendered the real account menu in a local browser fixture with a
staging hostname condition and mocked health response. Confirmed the SHA
fits below the email in the dark menu.
- Greptile review — 5/5, all review threads resolved.
- Manual check after deployment: open the menu on a staging host and
compare the SHA with `/api/health`. Open the menu again after a deploy
to refresh it. Confirm the label is absent on production and localhost.

## Risks

- Low risk. Each menu opening on staging can make one additional health
request.
- The host check applies to `*.staging.paperclip.app`. Other staging
domains will need an explicit update.
- The label identifies the running server commit. It can briefly show
cached data while the request completes.

## Model Used

OpenAI Codex, GPT-6. The exact model variant and context window are not
exposed in this session. Used code execution, repository inspection, and
browser inspection.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#123` / `Refs #123` 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 13:43:30 -05:00
Devin FoleyandPaperclip e9debd3eac fix(workspaces): allow larger status output for readiness checks (#14414)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server checks workspace contents before it allows cleanup or
branch reconciliation.
> - These checks need the full Git status output to count untracked
files.
> - Nested task worktrees can make this output exceed the scheduler's
default 1 MiB limit.
> - A scan failure then blocks an otherwise inspectable workspace.
> - This pull request raises the limit for these status checks to 32
MiB.
> - The checks retain exact counts and still protect uncommitted work
from cleanup.

## Linked Issues or Issue Description

Refs #14194 and #14253. Those changes address snapshot enumeration. This
PR addresses buffered execution-workspace status checks. Refs #13619 for
separate work on caching these checks. The related journal identity
failure is covered by #14312.

**What happened?**

Close-readiness checks failed when Git status output exceeded 1 MiB. A
workspace with thousands of long untracked paths could not report its
file count or complete readiness inspection.

**Expected behavior**

Allow up to 32 MiB of status output for execution-workspace readiness
and branch reconciliation. Preserve exact counts. Continue to block
cleanup when the workspace has uncommitted data or the scan exceeds its
bound.

**Steps to reproduce**

1. Create an execution workspace with a merged delivery.
2. Add 5,000 long untracked filenames under a nested task directory. The
status output exceeds 1 MiB.
3. Request close readiness. Before this fix the status scan fails. After
this fix it reports all 5,000 files.
4. Run the terminal-workspace sweep. Confirm that it preserves the
workspace and files.

**Paperclip version or commit**

Reproduced on master at `14795136f5` before this fix.

**Deployment mode**

Server with managed Git workspaces.

## What Changed

- Set a 32 MiB stdout bound for execution-workspace status scans.
- Add a real Git regression with 5,000 long untracked paths and a
cleanup-preservation assertion. Assert that the measured status output
exceeds 1 MiB.
- Document the bound and failure behavior.

## Verification

- The new regression failed on master before the service change: the
status result had no untracked files or count after the scan exceeded
its bound.
- `pnpm exec vitest run
server/src/__tests__/execution-workspaces-service.test.ts
server/src/services/workspace-git-operation-scheduler.test.ts` passed:
82 tests, including the new regression. The regression and server
typecheck also passed after the explicit byte-count assertion.
- `pnpm build` and `pnpm -r typecheck` passed. The full local `pnpm
test:run` was attempted and stopped after the failures listed below.
Greptile is 5/5 with zero unresolved review threads on the latest head.
All checks for head `45f93ad5ad` passed (53 successful, two intentional
skips).
- Full local validation did not pass. The attempt reproduced 13
company/runtime skill-cache permission failures, the terminal-workspace
cleanup assertion, and a heartbeat feedback timeout. It was stopped
during the general-server stage after these failures. Remaining
general-server tests, other workspace groups, and serialized-server
stages did not complete locally. Earlier clean-master checks reproduced
the cache failures and isolated cleanup retries passed. The latest-head
GitHub suite passed all of these groups.
- One GitHub browser shard initially failed because its
GitHub-connection test checked the resume-action array before the mocked
request completed. The single failed-job retry passed without a source
change. All latest-head checks are green.
- No browser suites ran locally. This change does not affect browser
behavior.

## Risks

- Each active status scan can buffer up to 32 MiB before parsing. The
existing scheduler bounds scan concurrency and queue size.
- Output above the bound still fails the scan and blocks destructive
cleanup. The change does not truncate output or change cleanup rules.
- There are no API, database, or snapshot-streaming changes.

## Model Used

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-28 09:59:56 -07:00
DottaandPaperclip 4b38db9622 fix(runtime): stream workspace Git snapshots through disk manifests (#14253)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Managed runs copy a selected workspace to an execution environment
and restore its changes.
> - Git snapshots select the files for that copy and for later recovery.
> - A fixed output limit stops large generated trees before the run can
start.
> - Increasing the limit still keeps the complete filename lists in
memory.
> - This pull request stores those lists and merge baselines in disk
manifests.
> - Large snapshots can now complete with bounded filename buffers and
explicit failure handling.

## Linked Issues or Issue Description

Refs #14194. This is the streaming follow-up to the merged 32 MiB limit
fix.

Related: #13619 and #11621 cover workspace scan admission and demand.
This change keeps the shared scheduler and changes the snapshot data
path.

## What Changed

- Stream changed, untracked, deleted, and ignored paths through the
shared scheduler and the standalone adapter path.
- Use SQLite manifests for file selection, duplicate removal,
ignored-path lookup, baseline capture, and merge lookup.
- Set a configurable 30-minute snapshot deadline. Keep the existing
interactive scan deadlines.
- Wait for each child process and pending sink write before removing
temporary storage after failure or cancellation.
- Use NUL archive lists and bounded deletion batches. Preserve unusual
names, explicit selection, nested repositories, and source root checks.
- Store manifest references in native recovery format v2. Check their
location and digest before recovery reads. Keep v1 descriptors readable.
- Remove temporary manifests at lifecycle completion. Use fixed-size
temporary copy names for long basenames.
- Admit each manifest with a SQLite page allowance based on current disk
capacity. Keep a configurable free-space reserve and fail explicitly
when either limit is reached.
- Preserve a host file that replaces a directory deleted by the sandbox,
and continue the rest of the restore.

## Verification

- Current head `5ab622ec43cd16d35429d79dedee6a5d8e3d2df2` has 54
successful checks/statuses and two skipped Storybook jobs. No checks
failed or remain pending.
- [CI
passed](https://github.com/paperclipai/paperclip/actions/runs/36318966368):
typecheck, build, all test shards, E2E, Rust checks, and the aggregate
verify job.
- [Greptile is
5/5](https://github.com/paperclipai/paperclip/pull/14253#issuecomment-5855670338)
on the current head. All four review threads are resolved. Security
checks passed.
- 229 focused tests passed across Git sync, runtime staging, merge,
manifest integrity, native recovery, and the scheduler (214
adapter/runtime tests and 15 scheduler tests).
- A real 40,000-file fixture produces 43,428,890 filename bytes. The
original standalone and scheduled scans fail. The new test passes all
four filename paths, complete staging, exclusion of late files, unusual
names, and deletion replay.
- Recovery tests reject changed bytes, symlinks, and paths outside the
controller state directory. Adapter-utils typecheck passed.
- A test executor returned buffered output and caused two retry
integration failures. The fixture now uses the shared streaming
scheduler. All 13 tests passed with `corepack pnpm exec vitest run
server/src/__tests__/heartbeat-project-repositories.test.ts`. The same
CI shard now passes.
- Ran `pnpm -r typecheck`, `pnpm test:run`, and `pnpm build` locally.
Each full local command hit SIGKILL/exit 137 in the 4 GiB container.
These local commands did not pass. The current-head CI gates above
provide the full verification.
- A real-Git disk-capacity regression confirms a typed failure and
removal of the incomplete manifest. Repeated writer attempts cannot
exceed the permitted page count.

- Follow-up real Daytona and separate staging qualification passed with
the related archive validator (#14315) and exact-owner finalization fix
(#14314). Three successive turns copied back all 60,000 files with
39,828,890 filename bytes and five unusual names. Independent host
inventories verified every file and the pinned Git HEAD. Native,
provider, session, and process identities stayed fixed; no retry
remained. The task reached Done, and its browser-downloaded final proof
matched exactly. The reusable regression is #14316, including an
assertion of the effective environment idle policy.

## Risks

- SQLite manifests use disk space. Each receives one quarter of the
available capacity above the host reserve at creation. The reserve
defaults to 256 MiB and has a 64 MiB configuration minimum. Disk
capacity, filesystem quotas, per-path limits, Git resource use, and
execution deadlines remain limits.
- Each path and sink chunk has a 64 KiB limit. SQLite connections use a
1 MiB page cache. Invalid or incomplete records fail explicitly.
- Restore transport keeps fixed and configured archive exclusions. A
remotely created Git-ignored file can be transferred, but the host merge
excludes it through the manifest.
- Provider archive buffers, Git and tar memory, repository metadata,
legacy v1 arrays, and the separate referenced-source resolver retain
their own limits. Existing provider safety validators still buffer
textual tar listings: Daytona allows 32 MiB and Kubernetes allows 64
MiB. These separate transport limits can stop a sufficiently large
restore before merge. This change does not claim bounded total process
memory or unlimited transport size.
- New descriptors use v2. Existing v1 recovery remains supported; a
downgrade cannot read v2 descriptors.

## Model Used

OpenAI GPT-6 through Codex. The exact deployment ID and context limit
are not exposed in this run. The agent used code editing, terminal
execution, tests, and GitHub tools.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-28 08:40:36 -05:00
DottaandPaperclip 0f14d26123 fix(runtime): allow bounded large untracked workspace snapshots (#14194)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Remote runs need a snapshot of the task workspace before the agent
starts.
> - The snapshot lists untracked filenames through the shared Git scan
scheduler.
> - A generated directory with a few thousand long filenames can exceed
the 1 MiB output limit.
> - This stops setup and prevents the agent from continuing its task.
> - This change gives that listing a 32 MiB bound and keeps the explicit
file snapshot.
> - Normal generated trees can now pass setup, while larger snapshots
still fail at a finite limit.

## Linked Issues or Issue Description

Refs #11572 and #12214 for the existing bounded scan and ignore-scan
protections.

**What happened?**

An agent continuation failed during workspace setup with `Workspace Git
scan exceeded its output limit`. A real Git fixture reproduces the
untracked-file path: 5,000 long filenames in one generated directory
exceed its 1 MiB output limit.

**Expected behavior**

The workspace snapshot must support ordinary generated trees with
thousands of files. It must keep a finite output bound and select
explicit files before staging.

**Steps to reproduce**

1. Commit a base file in a Git repository.
2. Add 5,000 untracked files with long names in one new directory.
3. Call `readGitWorkspaceSnapshot` with the normal scan limits.
4. Observe the output-limit error before this change.

**Paperclip version or commit**

Base commit: `640dee1`.

**Deployment mode**

Remote sandbox execution from source.

## What Changed

- Increase the untracked-file snapshot output bound from 1 MiB to 32
MiB.
- Keep explicit file selection, the shared scheduler, the timeout, and
the other scan bounds.
- Test that 40,000 long filenames above the old 8 MiB bound reach the
snapshot. Reuse those files with deeper paths to prove that output above
32 MiB still fails.
- Test that files created after the snapshot, including an ignored
secret, stay out of the overlay archive.
- Check the workspace root identity and reject selected paths with
symlinked parent directories before upload.
- Test root replacement after path resolution, including root-level
selected files.
- Preserve existing workspace root aliases by capturing the resolved
root before snapshot selection. Test that later alias retargeting cannot
change the archive contents.
- Stop staging on permission and I/O errors; continue to allow missing
files.
- Test these failures and preserve selected symlink entries.
- Accept valid case-renamed directories by checking ancestor file types.
A modeled case-insensitive regression failed before this correction and
now passes.
- Give the 40,000-file fixture enough time to remove its files.
- Document the larger bound and staging behavior.

## Verification

- Red: the 5,000-file regression failed with `stdout maxBuffer length
exceeded` before the fix.
- A separate check through the real server scheduler reproduced
`workspace_git_scan_output_limit` on the original code. The revised code
selected all 5,000 files.
- The late-file regression failed against the first PR revision because
the archive contained `drafts/late.secret`. It passes with the final
explicit-file approach.
- The staging regressions failed before the review fix: a substituted
parent directory and permission/I/O errors were accepted. All three
cases now stop before upload.
- Green: 134 tests passed across `git-workspace-sync.test.ts` and
`sandbox-managed-runtime.test.ts` with Vitest 4.1.11. This includes
complete selection above 8 MiB and rejection above 32 MiB.
- `pnpm --filter @paperclipai/adapter-utils... typecheck` passed after
the revision.
- The module-boundary check and `git diff --check` passed.
- `pnpm -r typecheck` and `pnpm build` stopped in the Rust runner steps
because this environment has no `cargo` executable.
- The full `pnpm test:run` attempt ended with `SIGKILL` during the
general server suite. It did not finish. That full-suite result belongs
to the earlier revision. Fresh checks are required for this revision.

- The new regression fails at the old 8 MiB bound with `stdout maxBuffer
length exceeded`. All 134 focused tests pass with the 32 MiB change.
- The affected typechecks and module-boundary check pass. The full local
typecheck requires Cargo, which is absent in this environment.
- Final verification for `b43e9bc95e55382c6a9bfe200487c164770c8be8`: 54
successful checks/statuses and two skipped Storybook checks. No checks
remain pending or failed.
- The [CI
run](https://github.com/paperclipai/paperclip/actions/runs/36315569674)
passes on attempt 2. The first attempt had one unrelated preview-fixture
readiness timeout. That exact test passed locally; its CI shard passed
on the single rerun.
- [Greptile reports
5/5](https://github.com/paperclipai/paperclip/pull/14194#issuecomment-5852045501)
on this revision. All review threads are resolved.
- [Security review accepts the documented memory
tradeoff](https://github.com/paperclipai/paperclip/pull/14194#discussion_r4115149465)
for this finite mitigation. The separate streaming follow-up will remove
full-list buffering.
- This revision also passes affected local typechecks and the
module-boundary check. Full local typecheck/build stop because Cargo is
absent. The full local Vitest attempt was stopped after about 18 minutes
once all remote gates passed; it did not complete locally.

## Risks

- Each untracked-file scan can buffer up to 32 MiB instead of 1 MiB. The
scheduler still limits concurrent scans and execution time.
- Snapshots above 32 MiB still fail with the existing error. Tracked and
ignored-file scan bounds stay unchanged.
- A workspace that replaces a selected path’s parent with a symlink now
fails staging.
- Detailed logs from the reported host were unavailable. The exact
command that exceeded its limit on that host is unconfirmed.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use, and code
execution. The runtime does not expose a more specific model build 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 references)
- [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-09-27 06:42:19 -05:00
Devin FoleyandPaperclip f3a214fe77 Fix relative symlinks in secondary sandbox repositories (#13953)
## Thinking Path

> - Paperclip manages agents and their task workspaces.
> - A task can use several independent Git repositories.
> - Sandbox staging copies secondary repositories from temporary clones.
> - The copy changed relative symlinks into absolute host paths.
> - Those links broke skill discovery and made workspace restore fail.
> - This change preserves link targets while keeping extraction checks
intact.

## Linked Issues or Issue Description

**What happened?**

Staging a secondary repository rewrites a link such as
`.claude/skills/demo -> ../../skills/demo` to an absolute path in a
temporary Git clone. That clone is then removed. The link is broken in
the sandbox, and Daytona refuses the outbound archive during workspace
restore. An agent can finish its turn but still have its run fail during
restore.

**Expected behavior**

Repository links keep their original targets after staging. Links within
a repository remain usable, and changes return to the local checkout.
Unsafe outbound archive links still fail before extraction.

**Steps to reproduce**

1. Create a project with a primary repository and a secondary
repository.
2. Commit a relative skill directory link in the secondary repository.
3. Stage the workspace for sandbox execution and inspect the copied
link.
4. Restore that repository through Daytona. Before this fix, the link
points at a removed host temporary directory and restore rejects it.

**Paperclip version/commit**

Reproduced on `0f8750627f11d855552abce9a837d7f3b67c9ddf` in the
multi-repository sandbox path.

Related: #13442 introduced multi-repository provisioning. #13882 adds
native Grok but keeps legacy adapters; #12991 addresses Grok instruction
isolation and leaves skill staging unchanged. Searches of open/closed
PRs and open issues found no direct fix for this copy behavior.

## What Changed

- Set `verbatimSymlinks: true` when copying secondary Git clones. This
[Node
option](https://nodejs.org/api/fs.html#fspromisescpsrc-dest-options)
preserves the stored link target instead of resolving it against the
temporary source.
- Test directory, file, chained and dangling links after temporary-clone
cleanup. Assert the copied Git checkout remains clean.
- Cover skill-link reads, edits and restore in fresh, warm-adoption and
durable-seed workspace modes.
- Extend Daytona checks for valid relative directory links and rejected
absolute targets.
- Document the staging behavior.

## Verification

- Four regression cases fail without the source fix: one clone test and
three staging modes.
- `pnpm exec vitest run
packages/adapter-utils/src/git-workspace-sync.test.ts
packages/adapter-utils/src/sandbox-managed-runtime.test.ts
packages/plugins/sandbox-providers/daytona/src/plugin.test.ts`: 301
passed.
- `pnpm -r typecheck` and `pnpm build`: passed.
- `pnpm test:run` was started locally, then stopped after the full Linux
CI suite passed. It did not finish locally; this is not a full
local-suite pass.
- Full PR CI: 53 checks passed, two conditional skips, on
`07b30ff298baab327a4e60708ade899935688a3f`. Three server shards were
interrupted by runner shutdowns; the unchanged mobile repository test
timed out waiting for a disabled Save changes button. One same-commit
failed-job rerun passed. Original attempts remain in [run
36036538369](https://github.com/paperclipai/paperclip/actions/runs/36036538369).
- Greptile: 5/5 on the same head, no review threads or actionable
findings.
- Diff scanned for secrets and private identifiers; no matches.

## Risks

Low risk: the production change is one copy option. It preserves
symlinks instead of following or materializing their targets. Daytona
extraction guards, workspace exclusions, authentication and database
behavior do not change.

This prevents corruption in newly staged snapshots. It does not rewrite
an already corrupted warm workspace or durable seed; those need fresh
staging from the source checkout. No live provider run or customer-task
replay was performed. The tests use real Git, filesystem and tar
operations with mocked provider transport.

## Model Used

OpenAI GPT-6 through Codex, with tool use and code execution. The exact
serving model identifier and context-window size are not exposed in this
session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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-24 10:58:49 -07:00
Devin FoleyandPaperclip 6681c71b40 fix(ci): stabilize chat startup and close the initial live-update gap (#13895)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Browser tests check chat state across navigation, reload, and agent
runs.
> - Runtime tests check that a service is ready before Paperclip
publishes its address.
> - CI for #13891 failed in these paths, then passed attempt 3 with the
same code.
> - The browser traces stopped during development asset startup. A
separate sidebar assertion used an unstable focus path through the rich
editor.
> - This PR gives browser tests fresh built assets and a direct keyboard
path to the star button. It adds service-worker reload coverage under
CPU throttling.
> - A later browser failure exposed a real reload race: comments can
change between the first query and the first live subscription. The UI
now refreshes active queries when that subscription opens.
> - Runtime fixtures now have separate registry state and better failure
evidence. The readiness deadline remains unchanged.
> - A later CI run exposed a wall-clock backoff assertion and three
authorization cases sharing one test lifecycle. The PR anchors the
assertion to transport time and separates the cases.

## Linked Issues or Issue Description

Refs #13891. Related runtime ownership and cleanup work: #11791, #11389,
#11278.

Evidence: [original CI run, attempt
3](https://github.com/paperclipai/paperclip/actions/runs/35910335089/attempts/3).
Attempt 3 passed both affected shards without code changes. This PR is
separate from the wake-payload change, which has since merged.

| Failure | Diagnosis and classification |
| --- | --- |
| Sidebar blank page and retry text missing after reload in CI | Both
traces show a blank document before React startup. Vite connects, but
the failing page makes no application API requests. The service worker
forwards the unbundled development module graph. The retry response is
already stored and its process-adapter run succeeded before reload. This
places the failure in browser bootstrap, not wake payload or reply
persistence. The exact reason the development module graph stopped is
not established by the retained trace. The harness now serves built
assets, and the new test covers startup and controlled reload at 4x CPU
throttling. |
| Star opacity remains zero on macOS | Reproduced on unchanged master
`f55759942b`. The old test clicked the rich editor, focused the star,
then used Tab and Shift+Tab. An instrumented baseline run captured the
sequence: Tab moved from the star to the next sidebar link, then the
editor bundle called `focus()` on its contenteditable before Shift+Tab.
That key reached the composer, where it is a work-mode shortcut. This
confirms a pending editor selection update stole focus; it was not the
browser skipping sidebar buttons. The assertion did not prove the star
retained focus. The test now moves the pointer away, focuses the
preceding sidebar link, presses Tab once, and asserts both actual focus
and opacity. This is test synchronization and keyboard traversal, not a
demonstrated CSS defect. |
| Runtime readiness exceeds 10 seconds | The old error only says `fetch
failed`. There is no child startup output in that failure, so it cannot
distinguish slow process startup from a refused or stalled probe. It
passed unchanged locally and took 3.416 seconds in attempt 3. Resource
contention is plausible but unproved. This PR does not claim a proven
historical runtime root cause: it isolates fixture registry/log files,
checks ports before spawn and after stop, checks live backends at
publication, and preserves transport errors, probe count, elapsed time,
and fixture startup timestamps for the next occurrence. |
| Later CI: recovery reply disappears after reload | Product
synchronization bug, distinct from the blank-page bootstrap failure.
Reproduced locally with a trace: the comments request started at
`21:56:07.443`, the server saved the reply at `.520`, and the first live
subscription started at `.541`. The reload fetched a successful run and
its complete log, but missed the comment event. The provider refreshed
after reconnects only. It now refreshes active queries on the first
connection too. A deterministic regression test fails before the fix. No
browser assertion was changed. |
| Later CI: Slack backoff and authorization tests | The 30-second
backoff assertion required more than 25 seconds to remain when it read
the saved action. CI spent 10.311 seconds in the test, exceeding that
five-second allowance. A local six-second read delay reproduces the
failure; the new transport-anchored lower and upper bounds pass the same
fault injection. The neighbouring authorization test ran three
independent fixtures in one test and timed out at 15 seconds. Each case
now has its own fixture cleanup and the normal per-test deadline, so
earlier cases do not remain active during later global worker sweeps. No
specific production slow call was established. |
| Self-hosted runner loses communication or shuts down | The original
lost-communication failure has no assertion. On final-head [attempt
1](https://github.com/paperclipai/paperclip/actions/runs/35925901613/attempts/1),
Build, Runner Vitest 1/2, and chat 2/3 ran on three separate fleet
instances. All received a runner shutdown signal at `22:04:55 UTC`,
within 35 milliseconds, then cancellation. Server shard 6/12 received
the same shutdown signal one minute later. All four were Spot
`m7i-flex.xlarge` instances in `us-east-1a`. No test assertion or build
error preceded those stops. This is infrastructure interruption; the
reason the fleet stopped the runners is not available in job logs. |

## What Changed

- Build the browser fixture UI into the static server's preferred
directory, `server/ui-dist`, and disable Vite middleware. Ignore these
generated assets. Start the source CLI directly from the repository
root, as required by the CLI invocation safety contract.
- Keep all existing chat assertions. Add first takeover and three
service-worker-controlled reloads under CPU throttling. Assert that the
page uses built module assets and that opening it creates no chat task.
- Use forward keyboard traversal from the Zeta link to its star. Check
focus before checking the reveal style.
- Give each runtime exposure test a temporary Paperclip home and restore
environment state after process cleanup.
- Check that reserved ports are free before spawn, serve the fixture
response before exposure, and become free after stop.
- Include the nested fetch error, probe count, and elapsed time in
readiness failures. Add a unit test for this diagnostic contract.
- Refresh active queries when the first live connection opens, covering
events missed during initial page loading. Keep reconnect toast
suppression unchanged.
- Measure Slack retry timing from the transport attempt and recovery
completion. This checks the full provider-requested delay without
spending a small wall-clock allowance on unrelated processing.
- Run each Slack authorization-revocation scenario as a separate test,
with cleanup between cases. All assertions remain.
- Document the browser fixture's build and serving mode. No configured
assertion deadline, readiness deadline, retry count, or skip was added.

## Verification

- Final-head [Linux CI, attempt
2](https://github.com/paperclipai/paperclip/actions/runs/35925901613/attempts/2):
**green**. All 52 check runs passed; two conditional checks were
skipped. The legacy Snyk status also passed. No pending or failed checks
remain.
- `pnpm -r typecheck` passed.
- `pnpm build` passed again after the final UI fix.
- Focused runtime suites: 38 passed, 3 existing platform skips.
- CLI invocation safety suite: 39 passed.
- Slack timing negative control: inserting a six-second delay before
reading the saved action fails the old assertion. All four revised
authorization/backoff cases pass with that same delay. The diagnostic
delay is not committed.
- Live update suites: 92 passed, including the new regression. UI
typecheck and token gates passed.
- Recovery browser negative control: the unchanged tests reproduced the
missing reply (1 failed, 9 passed). After the first-connection fix, all
six recovery paths passed twice (12 passed). Browser assertions and
deadlines are unchanged.
- Server typecheck passed after the Slack test adjustment.
- `GITHUB_WORKFLOW=PR pnpm test:run:general -- --group general-chat
--shard-index 0 --shard-count 3`: 342 passed. The other 682 tests belong
to the remaining shards; collection verified exact coverage.
- Final direct-source CLI launch: all five chat session tests passed.
- `PAPERCLIP_E2E_PORT=32993 PAPERCLIP_PLAYWRIGHT_CHANNEL=chrome pnpm
exec playwright test --config tests/e2e/playwright.config.ts
tests/e2e/agent-chat-sessions.spec.ts --repeat-each=3`: 15 passed,
including nine controlled reloads at 4x CPU throttling.
- `GITHUB_WORKFLOW=PR pnpm test:run:general -- --group
general-server-without-chat --shard-index 10 --shard-count 12`: 55 files
passed, 867 tests passed, 21 existing skips. An earlier run could not
initialize PostgreSQL because this Mac exhausted its System V
shared-memory slots. After reclaiming the orphaned segment from this
task's stopped browser server, the full shard passed.
- On final commit `1f1fafc08d`, [browser
4/8](https://github.com/paperclipai/paperclip/actions/runs/35925901613/job/107400837947)
passed all 16 tests; [browser
8/8](https://github.com/paperclipai/paperclip/actions/runs/35925901613/job/107400838155)
passed all 23 tests; [server
11/12](https://github.com/paperclipai/paperclip/actions/runs/35925901613/job/107400838328)
passed 887 tests with one existing skip. The readiness lifecycle case
took 1.842 seconds. Chat 1/3 also passed. All four jobs interrupted by
runner shutdowns passed unchanged on their single rerun.
- Greptile reviewed `1f1fafc08d`: **5/5**, with no unresolved comments.
- Full local `pnpm test:run` was attempted and stopped after confirming
failures outside this patch: a sibling `skills` directory shadows
bundled Slack/AgentMail skills; macOS rejects rename of read-only
skill-cache directories (`EACCES`, also reproduced in an isolated
filesystem probe); and the host exhausts PostgreSQL System V
shared-memory slots. Focused reruns confirmed these limits. The complete
Linux CI run is the repository-wide verification; the full local run is
not green.
- Baseline evidence: the original sidebar test failed on unchanged
master; a development-mode run at 4x CPU throttling passed six selected
cases, so CPU pressure alone did not reproduce the CI bootstrap stall.

## Risks

- Default browser tests now exercise the shipped static UI. They no
longer implicitly cover Vite middleware or HMR; use the development
server for those checks.
- The new browser startup test uses Chromium CDP, matching the only
configured browser project.
- Opening a live subscription now causes one active-query refresh to
close the initial event gap. This adds startup API reads but no
recurring poll.
- Runtime behavior and deadlines are unchanged except for error details.
The historical readiness stall remains unconfirmed; a green rerun alone
cannot establish its cause.
- Local verification runs on macOS. The runtime lifecycle checks also
passed on Linux CI.

## Model Used

- OpenAI GPT-6 through Codex. The session identifies the model family as
GPT-6; an exact served model ID and context window size are not exposed.
Used reasoning, repository inspection, shell tools, code editing, and
test execution. No subagents were used.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#123` / `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 passed;
full local host limits 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-23 15:22:21 -07: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
Devin FoleyandPaperclip c65fc9e3c8 fix: recover authentication and browser connection failures (#13724)
fix: recover authentication and browser connection failures

Include connect timeouts in the bounded retry policy for idempotent actor
synchronization. Handle WebSocket constructor failures through existing
reconnect paths and preserve HTTP polling while realtime is unavailable.
Refresh visible company queries until the socket recovers and clear all
fallback timers on hiding or unmount.

Verify 172 focused tests, server/UI typechecks, UI build, and design token
gates. Full workspace build/typecheck require the unavailable Rust toolchain;
the full test run is tracked separately.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-20 12:43:25 -07:00
DottaandPaperclip 7bc03e0acd feat(runner): default harnesses to full auto and support task reassignment (#13686)
## Thinking Path

> - Paperclip lets people manage AI agents and their work.
> - Agent Chat uses native runners to save plans and coordinate tasks.
> - Provider defaults differed across harnesses and could stop
unattended work at a second permission gate.
> - Agents also lacked a dedicated tool to move existing work to another
agent safely.
> - This change defaults native providers to full automatic permission
for provider tools and connected tools.
> - A guarded reassignment tool preserves task identity, stops the
previous run, and schedules the new owner once.
> - Codex and Claude chat acceptance tests now use production permission
defaults.

## Linked Issues or Issue Description

**Subsystem affected**

Native runner, ACPX Claude permission policy, task authority, and Agent
Chat acceptance tests.

**Problem or motivation**

A user can authorize an agent to save a plan or create a task, but
Claude's default provider gate can still stop that action. Reassignment
needs a dedicated operation that preserves context and avoids concurrent
owners or unintended recovery runs.

**Proposed solution**

Default Claude/ACPX to `approve-all`, OpenCode to `allow`, and Codex to
`never`. Apply the defaults at configuration, execution, fresh-session,
resume, driver, and proxy boundaries. Keep explicit permission settings
and server-side company, claim, task-mode, and approval checks. Add
`reassign_task` with version checks, durable idempotency, audited
cancellation, and guarded successor scheduling.

**Alternatives considered**

A Paperclip-only allowlist still blocks provider tools and other
connections during unattended work. Full automatic permission is the
requested product default. Recreating a task discards its identity and
history. Updating assignment without stopping the previous run can leave
two agents working on the same task.

**Roadmap alignment**

This extends the existing planning, delegated work, governed tool
access, and recovery features. It adds no new service or schema
migration. Recent related tasks and open PRs were checked for duplicate
work.

**Additional context**

Related: #13678 (Agent Chat tools and recovery), #13677 (remote runner
startup). The stacked legacy-adapter companion is #13693. This also
fixes the deployed-server artifact fallback needed to stage the current
runner binary.

## What Changed

- Default Claude/ACPX to `approve-all`, OpenCode to `allow`, and Codex
to `never`, including missing settings at direct driver and proxy entry
points. These defaults cover provider tools and connected tools.
Preserve explicitly configured restrictive modes.
- Include assigned approval reads using canonical side-effect
classifications, so verifying a recorded approval does not trigger
another provider gate. Paperclip approval decisions still enforce
controller authority.
- Carry the new permission mode through server configuration, execution
contracts, recovery identity, TypeScript, and Rust. Keep
`approve-paperclip` as an optional restricted mode, with exact SDK rules
and closed unknown requests. It is not a default.
- Add `reassign_task` to the semantic catalog, controller, mock
authority, and generated contracts.
- Guard reassignment with company authorization, expected owner and
version, protected-state checks, and durable retry receipts.
- Honor explicit backlog task creation atomically with the initial plan,
without scheduling a wake. Preserve backlog holds regardless of
dependency readiness.
- Stop active work before changing ownership. Restore the prior owner
through a guarded, idempotent wake if final handoff validation fails.
Keep intentional reassignment stops out of failure recovery. Preserve
backlog and blocked states without waking them early.
- Add authorization, concurrency, replay, stop, and permission boundary
regressions. Add Codex and Claude chat reassignment cases and run native
chat cases with production defaults.
- Clarify shared runner guidance: save plans and Paperclip documents
directly with `write_document`; create and register a local file only
when a downloadable file is requested.
- Document provider defaults and the operator choices for existing
agents.

## Verification

- Current head `d82fbb0f03546d27cecf072250e4172e0b1ee662`: **55 checks
passed**, with two intentional skips. [PR
checks](https://github.com/paperclipai/paperclip/pull/13686/checks).
- Greptile reviewed that exact head at **5/5**. The security reviewer
acknowledged the intended full-auto default, and the acknowledged
discussions are resolved.
- Full workspace `pnpm -r typecheck` and `pnpm build` passed locally
after rebasing onto current master. Targeted adapter/server, runner,
API, default/resume, and heartbeat configuration tests passed.
- **All six real-provider acceptance cases passed on their first
attempt, with cleanup passing:** plan handoff, task reassignment, and
backlog creation/status, each on native Claude and Codex. Evidence
records Claude's effective `approve-all` mode. [Campaign and
downloadable
evidence](https://github.com/paperclipai/paperclip/actions/runs/35469926548).
- The live campaign tested combined revision
`a37881c824dcd7170380fc4b788732fc743e5da7`. The final PR heads add only
a heartbeat test expectation correction; application code is unchanged
from that live-tested revision.
- The campaign's result-enforcement job passed. Its separate report
publisher failed because the trusted workflow's `patchedDependencies`
configuration differs from its frozen lockfile. All six results and
screenshots remain available as GitHub artifacts. The overall manual
workflow is red for this publishing failure.
- Full-suite coverage is supplied by the passing CI partitions. The
separate unsharded local run was stopped after the corresponding CI
partitions passed; it is not counted as a completed local run.
- Reassignment tests cover stale state, cross-company access, denied
authority, cancellation failure, compensating wake, and idempotent
retries. Backlog tests verify the original creation audit, saved plan,
exact task count, and absence of task-bound runs.

## Risks

- Agents with no explicit permission mode now receive full provider tool
permission, including connected tools. This is a deliberate broad
default. Existing explicit restrictive modes still apply. Controller
authorization, company isolation, workspace boundaries, and Paperclip
governance remain in force.
- Reassignment crosses run cancellation and task ownership transactions.
Durable stop intent, revalidation, audit receipts, and guarded queue
dispatch cover interruptions and retries.
- The new permission enum requires a current runner artifact. The remote
artifact fallback uses the same resolved controller binary for upload
and execution.
- Live provider behavior remains subject to the selected model. Targeted
live results do not qualify the full catalog.

## 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
DottaandPaperclip 04546c82d5 fix(runner): reconnect Daytona sessions after controller restart (#13691)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The native runner can execute a task inside a Daytona sandbox.
> - The sandbox can keep running when the Paperclip controller restarts.
> - Recovery treated sandbox process IDs as local process IDs and
selected the wrong recovery path.
> - Live verification also found races between startup, shutdown, and
queued task cleanup.
> - This pull request verifies the existing remote owner and orders
those transitions.
> - Users can continue the same task and provider session after a
controller restart.

## Linked Issues or Issue Description

**What happened?**

The Daytona `recover-controller` cases failed with
`runner_state_identity_mismatch`. Remote process IDs can be absent on
the controller or collide with unrelated local processes. Recovery then
looked for remote state in the local runner directory. Later turns could
also start before the previous executor released its sandbox resources.

**Expected behavior**

Reconnect to the original sandbox and authenticated runner. Preserve the
task, provider session, and queued comments. Reject a replacement
sandbox or mismatched identity. Do not start another provider during
reattachment.

**Steps to reproduce**

Run the `everyday-workflows` `recover-controller` case for
`runner-codex` or `runner-acpx-claude` in Daytona. The browser creates a
Python tool, requests a revision, restarts the controller during
execution, and queues another revision. It then downloads and tests the
final ZIP.

Related: #13682 is the preceding operational fix. #13291 addresses
legacy sandbox conversation recovery, a different execution path. #13666
includes broader run-capacity work; this change guards cleanup of an
existing native task executor.

## What Changed

- Add remote runner recovery without interpreting sandbox PIDs on the
controller.
- Verify the original provider lease, remote workspace, durable state,
process marker, and authenticated PRP authority before adoption.
- Compare the process marker with live Linux boot identity and start
ticks to reject PID reuse. Read virtual proc files through the
guaranteed Node runtime; unavailable proof blocks adoption without
blocking a fresh launch.
- Make the E2E supervisor own the actual server process so forced
restart cannot leave a late database closer behind.
- Scope the chat delivery lease test to its own fixture instead of
draining other tests’ pending deliveries.
- Preserve provider-attempt counts and recorded evidence during
reattachment.
- Serialize an idle-session checkpoint with admission of the next native
turn.
- Wait for an in-progress startup to acknowledge restart detachment.
Fail after a bounded deadline if it cannot.
- Keep a queued comment waiting until the previous native task executor
releases its resources. Allow unrelated tasks to continue.
- Update the Daytona image's resolved lock digest to match current
dependency manifests.
- Add classifier, ownership, process, startup, checkpoint, and
queued-admission regression tests. Document recovery behavior.

## Verification

- 415 focused tests passed across native execution, restart recovery,
workspace synchronization, queued admission, and real-process restart
tests. The final Node-based fingerprint change passed all 375
native-session tests.
- Runner harness unit tests: 394 passed. Chat integration shard 2: 335
passed after fixture isolation.
- The exact fingerprint command succeeded twice in a disposable Daytona
sandbox and returned the same identity; the sandbox was deleted.
- 11 real-process restart integration tests passed, including absent and
colliding remote PIDs.
- Repository typecheck and final build passed. Broad local checks found
machine-dependent database startup and timing failures; focused retries
passed. The final-revision PR pipeline is green. One unrelated browser
shard hit a five-second blank-page timeout on the first run and passed
its targeted retry.
- Final-revision local headed browser E2E:
`everyday-workflows.runner-acpx-claude.daytona.recover-controller`
passed on attempt 1 in 4.7 minutes, **40/40 checks**. Manual browser
inspection confirmed Done, all three ZIPs, and delivery of the queued
follow-up. All three runs succeeded using the same provider session. The
harness downloaded and independently tested the final artifact.
- Final-revision Daytona campaign:
https://github.com/paperclipai/paperclip/actions/runs/35463999611 —
**Codex passed first attempt (4.8 minutes); ACPX Claude passed first
attempt (6.1 minutes)**. Campaign aggregation/publication is finishing;
both test jobs succeeded.
- Greptile reviewed `beb08d8493b3286f5bb988dead369ff8c96a395d`: **5/5**,
no open findings.
- Staging browser verification is pending selection of a disposable
staging instance and removal of a Chrome extension UI block.

## Risks

- Recovery now depends on the original sandbox remaining available. A
replacement or mismatched identity still blocks adoption.
- Shutdown waits up to 30 seconds for a native startup to reach a safe
detach point. An unfinished startup returns a clear failure instead of a
false detach receipt.
- Queued native work on the same task waits for cleanup. Unrelated tasks
remain eligible.
- The image digest update rebuilds the Daytona runtime image. No
database migration or public API change is included.

## Model Used

OpenAI Codex, GPT-6, with repository inspection, code execution, and
browser tools. The runtime does not expose the exact deployed model ID
or context-window size.

## Checklist

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

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat turns discussion into plans, tasks, reviews, and hires.
> - These workflows need reliable tool results and task context on the
native runner.
> - Live Claude and Codex tests exposed lost retry requests, invalid
project inputs, and a child startup crash.
> - Recovery also exposed a misleading retry action and missing child
task context.
> - This pull request fixes those paths and adds regression coverage.
> - Agents can continue the original request and operators can inspect a
stopped run.

## Linked Issues or Issue Description

**What happened?**

A failed Agent Chat retry could lose the user's question. Project
creation accepted unsupported icons in its tool schema. Codex could stop
when a helper's MCP startup event arrived before its thread lineage. A
stopped task offered Retry even when the server required execution
reconciliation. Resumed agents could miss existing delegated tasks.
Hiring and review instructions did not describe the native runner's
available tools and source requirements.

**Expected behavior**

Retries retain the selected request. Tool schemas match the API. Child
startup information does not gain authority over the parent or stop it.
Recovery actions match the server's requirements. Task context exposes
existing child work. Handoffs contain the material the assignee needs.

**Steps to reproduce**

1. Enable experimental Agent Chat in an isolated development instance.
2. Configure native Codex and ACPX Claude agents on Paperclip Runner.
3. Ask for a plan, revise it, approve task creation, and request a hire
and status report.
4. Retry a failed chat turn and check that it answers the original
request.
5. Start a Codex helper before its thread lineage arrives.
6. Resume a delegated task and inspect its existing children and saved
output.

**Paperclip version or commit**

The live failures were found at `f2c5e54dc`. This branch is rebased onto
`86b7ee992`.

**Deployment mode**

Isolated local development instance with native Codex and ACPX Claude.
No database migration or default permission change.

Related work: Refs #13284 for Agent Chat. Refs #13438 for the
server-side API receipt fix, which this branch preserves. The transport
also accepts the earlier HTTP receipt format. Refs #13655 for the
current Codex continuation and helper lineage handling, which this
branch also preserves.

## What Changed

- Preserve failed Agent Chat wake-comment IDs and session generation
from the authorized source run. Reject pre-reset retries.
- Wrap API receipts with the correct semantic call identity. Test
current and earlier receipt formats through real HTTP and runnerd.
- Classify early child MCP startup notifications as information. Keep
foreign completion and result events rejected.
- Constrain project icons on both tool surfaces and regenerate the
protocol contracts.
- Include bounded, company-scoped visible direct child tasks in task
context. Filter hidden tasks before applying the limit.
- Replace the rejected Retry action with Inspect run for native
continuation reconciliation.
- Update hiring, review handoff, status reporting, and development
guidance.

## Verification

- Live tests covered Claude and Codex questions, plan revisions,
approval, task creation, hiring, status, chat reset, failures, and
recovery.
- The recovered task produced its saved checklist and example. A later
follow-up read the existing child tasks and document without creating
more work.
- Full build, repository type checks, token gates, 142 focused tests,
188 runner TypeScript tests, and the Rust notification/descendant
regressions passed after rebase. The separate local full-suite run was
stopped after the complete CI suite passed.
- Review fixes passed the updated route, tool-authority, and icon
regression tests plus server type checking.
- Required commands: `pnpm build`, `pnpm -r typecheck`,
`PAPERCLIP_IN_WORKTREE=false pnpm test:run`, and `pnpm
check:token-gates`.
- At `4ce8047b0`, all 55 applicable GitHub checks pass (two Storybook
checks are intentionally skipped), including the complete
general/serialized test matrix, runner tests, browser tests, build, type
checks, Docker checks, and canary dry run.
- Fresh Greptile review is 5/5 on `4ce8047b0`; all three findings were
fixed with regressions and there are no unresolved review threads.
- Two initial CI service-startup timeouts passed unchanged in local
reproductions and in the latest CI run.

## Risks

- The new event classification is limited to MCP startup information. It
does not authorize foreign task completion, results, or tool requests.
- Task context returns at most 100 direct child tasks and reports
truncation. It excludes hidden tasks and other companies. This improves
delegation context but does not enforce semantic duplicate detection.
- Native reconciliation still requires an operator to inspect and record
prior outcomes. The new link does not replace the recovery API.
- API tools remain opt-in. Claude permission choices remain explicit. No
default permission, schema, or workflow changes.

## Model Used

OpenAI GPT-6 in Codex, with reasoning, repository editing, code
execution, API tools, and browser testing. The exact deployment
identifier and context-window size are not exposed in this session. Live
acceptance agents used OpenAI `gpt-5.6-sol` and Anthropic
`claude-sonnet-4-6`.

## 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 09:11:04 -05:00
1ef3b08714 feat(ui): integrate agent personas across the app (#13171)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - A stable agent persona is useful only when the same identity appears
across the app.
> - Lists, task messages, selectors, and activity feeds need inexpensive
static avatars.
> - Onboarding and agent headers need a larger character with
expressions and pointer tracking.
> - This pull request connects the persona foundation to those existing
views and preserves onboarding draft assignments.
> - Full-page stories and Linux checks make the placements and
performance contract reviewable.

## Linked Issues or Issue Description

**Problem or motivation**

Agents need a stable visual identity in lists, tasks, onboarding, and
configuration. External tools also need an image URL for that identity.

**Proposed solution**

Assign each agent a permanent palette from a fixed ClipLab character
library. Store the assignment on the agent. Render and cache preset PNG
URLs on demand. Use static images in dense views and one animated
character in larger placements.

**Alternatives considered**

A generated image bundle requires a separate asset build. A live
renderer in every avatar adds unnecessary work in large lists. Arbitrary
uploaded images do not provide the requested shared character system.

**Roadmap alignment**

This improves agent identity across existing control-plane views. It
preserves agent permissions, company boundaries, and status labels.
ROADMAP.md has no separate ClipLab persona milestone.

Related approaches: #2422 adds configurable image URLs and DiceBear
generation; #5578 adds optional uploaded avatars. This work uses a
fixed, versioned character library and preset URLs.

## What Changed

- Replace agent icons with static persona images across lists, the
sidebar, org charts, tasks, comments, selectors, activity, and dashboard
views.
- Put one animated character in the agent header. Let it follow the
pointer across the page, with reduced-motion and touch fallbacks.
- Add larger padded characters to agent creation. Keep the palette
stable across draft refreshes and connection retries, then reveal it
after success.
- Pass appearance through shared projections rather than fetching each
agent separately.
- Add real full-page Storybook examples for the agent list, overview,
task, dashboard, new-agent dialog, and connection page.
- Add Linux screenshot, clipping, density, and 500-avatar performance
checks.

## Verification

- `pnpm -r typecheck`, `pnpm build`, and token gates pass on the rebased
tree. Persona lifecycle tests pass.
- The rebased feature passes 38 Linux screenshot/performance checks,
including both display densities, corner pointer positions, and the
no-WebGL/no-live-download contract for 500 avatars.
- The final Linux persona suite passes all 38 visual, lifecycle,
density, and full-page checks using the standard Storybook configuration
and real on-demand avatar endpoint.
- Final local focused verification: 45 avatar/native-recovery tests
pass; UI identity/routine tests, typecheck/build, token gates, and
Storybook build pass.
- Current-head CI passes: full workspace/server tests, all serialized
server groups, typecheck/release checks, build, canary validation, and
end-to-end shards. The build passed after retrying a native-runner
concurrency-test failure; its three targeted cases also pass locally.
- Manual inspection covered stable identities in the app, header
placement, full-page mouse tracking, onboarding size, and task/dashboard
placements.


### Screenshots

Linux captures use synthetic Storybook fixtures. Full-page captures use
reduced motion. The live character, mouse tracking, and disposal are
checked separately.

<details>
<summary>Agent overview with the character in its header</summary>

<img
src="https://raw.githubusercontent.com/paperclipai/paperclip/8c68f42b268ada22b67d79d0fe1bb0a2f84ec25c/screenshots/full-page-agent-overview.png"
width="900" alt="Agent overview with the character in its header" />

</details>
<details>
<summary>Task messages and assignee identity</summary>

<img
src="https://raw.githubusercontent.com/paperclipai/paperclip/8c68f42b268ada22b67d79d0fe1bb0a2f84ec25c/screenshots/full-page-task.png"
width="900" alt="Task messages and assignee identity" />

</details>
<details>
<summary>Larger onboarding character with room for expressions</summary>

<img
src="https://raw.githubusercontent.com/paperclipai/paperclip/8c68f42b268ada22b67d79d0fe1bb0a2f84ec25c/screenshots/full-page-meet-your-next-agent.png"
width="900" alt="Larger onboarding character with room for expressions"
/>

</details>
<details>
<summary>Dashboard agent activity</summary>

<img
src="https://raw.githubusercontent.com/paperclipai/paperclip/8c68f42b268ada22b67d79d0fe1bb0a2f84ec25c/screenshots/full-page-company-dashboard.png"
width="900" alt="Dashboard agent activity" />

</details>

## Risks

- This PR depends on #13170, the persona foundation. Merge the
foundation first, then retarget this PR to master.
- Many placements change from icons to character silhouettes. Human
avatars and authoritative agent status labels retain their existing
behavior.
- Only one character can render live per view. Reduced motion,
hidden/offscreen content, touch input, and renderer failures use the
defined fallbacks.
- The full-page stories use fixture data. They do not contact a real
company or complete real provider sign-in.

## Model Used

OpenAI Codex, GPT-6 family. The exact model identifier and context
window are not exposed in this session. Used code editing, shell
execution, browser inspection, and Linux visual testing.

## 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: Tonio <tonework@gmail.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-19 07:57:53 -05:00
DottaandPaperclip 924f07be8c feat(chat): simplify Slack onboarding and account linking (#13638)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat connections let people start and continue that work from Slack.
> - Setup mixed app creation, credentials, URL verification, account
linking, and testing on the same screens.
> - People also needed a safe way to link their own Slack identity after
the first operator finished setup.
> - This pull request gives each step a clear place and keeps membership
approval separate from identity linking.
> - It also makes connection details easier to use and fixes misleading
callback health behind HTTPS proxies.

## Linked Issues or Issue Description

**Subsystem affected**
Cross-cutting: chat routes and services, shared contracts, and the Apps
board UI.

**Problem or motivation**
Slack onboarding made users find settings without enough guidance. A
second user needed operator help to link their account. Activity stopped
at 100 records, and TLS termination could mark working callbacks as
stale.

**Proposed solution**
Use six setup steps with editable app names, a generated manifest,
credential guidance, URL verification, account linking, and an optional
message test. Send each Slack user a private, expiring confirmation
link. Require company membership or an approved access request before
linking. Add cursor pagination and tolerate the internal HTTP hop in
callback diagnostics.

**Roadmap alignment**
This improves the existing connected-app surface and supports CEO Chat
without changing the task-and-comments model. The maintainer requested
and reviewed the flow during a live Slack test drive.

**Additional context**
Related work: #7, #3349, #13000, and #13620. Those cover broader chat
capabilities, older webhook paths, or plugins. This PR improves the
existing native connector's setup and account-linking flow. HTTPS
documentation was published separately in
paperclipai/paperclip-docs#128.

## What Changed

- Split Slack onboarding into six clickable sidebar steps. Keep
secondary and primary actions on one row.
- Generate the Slack creation link and read-only manifest from editable
app, bot, and command names. Add credential prefix validation and direct
instructions.
- Add live account-link status and an optional mention-based message
test.
- Add private, single-use Slack account invitations and membership
access requests. Retain cloud authentication/bootstrap checks and
enforce the chat rollout flag in all identity APIs. Default new Slack
connections to linked users only.
- Put Settings, Access, Conversations, and Activity in the sidebar.
Simplify conversation rows and remove active header badges.
- Add 25-item activity pages, stable timestamp/ID cursors, and replay
safety across pages. Preserve the legacy array API for clients without
pagination parameters.
- Fix false callback warnings when HTTPS terminates at a proxy. Keep
host, port, and path drift detection.
- Document the setup flow, pagination, callback diagnostics, and shared
wizard footer rule.

## Verification

- Passed: `pnpm -r typecheck`, `pnpm build`, and `pnpm
check:token-gates`.
- Passed: focused Slack callback and pagination integration tests; UI
clipboard, wizard, pagination, and activity tests; OpenAPI route tests.
The final access-gate fix also passes 27 focused tests covering cloud
authentication/bootstrap, nonmember invitations, token validity, and the
server-enforced rollout flag.
- Passed: all 1,002 chat integration tests, 6,356 UI tests, and all 11
provider browser scenarios (including mobile light/dark navigation).
After rebase, the identity route, sidebar, and 25 clipboard tests pass.
- The full local `pnpm test:run` was attempted. The first run found 14
Slack fixtures that needed explicit guest access; those are fixed and
the complete chat suite passes. Unrelated embedded PostgreSQL
startup/resource failures and timeouts prevented a clean full local run.
All CI checks pass on `2d858b036`, including the full chat, server,
workspace, build, typecheck, and browser suites.
- Live test drive: Slack app creation, credential setup, URL
verification, private account confirmation, mention messages, and thread
replies. Verified the callback warning clears for the existing proxied
connection.
- Review: create a Slack connection, follow the six steps, link a second
user's account, and browse older activity with Next and Previous.

## Risks

- Identity invitations carry a temporary capability. Tokens are hashed,
expire after 15 minutes, work once, and require explicit confirmation by
a company member. Access requests do not grant membership.
- New Slack connections reject unlinked people by default. Existing
connection settings remain intact.
- Activity is a live ledger. Updated action rows can move forward in
time. Older pages do not poll.
- Proxy tolerance affects health display only. Slack signature checks
and proxy authentication settings remain unchanged.
- No database migration or package-lock changes.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository tools, code
execution, and browser verification. The runtime does not expose an
exact model build 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 (targeted suites; full
local-run limitations documented above)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-18 17:23:53 -05:00
DottaandPaperclip f4cdc7b231 fix: recover transient workspace bootstrap scans (#13481)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The control plane prepares task workspaces before it starts an
agent.
> - Workspace preparation reads Git state so it can preserve edits and
exclude private files.
> - A failed scan was treated as a non-Git folder and lost its actual
failure code.
> - The resulting generic setup failure could not recover, even when the
cause was temporary.
> - This pull request keeps the cause and uses the existing bounded
retry schedule before provider startup.
> - Tasks can recover without human intervention, while permanent
failures and exhausted retries stop with useful guidance.

## Linked Issues or Issue Description

**What happened?**

A Git scan error during managed repository preparation became
`Configured repository folder is not a Git checkout`, followed by
generic `setup_failed`. The agent never started. Generic recovery could
not distinguish a temporary timeout from a bad workspace configuration.

**Expected behavior**

Keep the closed scan error code. Retry temporary timeouts and queue
saturation under the existing shared budget. Preserve edits, exclusions,
ownership, and pause gates. Stop permanent failures and exhausted
retries with a specific explanation. Do not replay historical generic
setup failures.

**Steps to reproduce**

1. Configure a task project with a local Git source that must be copied
into its managed repositories.
2. Make the ignored-file scan exceed its timeout before the agent
starts.
3. Before this fix, the snapshot returns null and the run ends as
non-retryable `setup_failed`.
4. Use the disposable browser fixture in
`tests/e2e/workspace-bootstrap/README.md` to inject real timeouts and
test the full recovery path.

**Paperclip version or commit**

Reproduced against `4510bf7c9e2fcbeb043445850928b5dcb79908ca`.

**Deployment mode**

Built from source. The defect is in core workspace setup, not a specific
model provider.

Related work: Refs #13442 (managed repository preparation), Refs #11572
(bounded Git scheduler), Refs #12997 (separate adapter startup retry
work), Refs #13469 (separate terminal-workspace scan performance work).

## What Changed

- Return the non-Git fallback only for repository discovery. Propagate
failed scans of a confirmed repository.
- Replace full ignored status output with an ignored-only directory
listing. Preserve NUL-delimited paths and exclusions.
- Preserve typed, sanitized scan errors through workspace preparation
and persist pre-provider failure details.
- Retry only timeouts and queue saturation, using the existing durable
two-retry budget and issue gates. Prevent generic recovery from adding
another budget.
- Show workspace-specific failure copy and actionable exhausted-recovery
notices.
- Add red-green unit tests, real-database restart and retry-boundary
tests, and opt-in browser acceptance fixtures with real Git subprocess
timeouts.
- Document the recovery contract and browser verification procedure.

## Verification

- Red: injected scan failures returned null instead of rejecting; setup
lost the timeout code; task-thread and recovery notices had generic
copy.
- Green: 119 focused adapter/backend tests, 20 recovery-boundary tests,
and 136 task-thread tests.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed on the final production code.
- `pnpm check:token-gates` — passed.
- The initial local `pnpm test:run` overlapped source edits and was
interrupted after two late-added assertions saw pre-fix behavior; it is
not counted as a green full run. A fresh final-head run passed all 229
tests across the six affected adapter/backend/UI suites. The clean
latest-head CI full test matrix passed: all five general-server shards,
all five serialized-server shards, and all three general-workspace
shards.
- Latest-head CI also passed all three browser shards and their
aggregate gate, typecheck and release registry, build, runner
verification, canary dry run, policy, Docker context integrity, and
security gates. Greptile: 5/5, with the review thread resolved.
- Browser: created a task in a disposable instance. A real Git timeout
scheduled recovery, the next run completed through the run-scoped API
without manual Retry, and Done survived reload. The deterministic
process worker checked preserved source edits and excluded private
files; no model calls were made.
- `WORKSPACE_BOOTSTRAP_TEST_URL=<disposable-instance-url> pnpm exec
playwright test --config
tests/e2e/workspace-bootstrap/playwright.config.ts` — 2 passed (3.6
minutes). The persistent case made exactly three failed attempts, never
started the worker, showed the cause-specific notice, stayed stopped for
another scheduler tick, and retained Blocked after reload.
- Extra red-green coverage: 50 recovery tests passed after fixing an
exhausted-bootstrap classification that incorrectly implied unknown
provider actions. Missing or uncertain evidence still retains the safety
hold.
- Verified the documented Git executable override during repository
seeding.

## Risks

- A confirmed repository scan failure now fails closed instead of
falling back to directory sync. This prevents unfiltered copying but
makes previously hidden errors visible.
- Temporary host problems can create up to two additional setup
attempts, 30 seconds apart. Permanent scan errors do not auto-retry.
Generic recovery cannot reset this budget.
- The durable retry path still enforces ownership, pause, and work
eligibility. Integration tests cover restart, duplicate promotion,
pause, exhaustion, and non-retryable categories.
- No schema migration, new runtime setting, new retry budget, production
deployment, or historical task replay.

## Model Used

OpenAI Codex, GPT-5-based coding agent, with reasoning, repository
tools, shell execution, and browser testing. 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-15 12:37:21 -05:00
DottaandPaperclip 4510bf7c9e ci: use code-owner-reviewed master for trusted PR workflow (#13470)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Pull request CI uses a trusted workflow on the AWS runner fleet.
> - The caller used a fixed SHA that also needed runner-group admission.
> - A mainline pin update left CI queued because the group still allowed
older SHAs.
> - This pull request calls the trusted workflow on master, which
requires code-owner review.
> - New merged workflow versions can use the existing master
runner-group entry.

## Linked Issues or Issue Description

Related: #12968. That Dependabot PR proposes another SHA rotation. This
change keeps this first-party workflow on master instead.

**What happened?**

CI run 34975562974 stayed queued because its trusted workflow SHA was
absent from the runner-group allowlist. The fleet itself was healthy.

**Expected behavior**

New reviewed versions of the trusted workflow on master should receive
runner access without a separate SHA allowlist update.

**Steps to reproduce**

Change the caller to a new trusted workflow SHA without adding that SHA
to the restricted runner group. Its jobs remain queued. The master
reference removes that recurring synchronization step.

## What Changed

- Call `paperclipai/paperclip/.github/workflows/pr-trusted.yml@master`.
- Exclude this exact first-party workflow from Dependabot updates.
- Update the existing E2E shard workflow tests for the master caller
contract.
- Document the runner-group entry, required code-owner review, and
old-reference retention.

## Verification

- `actionlint .github/workflows/pr.yml` passed.
- `node --test scripts/__tests__/e2e-shard.test.mjs
.github/scripts/tests/cloud-runner-routing.test.mjs
.github/scripts/tests/pr-runner-rust-cache.test.mjs
.github/scripts/tests/pr-dependency-cache.test.mjs` passed: 35 tests.
- Parsed Dependabot YAML and checked the exact workflow exclusion.
- `git diff --check` passed.
- Live GitHub checks confirmed `.github/**` has code owners, CODEOWNERS
has no errors, and the active master ruleset requires code-owner review.
This covers the trusted workflow, caller, and CODEOWNERS itself.
- The approved organization setting now allows
`paperclipai/paperclip/.github/workflows/pr-trusted.yml@refs/heads/master`.
All previous references and other runner-group settings remain intact.
- Full application typecheck, tests, and build were not repeated locally
for this workflow-only change. This PR's CI and review are pending.

## Risks

New versions of the trusted workflow take effect for new callers after
merge to master. Keep code-owner review and master protection enabled.
Existing administrator pull-request bypasses remain unchanged.
Third-party action pins, runner routing, and infrastructure are
unchanged. Older callers still use their SHA pins; their allowed refs
remain in place.

## Model Used

OpenAI GPT-6 through Codex performed implementation and orchestration;
its exact runtime variant and context-window size were not exposed.
OpenAI `gpt-5.6-luna` with high reasoning inspected workflow assumptions
and applied the approved runner-group setting. Both used code and tool
access.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-15 09:43:24 -05:00