Commit Graph
15 Commits
Author SHA1 Message Date
DottaandPaperclip 0a5f1546ee feat(cases): add reusable prompt workflows (#17114)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Cases keep facts, documents, and one primary task across agent
handoffs.
> - Each case currently needs its own procedure text.
> - Agents need to reuse procedures and move cases between them without
replacing the task.
> - This change adds company workflow definitions with a name and
Markdown prompt.
> - Existing handoff and document transactions preserve authority,
revisions, and recovery.
> - Cases remain behind `experimental.enableCases`.

## Linked Issues or Issue Description

Refs #16959. Related proposal: #3951 uses task graphs and a visual
editor. This change extends existing Cases with prompt definitions and
keeps its current handoff model.

**Problem or motivation**

Agents cannot share a reusable procedure across cases or inspect a
case's movement between procedures.

**Proposed solution**

Add name-and-prompt workflow definitions. Adopt a prompt into the
primary task's revisioned workflow document through a handoff. Keep
phases as free text.

**Alternatives considered**

Defer graphs, workflow versions, run entities, role schemas, authoring
screens, and Spec Kit integration.

**Roadmap alignment**

This extends the existing Cases experiment and same-task review flow. It
adds no work queue or new execution engine. The maintainer approved this
scope in the implementation plan.

## What Changed

- Add company-scoped definition storage, shared request schemas, REST
routes, and four optional Cases tools.
- Accept a workflow ID at kickoff. Agent handoffs can adopt, refresh,
preserve, or detach a workflow.
- Capture prompt text and the document base revision at acceptance.
Apply workflow, phase, and document revision together after outgoing
execution settles.
- Hold conflicting document edits for recovery. Preserve cancellation,
replay, and restart behavior.
- Show current workflow names and captured transition names/phases in
Work, history, and Audit.
- Update instructions, API/tool contracts, capability maps, and the
isolated workflow journey.
- Pin bounded workflow prompt reads to a content fingerprint;
continuation conflicts on edits and can restart safely.
- Remove experimental Cases/workflow/Mermaid guidance from the always-on
native prompt. Extract runtime-context prompt strings into a
CODEOWNERS-protected constants file while preserving the public imports.
- Refresh Copilot’s pinned source identity to v57, including the
extracted prompt file and retaining historical identities.

## Verification

Local checks: repository `pnpm -r typecheck` and `pnpm build` pass on
the prompt-extraction tree (`88222d45d8`). Full repository coverage
previously completed through the supported isolated shard groups (1,082
general server suites, 161 serialized suites, and all three workspace
groups). The earlier default serial run was interrupted and remains
incomplete. The first sharded run retained the failures described below;
targeted corrections and separate limited-concurrency reruns pass. All
CI jobs, security checks, and the 5/5 Greptile review passed on
`fc1bd79c28`. Fresh CI and review are pending for the prompt extraction
in `88222d45d8`. Focused verification passes: real-database handoff
recovery and reuse; 2,002 native-tool/API contract checks; 144 Runner
catalog/discovery checks; 27 Runner context/coverage checks; 37
case/Audit UI checks; and Product E2E oracle calibration. Token gates,
migration safety/numbering, module boundaries, capability maps, and
generated tool/Storybook catalogs pass. The final route/context
corrections pass 49 API/native-tool tests, 90 real-database handoff
tests, and server typecheck; 142 Copilot installation/sidecar tests pass
with the refreshed identity.

Greptile’s first review found that successive prompt pages could mix
definitions after an edit. The fix returns a content fingerprint,
requires it for continuation, and rejects edits with 409. Strict
live/catalog schemas pass (171 Runner checks). The 2,005 API/OpenAPI
tests pass; the initial native regression caught compression’s weak ETag
prefix, and all 23 native integration tests pass after handling it. The
regression covers same-length edits and a four-byte restart window. No
stored version fields or entities were added.

The prompt extraction passes all 462 checks across six focused suites,
including persisted-context recovery and provider transport. The first
local transport attempt lacked the required debug Runner binaries (102
failures, retained); after building the normal prerequisites, all 283
tests in that suite pass without source or assertion changes. Existing
saved snapshots retain their recorded prompt text, and new executions
use core-only prompt v7. The extracted prompt source is now covered by
both CODEOWNERS and Copilot’s source fingerprint.

Live-provider evidence is separate from those simulated checks: the
isolated API-key campaign `reusable-workflows-api-final-2026-10-21`
passed with local code matching `a1d73b4652`. Four actual Codex API runs
read the adopted task documents, moved one case A → B → A on the same
task, completed normally, and passed all nine durable checks. Browser
assertions verified the current workflow/phase, historical names/phases,
five handoff records including terminal completion, and the completed
original task. Cleanup passed. The local report remains under
`tests/runner-e2e/results/reusable-workflows-api-final-2026-10-21/`; no
credentials or screenshots are committed.

CI initially caught an omitted route-inventory entry and a stale pinned
instruction-source hash; both are corrected and separately verified.
Local serialized coverage also recorded an unrelated environment-route
socket disconnect and activity-route timeout; their separate 11-test and
17-test suites passed without code or timeout changes. An unchanged
chunked-webhook check also passed its separate four-test rerun. The
initial adapter/database workspace groups hit time and resource limits
under default worker counts; complete reruns with `VITEST_MAX_WORKERS=2`
pass, including all 55 database files and 211 tests. The UI/CLI groups
passed 837 files and 9,442 tests in the original run. Original failures
remain retained and are not regraded.

Earlier failed live campaigns remain unchanged: subscription HTTP 429
before agent execution; an obsolete exact-four-row oracle that rejected
the valid terminal fifth row; and a chat-marker expectation that did not
account for the existing explicit-comment presentation policy. The final
fixture requires terminal completion and places the marker in its
authoritative comment. Positive/negative oracle tests and the fresh live
campaign pass.

## Risks

- The additive migration adds a table and nullable case/handoff fields.
Existing rows keep null workflow metadata; no assignments are inferred.
- Adoption can wait on an intervening task-document edit. Recovery must
cancel the old intent and accept a new one after readback.
- Shared definition edits affect future adoptions. Existing case copies
keep their revisions.
- The feature remains experimental. This PR does not merge or deploy the
change.
- Live acceptance covers native Codex before the prompt extraction; this
cleanup has contract/transport verification rather than a new
live-provider campaign. The refreshed Copilot identity has static
compatibility evidence, not new live-provider qualification.

## Model Used

OpenAI Codex, configured model ID `gpt-6-astra`, xhigh reasoning. Used
terminal execution, file editing, and tool calls. The active
context-window size is not exposed.

## Checklist

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

> - Paperclip manages AI agents and their work.
> - An agent workflow needs persistent facts and a safe way to transfer
work.
> - Creating a task for each phase splits the objective, discussion,
workspace, and review policy.
> - A case can retain the facts while one primary task moves between
agents.
> - Transfers must survive process failure and preserve private access,
budgets, and completion gates.
> - This pull request adds durable case handoffs, native case tools, and
read-only case pages.
> - Prompts describe the workflow. Existing task controls decide when
work can run and finish.

## Linked Issues or Issue Description

**Problem or motivation**

Prompt-driven agent teams need a persistent record that can move through
triage, implementation, verification, and correction. Ordinary
reassignment does not provide a durable instruction, safe release
barrier, or recoverable delivery receipt for an agent handing off its
own running task.

**Proposed solution**

Extend standalone cases with one primary task, a descriptive phase,
retained access sources, and a handoff ledger. Apply assignments after
source execution and workspace settlement. Deliver each transfer through
the existing durable wake queue. Provide `create_case`, `read_case`,
`update_case`, and `handoff_case` in the native runner. Creation
requires kickoff and explicit workflow text. An explicit handoff to
`done` closes the case when normal task completion is accepted.

**Alternatives considered**

Do not add a workflow engine, filesystem queue, configured state graph,
or one task per phase. The workflow document combines transition prose
with an optional Mermaid `stateDiagram-v2` map. The server does not
execute the diagram. The Pipelines experiment removed on master stays
removed.

**Roadmap alignment**

This extends Agent Reviews and Approvals, Enforced Outcomes, Bounded Run
Recovery, and Activity Log attribution. Existing approval, review,
budget, privacy, workspace, and responsible-user rules remain
authoritative.

Related work: [ordinary handoff wake
recovery](https://github.com/paperclipai/paperclip/pull/15019). This
feature adds a separate persisted case-handoff receipt and release
barrier.

## What Changed

- Add case routing fields, retained access sources, durable handoff
history, delivery leases, and replay-safe migrations.
- Keep the same primary task across agent phases. Preserve each
returning agent's own session and the task's workspace.
- Fence outgoing mutations, wait for provider and workspace release, and
recover delivery without duplicate task comments or runs. Recheck
current assignment permissions as the original caller before applying a
delayed transfer. Scope a run Stop to that run’s own handoff intents, so
repeated old Stop requests preserve newer work. Cancelling terminal
intent without a source run also requires fenced current task ownership,
including native retries and preparation with an old checkout. For Cloud
callers, revalidate current stack membership with an uncached Cloud RPC
and derive owner elevation from the current managed setting.
- Keep case reads, documents, assets, Audit, and live events inside
retained task/project permissions.
- Add native case creation/read/update/handoff tools. Store required
workflow text and initial documents on the first task. Page oversized
case facts and referenced document bodies through the dedicated tool
with bounded UTF-8 JSON, current routing versions, snapshot conflicts,
and current source authorization on every page.
- Add read-only case lists and detail pages, task-style list controls,
compact dotted field tables, linked handoff tasks, and case filters in
Audit.
- Add native/legacy integration tests, migration/restart tests, browser
coverage, and bounded live receipt fixtures. Extend the trusted sandbox
condition to cover the new subscription fixture profile.
- Hide obsolete paused-agent warnings on completed or cancelled task
threads.
- Synchronize the company-switch settings test with React effects after
a CI failure. Preserve its security assertions and production remount
behavior.

## Verification

The branch directly includes master `9ef434fe79`. The required `ci /
verify` and `ci / e2e` gates pass on head `765fccd67c`. [Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/39464348614)
passes typecheck, build, tests, and all eight browser shards. Security
checks pass. [Greptile gives this exact head
5/5](https://github.com/paperclipai/paperclip/pull/16959#issuecomment-6291156549),
with no unresolved review threads. The optional Paperclip Review check
remains queued because its assigned agent is paused. It is not a
required branch check. No check result was overridden.

Local workspace typecheck and build pass after the master merge, along
with database migration checks, token gates, map checks, Storybook
catalog checks, and the Copilot profile identity check. Standard builds
refresh Runner vendor output. Focused checks pass 2,008
API/paging/context tests and 7 strict case protocol tests. The final
commit changes one test fixture only; its ten tests, UI typecheck, and
token gates pass. No production source changed in that commit.

On current head `765fccd67c`, all **194 critical workflow tests**
executed and passed with no skipped tests in those files:

- 38 Stop/ownership tests, including board completion intent, native
retries, stale Stop, and preparation with an old checkout.
- 2 actual legacy process/HTTP handoff tests, including scratch failure,
a closed-stdio child that continues writing, and recovery through a
fresh worker after the process group stops.
- 5 migration tests, including SQL column metadata, preserved null
authority context, and all six prior-numbering receipts.
- 3 process-settlement and 5 scratch tests.
- 88 handoff-service, 18 heartbeat handoff, and 21 native case-tool
integration tests.
- 7 bounded case/document-read projection tests and 7 strict
protocol-contract tests.

The current CI checkout was `fed65d49`, merging `765fccd67c` into master
`9ef434fe79`. Its new document regressions reconstruct exact
Unicode/escaped bodies and revisions through real native authority and
authenticated HTTP with generic API tools disabled. They cover
case-owned, primary-task, and linked-task documents; routing on every
page; stale document snapshots; access loss and unlinking;
unrelated/foreign/private sources; system documents; and quarantined
content. Active-task document tools retain their existing behavior.
These are current-head test results from the first CI attempt; the
browser-only retry did not rerun these suites.

The full `64fdd3403f` CI failed one separate settings test: after a
company switch, it observed an unsettled API-key draft. The production
component and test were unchanged from prior green source. Production
switches remount both keyed settings layers; the test directly reused an
unkeyed view and used a timer tick instead of waiting for React effects.
The final commit replaces that fixture synchronization with React `act`.
The exact secret-clearing assertions and all timeouts remain unchanged.
The original assertion failure remains recorded; no unchanged retry was
used. The narrow unchanged baseline and fixed fixture each pass 10
tests.

The upstream result-paging merge preserves case capture namespaces and
current asset privacy. Its API integration suite executed 39 of 41 tests
successfully, with two skipped; the optional assigned-result PRP
integration test was skipped. Neither skipped suite is counted in the
194 critical tests or as live provider proof.

All 361 upstream migration entries and SQL bodies remain unchanged. Six
case migrations follow master as 0363–0368 with identical SQL hashes.
Official Drizzle generators produced the combined metadata and five
retained snapshots. Generation reports no schema changes, and the
snapshot drift test passes. The earlier `ce361ae5d0` CI passed on
attempt 1, including its then-current 179 critical tests. Fresh review
later identified unusable document references with generic API tools
disabled; the bounded document reads and ten additional authenticated
HTTP tests address that finding.

The full local `pnpm test:run` attempt was cancelled after this Mac
exhausted PostgreSQL semaphore capacity; it is **not** counted as a
pass. Later database attempts also stopped before assertions or skipped,
including one sandbox socket denial. Two original stale-Stop regressions
did reproduce the bug against the old source. A REST serialization
assertion passed after two preserved database-startup failures. No test
timeout was increased. All 194 assertions listed above executed and
passed in current-head CI. The complete 385-file, 3,963-test UI shard
also passed after the fixture repair.

A configured-provider receipt workflow passed 13 backend checks across
triage → implementation → verification → correction → done, using one
task and four work runs. The saved receipt is revision 2 with total 6
USD; case and task both closed. The original canonical attempt remains
failed because its browser assertion confused the terminal destination
with completed-task tooltips. The corrected full browser verifier passed
on the same retained database and original runs, with no additional
provider calls. The last clean-build browser readback is on
`6a86c54a53`; later changes affect recovery, authorization, bounded
reads, and settlement. Accounted work cost is a $1.010574 rate-card
estimate; provider billing and setup-probe usage are unavailable.

Copilot profile 49 passed the unchanged seven-fixture private protocol
pack (46/46 checks, no retries) and the product file-edit canary after
master's completion-replay change. All 60 bound implementation hashes
remain unchanged on the current source. Historical profile-47/48
identities and results remain intact. See the [profile-49 compatibility
record](https://github.com/paperclipai/paperclip/blob/codex/persistent-case-handoffs/doc/plans/2026-10-20-copilot-completion-recovery-compatibility-v49.json).
This is bounded compatibility evidence, not a fresh full matrix,
installed-package product test, or Daytona rollout.

Preserved CI failures and retries:

- On `20662930ac`, Slack managed setup failed a five-second success
assertion after reload. Its test/application path was unchanged from a
prior green head. One unchanged-source retry passed all 25 tests in that
shard; no source or timeout changed.
- On `9402b4f17a`, two CI workers received shutdown signals at 15:24:19
UTC. Neither log had an assertion failure before interruption. One
unchanged-source retry of each passed all Runner static checks and all
32 tests in browser shard 6; both aggregates passed. The next head,
`7b4374edaf`, passed all CI without retries.
- On `295f289b5a`, serialized shard 9 timed out during its first
device-login test, then the next test found an active login lease.
Direct login/test paths were unchanged from a prior green head. Cold
import plus a timed-out async body using the next test's mutable
actor/store is the supported fixture-race explanation; no request trace
proves that sequence. The original failure remains recorded. One
unchanged-source retry passed all 294 tests in 19 files, including all
41 device-login tests. No login source or timeout changed. The
subsequent `ce361ae5d0` CI passed without retries.
- On `64fdd3403f`, one company-switch settings assertion observed an
unsettled draft. The final test-only commit uses React `act` without
changing assertions, timeouts, or production code. On `765fccd67c`, all
ten settings tests and the complete 385-file, 3,963-test UI shard
passed.
- On `765fccd67c`, browser shard 3 completed the split-handoff
assertions, then cleanup received HTTP 500 from run cancellation after a
one-second PostgreSQL row-lock timeout. The extra chat run was reporting
completed work while teardown began. Cleanup stopped before restoring a
global experiment flag, causing a later assertion to fail. Relevant
production and test paths are unchanged from an earlier green commit.
Stop's lock order is consistent, and no nested self-lock was found; the
exact PostgreSQL blocker was not recorded. One unchanged-shard retry
passed. The original failure, trace, and downstream flag failure remain
recorded. No Stop implementation, cleanup assertion, or timeout changed.
The retry supports intermittent cleanup contention; it does not identify
the original blocking transaction.


## Risks

- Local process transfers require host-owned PID/group absence. Missing
or uncertain termination evidence keeps delivery pending, independently
of scratch setup.
- Handoff admission and task cancellation share execution ownership. New
regression tests cover temporary holds, late source writes, and
uncertain provider termination.
- Retained private sources use an intersection of existing permissions.
This intentionally fails closed when a source is missing or an existing
task cannot preserve that boundary.
- Migrations add tables and indexes. They preserve master history and
can replay over prior feature installs. Migration 0368 adds nullable
internal authorization provenance with no default or authority backfill.
Historical transfers still awaiting release without this context fail
closed; an operator must cancel them and request a new handoff.
- Delayed Cloud handoffs depend on the current Cloud membership RPC. An
unavailable, ambiguous, expired, or mismatched response holds the
handoff for retry; it does not reuse cached authority or grant access.
- Bounded reads reload and reauthorize the selected projection per page.
Underlying work grows with the data size and number of pages. Changed
data or routing requires restarting from offset zero without the old
snapshot.
- Phase names and workflow diagrams remain advisory. They do not satisfy
review or approval gates.
- This is a large, cross-cutting PR. The maintainer requested one PR for
the whole feature; the commits separate data, runtime, UI, and
qualification work.

## Model Used

OpenAI Codex, GPT-6 family, with tool use, code execution, and delegated
code review. The exact deployment model ID and context-window size were
not exposed in the session. Live fixture agents used the explicitly
configured provider model recorded in their test evidence.

## 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-20 12:46:14 -05:00
DottaandPaperclip e6dcd1e8e9 feat: add Commentary to Audit with filters and shareable messages (#16884)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents can submit suggestions and complaints while they work.
> - Operators currently need database access to read those messages.
> - That makes it hard to find feedback from one agent or share a
specific message.
> - This pull request adds a standard Commentary tab in Audit.
> - Operators can filter messages, browse 50 at a time, and share links
to full message dialogs.

## Linked Issues or Issue Description

Refs #15367, which added feedback storage and agent submission. The
duplicate search found no open PR for a commentary reader.

**Subsystem affected**

Server, shared API contracts, and the board UI.

**Problem or motivation**

Agent suggestions and complaints are stored but have no board reader.
Operators must query the database to inspect feedback.

**Proposed solution**

Add Commentary to Audit without an experimental toggle. Show previews,
agent and message-type filters, text search, and 50-message pages.
Opening a row updates the URL. A copied URL opens the full message with
its agent, task, and run context.

**Alternatives considered**

Direct database queries remain useful for operators, but do not provide
a normal product workflow. An experimental setting would add setup to a
read-only audit page.

**Roadmap alignment**

This completes the operator view for the existing feedback feature. It
supports human oversight and does not change agent execution or task
ownership.

## What Changed

- Add company-scoped, board-only list and detail endpoints with audit
permission and source-task privacy checks.
- Return bounded previews and counts. Fetch full bodies only when a
message opens.
- Add the Commentary tab, search, filters, 50-row pagination, and
URL-based selection. Audit tab destinations work in both layouts, with a
classic sidebar entry for Commentary.
- Add production Storybook examples for populated, filtered, linked,
long, paginated, empty, loading, failed, denied, mobile, and light
states.
- Update API documentation and the feature and agent access maps.

## Verification

- Final head `abc4a251c14cfbfec007542214beec528f2b18bf`: 55 checks pass;
two conditional Storybook checks are skipped. The PR workflow is
successful. Greptile is 5/5 with all findings resolved.
- Focused database, HTTP, submission, OpenAPI, and UI regression tests
cover company isolation, task privacy, filter bounds, 50-row pagination,
and copied message links.
- Browser Storybook journeys cover row opening, direct links, combined
filters, search, and pagination. Storybook uses synthetic API fixtures;
database authorization is tested separately.
- Token gates, feature maps, and Storybook catalog validation pass.
- `pnpm -r typecheck`, `pnpm build`, and `pnpm build-storybook` pass on
the rebased branch. All 80 focused tests and all 37 Audit tests pass,
including the real App route table in both layouts, task
grant/revocation through HTTP, deleted-task privacy, and URL UI
regressions. The full suite passes in the parallel PR CI matrix. The
local serial full-suite run was stopped before completion after checking
the recorded 94-minute serial duration. Local focused tests, workspace
typecheck, production build, and final server/UI checks pass.
- The linked-message Storybook test initially asserted against the
loading dialog. It now waits for the message body; both direct-link and
row-open journeys pass.
- Native and legacy deleted-task privacy regressions failed before the
fix and pass afterward. The reader checks the run task binding after the
task foreign key clears.
- A rapid search-then-agent-filter browser regression reproduced the
search overwriting the selected agent. The pending search now restarts
when URL filters change. The same browser test passes with both filters
applied.
- CI found two existing AuditHub assertions that still expected five
tabs. They now assert the six-tab model and selected-company Commentary
rendering. All 37 Audit tests pass. All other test and build jobs passed
before this test-only correction.

- The [agent-chat attachment browser
test](https://github.com/paperclipai/paperclip/actions/runs/39307881171/job/118250189664)
timed out waiting for an attachment preview. The [same shard passed on
the prior
head](https://github.com/paperclipai/paperclip/actions/runs/39306658703/job/118245498343)
with identical application code; the intervening change only updates
AuditHub unit tests. The single retry passed on the same head. The
precise cause of the earlier failure remains unconfirmed.

## Risks

- Commentary may contain sensitive task context. The reader requires
board access and audit permission, and filters source-task visibility
before returning previews, counts, or full bodies.
- Text search scans stored message bodies. Pages are bounded and full
bodies are fetched on demand.
- Offset pagination can shift if new messages arrive while paging.
Ordering uses timestamp and ID for stable ties.
- No database migration or agent submission behavior changes are
required.

## Model Used

- OpenAI Codex, GPT-6 family, with reasoning, tool use, browser
interaction, and code execution. The exact backend model ID and
context-window size are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 14:21:13 -05:00
Devin FoleyandPaperclip 799e4d556f fix: make accounting durable and synchronize cost reporting (#14997)
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-06 22:26:48 -07:00
DottaandPaperclip f589660ec0 feat(routines): add safe webhook setup and in-routine run management (#13637)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Routines turn scheduled work and external events into tasks for an
assigned agent.
> - Webhook setup was disabled, and actor authentication rejected valid
webhook bearer keys.
> - Operators need to connect and test a sending app before events can
start work.
> - This pull request adds a guided setup with durable connection tests
that cannot dispatch a task.
> - It keeps trigger management, execution tasks, and activity within
the routine.
> - The benefit is a webhook that can be configured, verified, and
operated from one place.

## Linked Issues or Issue Description

Fixes #11937.

Related: #13216 adds provider-specific Sentry support. This PR addresses
general routine setup and ingress. #6841 addresses legacy secret
bindings; this PR retains the existing secret service.

**Current behavior**

Webhook creation is disabled. Bearer deliveries can fail in agent
authentication before the routine checks its key. Setup has no safe
connection test. Runs and Activity send the operator away from the
routine.

**Proposed behavior**

Choose a schedule or a webhook. Follow the setup steps, copy credentials
or complete agent instructions, and test delivery without creating work.
Finish setup to allow future events to start tasks. Edit or remove
compact trigger cards, undo removal, and inspect tasks and activity
inside the routine.

**Reason and benefit**

An operator can verify credentials and delivery before enabling
automatic work. Durable setup state survives refreshes and restarts.
Retry receipts prevent an old test event from starting work after
activation.

## What Changed

- Add a production trigger wizard using reusable Slack setup navigation
and footer components.
- Add schedule and webhook choices, one-time credentials, agent
instructions, and live connection feedback.
- Persist pending setup, test delivery receipts, connection status, and
reversible trigger removal.
- Keep setup checks free of routine runs, tasks, and agent wakeups.
Preserve delivery idempotency after activation.
- Add compact trigger cards, inline editing, key rotation, pause
controls, removal, and Undo.
- Keep Runs and Activity in the routine. Use the shared task list and
compact activity rows.
- Permit only exact public delivery POSTs through actor authentication.
Retain webhook authentication, JSON-object validation, and log
redaction.
- Add production-backed Storybook states and focused server, database,
and UI coverage.
- Document signing modes, setup checks, retries, rotation, HTTPS
ingress, and navigation.

## Verification

- Full workspace typecheck, build, and token gates passed on the rebased
branch. Storybook also builds.
- Focused routine, middleware, logging, shared wizard, and UI coverage
passes on the rebased branch: 195 tests across 14 files. The migration
passed on a fresh PostgreSQL database and on two repeated applications.
- Browser testing used the real app, database, and a deterministic
process worker through Tailscale HTTPS and the current Cloud proxy code.
- Verified rejected keys, safe setup deliveries, persisted state after
restart, activation, retry deduplication, key rotation, schedule
editing, removal, and Undo.
- Fresh bearer and GitHub-signed deliveries created tasks that the
worker checked out and completed. Runs and Activity stayed within the
routine.
- Current Cloud ingress tests passed. Public delivery POSTs passed
through without a browser session; management routes remained gated.
- All 54 current-head PR checks pass, including general and serialized
tests, all eight browser E2E shards, typecheck, build, runner checks,
security checks, and the canary dry run. Two optional Storybook jobs are
skipped by workflow conditions.
- Greptile is 5/5 on commit `7ea63a61e`, with no unresolved review
threads. The stale connection-status finding is fixed and covered by a
regression test.
- No production deployment was performed.

## Risks

- Migration 0281 adds three trigger columns and a test-receipt table. It
is additive and safe to reapply. Apply it before running the new server.
Existing triggers remain live by default.
- Requests without delivery IDs are new events after activation. Senders
must reuse an event's delivery ID for retries.
- Completed webhooks keep normal dispatch behavior. Their management
connection check can start work; the UI states this.
- Removing a trigger archives it. Undo restores the URL and credentials.
Permanent deletion remains available through the existing API.
- Public ingress must remain restricted to the delivery POST route. The
tenant verifies credentials. Cloud sleeping-stack behavior is unchanged.
- Shared setup components also serve Slack. Existing setup contracts and
navigation tests cover that integration.
- Senders must use application/json with an object. Other media types
receive 415.

## Model Used

OpenAI Codex, based on GPT-6, 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-19 10:49:05 -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 f449b05bc5 feat(apps): unify permissions and action testing (#12802)
## Thinking Path

> - Paperclip is the control plane for companies that use AI agents.
> - Apps give humans and agents controlled access to external services.
> - The existing app detail flow split permissions, tests, setup, and
activity across separate pages.
> - The split made access rules harder to understand and made reconnect
work hard to find.
> - New write actions also defaulted to Ask first, which did not match
the intended connection policy.
> - This pull request combines permission control and action testing,
removes the setup page, and moves connection activity into Audit.
> - The benefit is one clear place to configure, test, reconnect, and
review each app.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The installed app Permissions, Test, Setup, and Activity views.

**Subsystem affected**

Cross-cutting. This change updates the React UI, shared app defaults,
server permission behavior, tests, smoke scripts, and connection
documentation.

**Current behavior**

App access and action testing use separate pages. The app detail view
also links to a setup page after installation. Connection activity uses
a separate tab. New write actions default to Ask first.

**Proposed behavior**

Permissions uses the connection access language from the initial flow.
It includes searchable Read and Write sections, a three-state permission
control, and a Test dialog for each action. Reconnect appears below a
Needs attention header on Permissions and Review. Old Setup and Test
links redirect to Permissions. Old Activity links redirect to the
filtered company Audit feed. New write actions default to Allowed.

**Reason and benefit**

A person can understand and test app access without moving between
several pages. Reconnect work stays visible where the person reviews the
connection. Audit events use one consistent feed and filter model. New
connections have the intended default policy.

**Breaking changes**

The Setup, Test, and app Activity tabs are removed. Existing deep links
redirect to their replacement pages. Existing saved action permissions
do not change. Only defaults for new write actions change.

**Additional context**

This builds on the managed app connection work in #12728. A search found
no duplicate open pull request or issue.

## What Changed

- Combined action testing with Permissions.
- Added searchable Read and Write action groups.
- Added Off, Ask first, and Allowed controls with tooltips.
- Added an action Test dialog with agent selection, arguments, and
formatted results.
- Removed the installed-app Setup and Activity tabs.
- Added reconnect guidance to Permissions and Review when a connection
needs attention.
- Routed connection activity into the company Audit feed and preserved
the Apps & tools filter in streamlined Audit.
- Moved connection removal to the Connectors-page management menu.
- Made new write actions default to Allowed across connection creation
paths.
- Updated regression tests, browser suites, smoke scripts, and
connection documentation.

## Verification

- `pnpm check:token-gates`
- `pnpm exec vitest run packages/shared/src/app-definitions.test.ts
server/src/__tests__/generic-mcp-connection.test.ts
server/src/__tests__/tool-access-service.test.ts
ui/src/components/AppConnectionSidebar.test.tsx
ui/src/pages/apps/AppDetail.test.tsx
ui/src/pages/apps/AppNotConnected.test.tsx
ui/src/pages/apps/AppsConnect.test.tsx ui/src/pages/apps/Browse.test.tsx
ui/src/pages/apps/Connections.test.tsx
ui/src/pages/apps/composio-services.test.ts
ui/src/pages/audit/AuditFeed.test.tsx
ui/src/pages/tools/PasteConfigTab.test.tsx` (517 tests passed)
- `pnpm exec vitest run ui/src/pages/apps/app-detail/TestPanel.test.tsx
ui/src/pages/audit/AuditHub.test.tsx
ui/src/pages/audit/AuditFeed.test.tsx
ui/src/pages/apps/AppDetail.test.tsx ui/src/pages/apps/Browse.test.tsx`
(96 tests passed)
- Targeted Playwright verification for connection removal, rename on
Permissions, inline action testing, and Smoke Lab Audit evidence (5
flows passed)
- `pnpm -r typecheck`
- `pnpm build`
- `pnpm test:run` completed with 5,755 passing tests and 20 unrelated
macOS harness failures. The failures use `/tmp` versus `/private/tmp`,
invalid ports above 65535, and workspace fixtures outside this change.

## Risks

- Low migration risk. This change has no database migration.
- Old app-detail URLs depend on redirect compatibility.
- New connections grant write actions by default. Finalization remains
configure-authorized and audited, Ask first and Off remain available per
action, and existing connections keep their saved policy.

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

## Model Used

OpenAI Codex, exact model ID `gpt-5`. The client does not expose the
context-window size. The model used reasoning, repository tools, code
execution, and browser verification.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-03 21:23:26 -05:00
scotttong b1f4910ee5 feat(ui): refine streamlined workspace surfaces (#12747) 2026-09-02 23:55:55 -07:00
scotttong 597fd63b61 feat(ui): add streamlined navigation foundation (#12746) 2026-09-02 23:55:43 -07:00
scotttong 4d82f5eaea copy: unify user-facing "company" wording to "organization" (#12243) 2026-08-27 01:04:55 -07:00
e43f187cad feat(secrets): add human-approved secret proposals (#9934)
## Thinking Path

> - Paperclip is the control plane people use to manage AI-agent
companies.
> - Agents can encounter credentials during work.
> - Directly creating live secrets or bindings would bypass human
governance.
> - Proposal records must remain inert and separate from live secret
resolution until an authorized human approves them.
> - Approval must reuse the existing secret-create and protected
agent-config write paths.
> - This pull request adds the propose, review, approve, and reject
lifecycle.
> - The benefit is that agents can safely hand credentials into
Paperclip without exposing plaintext or gaining authority to activate
them.

## Linked Issues or Issue Description

Follow-on to #9921, which established run-bound agent secret access.

**Problem / motivation:**

Agents can receive credentials during work. There is no governed way for
them to propose a credential or binding without exposing plaintext in
work artifacts or immediately creating live access.

**Proposed solution:**

Store agent-authored proposals outside live secret tables. Encrypt each
proposed value and register exact-value redaction when Paperclip
receives it. Require an authorized human to approve or reject each
proposal. Approval executes through the normal write paths as the human
approver. Binding proposals can target only the proposer or its downward
reporting chain under the restrictive V1 policy.

**Alternatives considered:**

We rejected live secrets with a `proposed` status. That design would put
untrusted rows in resolver, list, and sync paths. It would also allow
uniqueness squatting. We rejected direct agent binding writes because a
binding is an agent-config write and must keep the existing human
permission gate.

**Roadmap alignment:**

This change extends the run-bound agent secret-access foundation in
#9921 with a governed proposal workflow.

## Security Verdict

Q0 SecEng verdict: **PASS-with-required-changes**. The review accepted
the separate proposal-table design and required the implementation to:

- fail closed unless both encryption and exact-value run redaction
registration succeed;
- scrub ciphertext idempotently on reject, withdraw, and expiry, with
audit-visible state;
- treat agent justification as hostile input and foreground action,
target, provenance, and approver permissions;
- snapshot and re-check the target agent plus reports-to chain at
approval to prevent org-chart laundering;
- make cascade approval atomic and fail closed if either secret creation
or binding authorization fails;
- deny low-trust, `skill_test`, `task_bridge`, and non-run-bound sources
consistently; and
- execute approval through the normal human secret/config write paths,
including protected-change gates.

Those requirements are implemented and covered by focused service,
route, and UI tests. Residual V1 risk remains the accepted 14-day
encrypted retention window. Proposal-time redaction also cannot clean a
value that leaked before the propose call.

## What Changed

- Added `company_secret_proposals`, migration `0207`, shared proposal
contracts, and a state-machine service for create, approve, reject,
withdraw, cascade, expiry, and ciphertext scrubbing.
- Added run-bound agent proposal routes and board review routes. The
routes derive provenance from authentication and enforce source
restrictions, company isolation, chain-of-command checks,
approval-as-approver, wake-on-resolution, and dual audit trails.
- Added durable per-run exact-value redaction registration so proposal
values remain redacted on later read surfaces.
- Added the Secrets **Proposals** tab and agent configuration **Proposed
access** rows. The UI shows fingerprint and length only. It also frames
agent justification as untrusted input, runs permission preflight,
supports approve and reject actions, and confirms cascades.
- Updated OpenAPI, agent skill guidance, API reference documentation,
and focused server and UI regression coverage.
- Rebased the branch onto current `master` and renumbered the proposal
migration after `0206`.

## QA Acceptance Results

Q5 QA verdict: **PASS — 9/9 acceptance criteria met**, with one Minor
non-blocking follow-up.

- **AC1:** proposed values never echo, never appear in live
lists/resolvers, and expose only fingerprint + length to board
reviewers.
- **AC2:** restrictive `self_and_reports` matrix passes: self/downward
allowed; upward/lateral denied.
- **AC3:** secret approval uses the normal create path, honors rename
overrides, records proposer/approver provenance, and scrubs ciphertext.
- **AC4:** approved bindings materialize and resolve through the target
agent's runtime list/fetch routes.
- **AC5:** pending-secret bindings require cascade; cascade succeeds
atomically and permission failures leave nothing applied.
- **AC6:** reject, withdraw, dependent rejection, and expiry paths scrub
ciphertext and preserve reasons/audit state.
- **AC7:** token/source and approver denial matrix passes through live
checks plus focused route tests.
- **AC8:** proposal lifecycle events and reused
`secret.created`/config-write events form the required dual audit trail;
origin-issue notification and wake are queued.
- **AC9:** both review surfaces render and execute correctly; UI
approval materializes the binding.

QA also confirmed zero plaintext occurrences for all exercised proposal
values in server logs. The single finding is that the company-level
`bindingTargetPolicy` toggle is not wired yet. V1 is hardcoded to the
restrictive `self_and_reports` policy. The matrix is correct and the
follow-up is tracked separately, so QA classified it as non-blocking.

## Verification

- Focused server proposal and redaction suite: 83 tests pass.
- Focused proposal review UI suite: 54 tests pass.
- Embedded-Postgres migration reapply test: 1 test passes with the
documented 30-second timeout.
- `pnpm --filter @paperclipai/db typecheck` passes, including migration
numbering and safety checks.
- `pnpm --filter @paperclipai/shared typecheck` passes.
- `pnpm --filter @paperclipai/ui typecheck` passes.
- `pnpm check:token-gates` passes with all gates clean.
- Q5 exercised the complete propose, review, approve, bind, and
runtime-resolve flow over real HTTP, JWT, and database paths. It
verified 9/9 acceptance criteria.

## Risks

- Proposal ciphertext is retained encrypted for up to 14 days while
pending. Terminal-state and expiry scrub paths reduce but do not remove
server-compromise risk during that window.
- The V1 target policy is restrictive but not yet company-configurable.
A separate follow-up owns that change.
- A new migration can require another renumber if another migration
lands before maintainers merge this pull request.

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

## Model Used

- OpenAI Codex coding agent. The exact runtime model ID and
context-window size are not exposed. The agent used reasoning,
repository editing, terminal execution, Paperclip API, and GitHub CLI
capabilities. Q3 UI work also records Claude Opus 4.8 assistance in its
commit trailers.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 21:49:40 -05:00
Nicky LeachandPaperclip f5e9ca3e89 fix(adapters): keep user-scoped env bindings on the agent Test action (#10926)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The agent Test action builds adapter config from the form.
> - The build-config parser kept plain and secret_ref bindings.
> - It dropped user_secret_ref bindings on the create path.
> - This PR shares one parser that keeps every binding shape.
> - The test path now sends the same env binding set that a real run
sees.
> - The benefit is one fix across every adapter build-config path.

## Linked Issues or Issue Description

**What happened?**
The agent Test action dropped a user-scoped env binding in create mode.
The same agent config worked in a real run. Related public PRs: #10115,
#9321, #9921, #8825.

**Expected behavior**
The Test action should keep user-scoped env bindings and resolve them
like a real run.

**Steps to reproduce**
1. Set a user-scoped env binding on an agent config form.
2. Run Test in create mode.
3. The probe runs without the variable.

**Paperclip version or commit**
c09d2509e3

**Deployment mode**
Local dev (pnpm dev)

**Agent adapter(s) involved**
Not adapter-specific (core bug)

**Database mode**
Embedded PGlite (default — DATABASE_URL unset)

**Additional context**
This change is not Claude-specific.

## What Changed

- Added a shared env binding parser in `@paperclipai/adapter-utils`.
- Replaced the eight adapter build-config copies with the shared helper.
- Kept `plain`, `secret_ref`, and `user_secret_ref` bindings intact in
create mode and edit mode.
- Preserved the runtime merge behavior from the earlier env merge
change.

## Verification

- Author-recorded test run:
`packages/adapter-utils/src/env-bindings.test.ts`
- Author-recorded test run:
`packages/adapters/claude-local/src/ui/build-config.test.ts`
- Author-recorded test run: six adapter build-config test files
- Author-recorded typecheck: `tsc --noEmit` for adapter-utils and the
eight adapter packages
- GitHub checks: all required PR checks pass on PR #10926.
- Greptile review: 5/5 with no open comments.

## Risks

- The change touches adapter config assembly.
- A wrong binding shape would change test-time probe input.
- Tests cover the binding types and the create-mode path.

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

## Model Used

OpenAI GPT-5, code execution and repo inspection.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-05 17:18:41 -07:00
8142e54150 feat(activity): merge the audit page into one rich Activity page (#10838)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The board has two different pages for change history: a basic
Activity list and a rich Audit feed
> - The two pages show the same kind of information, so an operator must
guess which page to open
> - The basic list also caps at 200 rows and has no filters, so it hides
older changes
> - This pull request merges both pages into one Activity page that is
built on the rich audit feed
> - The page adds a scope toggle for all actors or agent actions only,
and it hides privileged controls from members who do not have the audit
permission
> - The benefit is one obvious place to answer "who changed what", for
every member, with filters and full history

## Linked Issues or Issue Description

Related pull requests in this stack (open both before this one):

- Refs #10830 — adds the company prefix to the board audit route.
- Refs #10831 — adds the two-tier all-actors scope to the audit
endpoint. This pull request calls that scope.

This branch is stacked on those two pull requests. The diff therefore
shows their commits until they merge. After they merge, this pull
request contains only the last two commits: the page merge and the
actor-label fix.

**Problem or motivation**

The board has two overlapping history pages. `/:company/activity`
renders a plain list that is capped at 200 rows and has no filters. The
audit page renders a filtered, paginated feed of agent actions, but it
is a separate sidebar item and it was reachable only by members with the
audit permission. A member who wants to know who changed an issue must
know which of the two pages answers the question.

**Proposed solution**

Keep one sidebar item, "Activity", and build it on the rich feed. Add a
scope toggle: "All activity" reads every actor kind, and "Agent actions"
keeps the earlier audit behavior. Put the scope in the `mode` query
parameter so a person can link to it. Show the responsible-user filter
and the CSV export only to callers that the server answers at the
privileged tier. Redirect the earlier audit paths to the merged page
with the agent scope preset, so old links continue to work. Delete the
plain list page.

**Alternatives considered**

Keeping both pages and adding filters to the plain list. That duplicates
the feed logic and keeps the "which page?" problem. Deleting the audit
page instead was also rejected, because the audit feed has the
pagination, filters, and export that the plain list does not.

**Roadmap alignment**

The roadmap marks the activity log and action attribution as shipped.
This change improves that shipped capability. It does not add a new
subsystem.

## What Changed

- Added a scope toggle to `AuditFeed`. "All activity" requests
`actorScope=all`, and "Agent actions" keeps the earlier agent-only
request. Cursor pagination works in both scopes.
- Stored the scope in the `mode` query parameter, so a person can
bookmark or share a scope.
- Made the page chrome permission-aware. The toggle, the
responsible-user filter, and the CSV export appear only when the server
answers at the privileged tier. A basic member sees the shared feed and
no upsell wall.
- Replaced the sidebar "Audit" item. The sidebar now has one "Activity"
item.
- Redirected `/:company/audit` and the unprefixed `/audit` to
`/:company/activity?mode=agents`.
- Deleted the earlier `ui/src/pages/Activity.tsx` list page and the
`CompanyAudit` page wrapper. Added `CompanyActivity` as the single route
target.
- Fixed the actor label for stripped rows. The basic tier removes the
agent id but keeps the actor kind, so every agent row rendered as
"System". Rows now fall back to the actor kind: "Agent", "User",
"Plugin", or "System".
- Widened the responsible-user filter control, which truncated its own
label.
- Resolved agent names on the basic tier. The basic tier removes the
privileged `agentId` but keeps the acting principal `actorId`, and the
company agent directory this page already reads is
authorization-filtered. The feed therefore resolves an agent actor from
`agentId` first and from an agent-typed `actorId` second. Hiding the
name only in the UI gave no confidentiality benefit, because any reader
could join the retained id against the readable directory. Agents that
the directory filters out still fall back to the generic kind label. No
server payload or permission was widened.
- Fixed a stuck state in the access-downgrade recovery. A downgrade
between cursor requests leaves full-tier and basic-tier pages in one
cache, which starts a single recovery refetch. If that refetch did not
clear the mix, the cached pages kept the condition true, the "Refreshing
audit access…" banner rendered permanently, and it hid the error state
together with its "Try again" button. The banner is now tied to an
outstanding attempt. The refetch effect also depended on the whole query
object, which changes identity every render, so it repeated the request
on each render; the attempt is now tracked in state and runs once per
downgrade.
- Kept the agent detail "Audit" tab unchanged. That tab passes a locked
agent id, which keeps the earlier privileged scope and hides the toggle.

The `GET /companies/:id/activity` endpoint stays. The dashboard still
reads it. This pull request does not change that endpoint.

## Verification

- `pnpm exec vitest run ui/src/pages/audit/AuditFeed.test.tsx
ui/src/App.activity-routing.test.tsx ui/src/lib/company-routes.test.ts
ui/src/components/Sidebar.test.tsx
server/src/__tests__/activity-routes.test.ts
server/src/__tests__/agent-action-audit-routes.test.ts` — all tests
pass.
- New `ui/src/App.activity-routing.test.tsx` drives the real route
table. It asserts that the company activity path resolves, and that both
the company audit path and the unprefixed audit path reach the activity
path with the agent scope preset.
- New `AuditFeed` tests cover the scope toggle, the basic tier without
privileged chrome, the locked-agent case, the actor-kind fallback label,
basic-tier name resolution, and both downgrade-recovery paths (the
refetch errors, and the refetch returns a still-mixed pair).
- Mutation-checked the three new guards: disabling each one fails the
test that covers it, so none of them pass vacuously.
- `pnpm -r typecheck` is clean. Both design token gates are clean.
- Rendered every state in a browser at 1440x900 and at 390x844: both
scopes, the basic member view, the loading state, the error state, the
filtered-empty state, and the true-empty state. A designer reviewed the
renders and approved them.

## Risks

- The default company page now reads the all-actors scope, which returns
more rows than the earlier agent-only query. Cursor pagination and the
existing page limit bound each request.
- The page is now visible to every company member. The server decides
what each member sees. The UI only hides controls that the caller cannot
use. Refs #10831 for the server rules and tests.
- The basic tier now shows agent names that the previous revision
withheld. The name was already recoverable from the retained `actorId`
through the readable agent directory, so this closes an inconsistency
rather than widening access. A security reviewer chose this outcome over
stripping `actorId`.
- Old audit links now redirect. The redirect keeps the agent scope, so a
person who bookmarked the audit page sees the same rows.
- Low migration risk. There is no database change.

> The roadmap marks activity log and action attribution as shipped. This
change improves that existing capability.

## Model Used

Claude Opus 5 (`claude-opus-5`, 1M context) with extended thinking and
tool use, run through Claude Code.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [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>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 23:30:23 -05:00
DottaandPaperclip 68ddd6a7a0 feat(activity): add two-tier all-actors audit feed (#10831)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Operators need one activity feed for human, agent, plugin, and
system changes
> - The existing audit endpoint returns only rows that have agent
attribution
> - The full audit view also requires a dedicated permission
> - This pull request adds an explicit all-actors scope with basic and
privileged access tiers
> - The benefit is that company members can inspect the shared activity
history while sensitive attribution and export controls stay protected

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The company audit activity endpoint and the board audit route.

**Subsystem affected**

Server REST API and board UI routing/API contracts.

**Current behavior**

The agent-action audit endpoint excludes activity without an agent ID.
It also rejects company members who do not have the full audit
permission.

**Proposed behavior**

Callers can opt into `actorScope=all`. A company member receives all
actor kinds with sensitive attribution fields removed. A permitted board
user receives complete rows and can use attribution filters. The default
scope and CSV permission remain unchanged.

**Reason and benefit**

The board needs one chronological activity source for user, agent,
plugin, and system actions. A two-tier response keeps the feed useful
without widening access to detailed attribution or export capabilities.

**Breaking changes**

None. The endpoint keeps the existing agent-only scope and permission
behavior by default.

## What Changed

- Added `actorScope=all` to the unified audit query and included
activity from every actor type.
- Added a company-readable basic tier that removes run,
responsible-user, agent, and details attribution.
- Kept attribution filters and CSV export behind
`audit:view_agent_actions`.
- Added route and integration coverage for basic readers, permitted
readers, pagination, filter denial, and all actor kinds.
- Added the missing unprefixed `/audit` redirect and company route
classification.

## Verification

- `pnpm exec vitest run server/src/__tests__/activity-routes.test.ts
server/src/__tests__/agent-action-audit-routes.test.ts
ui/src/lib/company-routes.test.ts --reporter=verbose` (35 tests passed)
- `pnpm -r typecheck`
- `pnpm test:run`
- `pnpm build`

## Risks

- The all-actors query can return more rows than the legacy agent-only
query. Cursor pagination and existing limits bound each request.
- The basic tier intentionally exposes action and actor-kind context. It
removes detailed run, agent, responsible-user, and details attribution.
- The legacy endpoint behavior remains the default, which reduces
compatibility risk.

> The roadmap marks activity log and action attribution as shipped. This
change improves that existing capability and does not introduce a
separate workflow system.

## Model Used

- OpenAI Codex, `gpt-5.6-sol`, 114K context, agentic reasoning with tool
use and code execution.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-04 23:07:38 -05:00
71231dfa38 feat(audit): agent audit UI — company page + per-agent tab (#9744)
## Thinking Path

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

## Linked Issues or Issue Description

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

Refs #9731 and #9735.

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

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

## What Changed

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

## Verification

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

## Screenshots and Manual QA

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

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

## Risks

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

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

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-31 19:09:13 -07:00