## Thinking Path
> - Paperclip is the open source control plane people use to manage AI
agents for work.
> - Local coding adapters currently spawn their CLI processes directly
on the Paperclip host.
> - CLI-native approval and sandbox flags do not provide a reliable host
filesystem or network boundary.
> - An agent can therefore inspect unrelated host files or fetch
external material when an operator needs stronger isolation.
> - The confinement must stay opt-in so existing local adapter behavior
does not change unexpectedly.
> - This pull request adds a shared Linux Bubblewrap spawn layer for
workspace filesystem and deny/allowlist network scopes.
> - The benefit is enforceable defense in depth around Codex and Claude
local runs while preserving explicit provider connectivity.
## Linked Issues or Issue Description
### What happened?
`codex_local` and `claude_local` processes could read arbitrary host
paths and make unrestricted outbound network requests because Paperclip
did not impose a spawn-level boundary.
### Expected behavior
Operators can opt into a workspace-only filesystem view and either deny
network egress or allow exact provider/API hosts, independently of CLI
approval flags.
### Steps to reproduce
1. Run current `master` on Linux and configure a Codex or Claude local
adapter.
2. Ask the agent to read a canary file outside its active workspace.
3. Ask the agent to `curl` a public host.
4. Observe that both operations succeed without a Paperclip-level
confinement option.
### Environment
- Paperclip commit: `c36f1a4af` / current `master` base.
- Deployment mode: Linux local dev or self-hosted server.
- Installation: built from source.
- Adapters: Codex and Claude Code.
- Database: not related.
## What Changed
- Added a shared Bubblewrap process wrapper with opt-in
`filesystemScope: "workspace"`, managed/extra path mounts, private
`/tmp`, and Linux-only validation.
- Added `networkScope: "deny" | "allowlist"`; both use a private network
namespace, while allowlist mode exposes an exact-host HTTP(S) proxy over
a Unix-socket bridge.
- Wired Codex and Claude local CLI execution through the wrapper and
forced scoped auto runs onto the CLI lane because ACP processes are not
covered.
- Added unit and gated Bubblewrap canaries for outside-file denial,
workspace writes, direct network denial, allowlisted forwarding, and
rejected destinations.
- Documented both scopes, provider allowlist examples, Bubblewrap
requirements, and default-off behavior.
## Verification
- `pnpm exec vitest run
packages/adapter-utils/src/local-process-sandbox.test.ts
packages/adapters/codex-local/src/server/acp.test.ts
packages/adapters/claude-local/src/server/acp.test.ts` — 34 passed, 4
gated Bubblewrap tests skipped by default.
- `pnpm --filter @paperclipai/adapter-utils typecheck`
- `pnpm --filter @paperclipai/adapter-codex-local typecheck`
- `pnpm --filter @paperclipai/adapter-claude-local typecheck`
- `pnpm --filter @paperclipai/adapter-utils build`
- `pnpm --filter @paperclipai/adapter-codex-local build`
- `pnpm --filter @paperclipai/adapter-claude-local build`
- Attempted the gated tests with a vendored Bubblewrap binary; this
container blocks unprivileged namespace setup (`setting up uid map:
Permission denied` / loopback `RTM_NEWADDR: Operation not permitted`),
so kernel-level execution remains for CI or a namespace-enabled Linux
host.
## Risks
- Bubblewrap must be installed and unprivileged user/mount/network
namespaces must be enabled on the host; scoped runs fail clearly if the
prerequisite is missing.
- Allowlist mode depends on the coding CLI honoring standard
`HTTP_PROXY` / `HTTPS_PROXY` variables; custom providers must list every
required exact hostname and port.
- Exact-host allowlists intentionally reject wildcards, which is safer
but may require operators to enumerate multi-host provider setups.
- No behavior changes unless an operator enables `filesystemScope` or
`networkScope`.
> This aligns with the ROADMAP direction toward safer remote and
sandboxed agent environments and does not duplicate an open PR or issue
found in the repository search.
## Model Used
- OpenAI GPT-5.5 (`gpt-5.5`) via Codex CLI, with reasoning, repository
tool use, shell execution, code editing, and test execution. The serving
context-window size is not exposed to the agent.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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>
## Thinking Path
> - Paperclip is the open source control plane people use to manage
AI-agent companies
> - Budgets and spend telemetry are control-plane safety features, not
just reporting
> - Local Codex and Claude adapters can execute through either ACP or
their native CLI engines
> - The ACP lane records usage and reported cost, but CLI JSON output
often reports tokens without a price
> - The CLI lane was either losing per-run usage semantics or coercing
missing cost to zero, making real usage indistinguishable from a
genuinely free run
> - This pull request preserves CLI usage as per-run totals and records
token-bearing runs without a reported price as explicitly unpriced
ledger events
> - The benefit is accurate usage accounting and a visible pricing gap
instead of silently misleading zero-cost telemetry
## Linked Issues or Issue Description
Refs #9471
Refs #9230
**Bug description**
A `codex_local` run using the CLI engine can emit a final
`turn.completed` event with millions of input tokens and tens of
thousands of output tokens while the agent's spend ledger remains
indistinguishable from a true zero-usage, zero-cost run. Claude CLI
output has the same missing-price edge case.
**Expected behavior**
Token-bearing CLI runs should persist their usage. If the adapter
reports a price, the ledger should record it as reported; if the CLI
reports usage but no price, the ledger should explicitly mark the event
as unpriced rather than silently treating missing price data as a
reported `$0` cost.
**Reproduction shape**
1. Configure `codex_local` with `engine: cli`.
2. Run a task that produces a `turn.completed` usage payload.
3. Observe token usage in the run stream.
4. Before this change, missing price data is represented as ordinary
zero-cost spend and the CLI usage basis is not consistently propagated.
## What Changed
- Mark Codex and Claude native CLI usage totals as `per_run` and
propagate that basis through success and failure results.
- Stop coercing missing Claude CLI cost to `0`.
- Add `cost_status` to cost events with `reported` and `unpriced`
values, including an idempotent migration and shared validation/types.
- Persist token-bearing runs without a reported price as `unpriced`
ledger events while retaining zero cents until an authoritative price
exists.
- Add parser, execute-path, heartbeat-accounting, and cost-service
regression coverage for both local CLI adapters.
- Document the cost-status invariant and CLI accounting behavior.
## Verification
- `pnpm exec vitest run
packages/adapters/codex-local/src/server/parse.test.ts
packages/adapters/claude-local/src/server/parse.test.ts
server/src/__tests__/codex-local-execute.test.ts
server/src/__tests__/claude-local-execute.test.ts
server/src/__tests__/heartbeat-cost-accounting.test.ts
server/src/__tests__/costs-service.test.ts` — 6 files / 102 tests
passed.
- `pnpm --filter @paperclipai/shared typecheck`
- `pnpm --filter @paperclipai/db typecheck` — includes migration
numbering and safety checks.
- `pnpm --filter @paperclipai/adapter-codex-local typecheck`
- `pnpm --filter @paperclipai/adapter-claude-local typecheck`
- `pnpm --filter @paperclipai/server typecheck`
## Risks
- Existing cost rows default to `reported`, preserving current
interpretation; only new token-bearing events with absent cost are
marked `unpriced`.
- This change does not invent model pricing. Budget hard stops still
cannot charge an unknown amount, but operators and evals can now
distinguish missing pricing from a genuinely reported zero cost.
- Consumers that enumerate cost-event fields should tolerate the
additive `costStatus` field.
> 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 `gpt-5.3-codex`, with repository tool use
and code execution; default reasoning mode.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
Co-authored-by: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - The browser UI depends on the Inter font family for its intended
visual baseline
> - The app previously referenced remote Google Fonts stylesheets at
runtime
> - That meant self-hosted, offline, or privacy-sensitive deployments
could lose the intended typography or depend on an external request
> - This pull request bundles the required Inter variable font files
with the UI and serves them from the app
> - A normal UI test now covers the static assets and CSS wiring without
adding a package script or build step
> - The benefit is a more reliable, self-contained UI that does not rely
on third-party webfont hosting
## Linked Issues or Issue Description
No public GitHub issue was found for this exact gap.
**Subsystem affected**
ui/ — React + Vite board UI
**Problem or motivation**
Paperclip's UI should ship the webfont assets it references so
production and self-hosted deployments render consistently without
reaching out to Google Fonts at runtime.
**Proposed solution**
Bundle the Inter variable font files under the UI public assets, load
them with local `@font-face` declarations, document the bundled assets,
and cover the source assets/CSS wiring with a normal UI Vitest test.
**Alternatives considered**
Keeping the remote stylesheet dependency is simpler, but leaves
deployments dependent on external font hosting. Using system fonts only
would avoid the asset footprint, but changes the intended UI typography.
**Roadmap alignment**
This is a focused UI reliability/polish fix, not a roadmap-level core
feature.
**Additional context**
Searched public GitHub issues and PRs for `webfonts
repo:paperclipai/paperclip`; no duplicates or closely related open items
were found.
## What Changed
- Added bundled Inter variable font assets and their notice under
`ui/public/fonts/`.
- Replaced remote Google Fonts imports with local `@font-face`
declarations using relative public-asset URLs that remain subpath-safe
from built CSS.
- Documented the local font asset expectation in development and UI spec
docs.
- Removed the follow-up font asset checker scripts and package/build
wiring after review feedback clarified they are not required for
building the UI.
- Added `ui/src/lib/ui-font-assets.test.ts` to verify the shipped WOFF2
files, notice text, and CSS font references through the normal UI test
suite.
## Verification
- `pnpm --filter @paperclipai/ui exec vitest run
src/lib/ui-font-assets.test.ts --config vitest.config.ts`
- Passed.
- Confirms the bundled font files exist, are WOFF2 files, have notice
coverage, and are referenced by `ui/src/index.css`.
- `pnpm --filter @paperclipai/ui build`
- Passed.
- Confirmed the UI still builds after removing the checker from
`ui/package.json`.
- Confirmed `ui/dist/fonts/` contains `InterVariable.woff2`,
`InterVariable-Italic.woff2`, and `NOTICE.md` after the build.
- The UI build emitted existing warnings about `::highlight(...)`, a
dynamic/static import overlap for `MarkdownEditor.tsx`, unresolved
relative public font URLs left for runtime resolution, and large chunks,
but completed successfully.
## Risks
Low risk. This adds static font assets and swaps the font source from a
remote stylesheet to same-origin files. The main tradeoff is a larger
repository/UI asset footprint from the bundled `.woff2` files.
> 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, GPT-5-based coding agent, tool-enabled terminal/GitHub
workflow with reasoning support.
## 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>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies.
> - This branch accumulated multiple already-tested control-plane,
adapter runtime, invite, workspace, plugin, and UI quality fixes on the
primary Paperclip checkout.
> - `origin/master` advanced while those commits were still local, so
the branch needed to be preserved and reconciled before review.
> - Splitting the branch commit-by-commit against the new base produced
overlapping conflicts with recently merged upstream PRs.
> - This pull request keeps the remaining branch as one standalone PR
because the final diff is 38 files after removing screenshot artifacts,
under Greptile's 100-file cap, and can be merged independently after
review.
> - The benefit is that none of the local work is lost, the branch is
now based on current `origin/master`, and reviewers can evaluate the
reconciled changes in one place.
## What Changed
- Merged the local accumulated branch with current `origin/master` and
resolved the invite-flow overlaps from the newer upstream companies
query helper.
- Preserved the local fixes for invite existing-member behavior, invite
link copy fallback, reusable workspace selection, worktree auth, static
SPA fallback, markdown wrapping, plugin slot registration, cloud
upstream UX/server polish, project sorting, and related tests.
- Removed screenshot artifacts from the PR per review request.
- Kept the PR under the requested file limit: 38 files changed, with no
`pnpm-lock.yaml` or `.github/workflows/*` changes.
## Verification
- `NODE_ENV=test pnpm exec vitest run
ui/src/pages/CompanyInvites.test.tsx ui/src/pages/InviteLanding.test.tsx
ui/src/pages/Projects.test.tsx ui/src/plugins/slots.test.ts
ui/src/components/MarkdownBody.test.tsx
server/src/__tests__/invite-accept-existing-member.test.ts
server/src/__tests__/static-index-html.test.ts
server/src/__tests__/execution-workspaces-service.test.ts
server/src/__tests__/better-auth.test.ts
server/src/__tests__/worktree-config.test.ts`
- `NODE_ENV=test pnpm --filter @paperclipai/ui typecheck`
- `NODE_ENV=test pnpm --filter @paperclipai/server typecheck`
- Confirmed `git diff --name-only origin/master...HEAD | wc -l` is `38`.
- Confirmed no PR diff entries match `pnpm-lock.yaml`,
`.github/workflows/*`, or `screenshots/*`.
## Risks
- Medium review risk because this is a bundled rescue PR rather than
several narrow feature PRs.
- Invite flow and company cache behavior overlapped with newer upstream
changes; the merge resolution intentionally keeps the shared
`companiesListQueryOptions` helper while preserving local
existing-member invite behavior.
- Visual review evidence is no longer attached in-repo because
screenshots were removed from this PR per review 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 — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
- OpenAI Codex, GPT-5-based coding agent, with repository tool access,
terminal execution, and git/GitHub CLI operations.
## 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 run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] UI screenshots were intentionally removed from this PR per review
request
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: CodexCoder <codexcoder@paperclip.local>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies.
> - Agent creation can happen through local runtimes, managed runtimes,
and external agents that onboard through invites.
> - The old OpenClaw-oriented invite UX lived under company
settings/invites and made a gateway-specific path look like a company
access setting.
> - That hid the broader bring-your-own-agent flow and forced operators
to leave the add-agent modal when adding an external agent.
> - This pull request moves external agent invite generation into the
add-agent modal and makes the copy agent-oriented instead of
OpenClaw-only.
> - The benefit is a clearer agent-first onboarding path while company
invites stay focused on human access.
## What Changed
- Added an external-agent invite branch to the add-agent modal,
including a dedicated prompt result view with Back navigation.
- Added a shared agent onboarding prompt builder and focused modal
coverage for prompt replacement/back navigation.
- Removed the agent invite prompt UI from Company Settings and Company
Invites, leaving Company Invites focused on human access links and
invite history.
- Updated the hidden OpenClaw Gateway runtime hint to direct operators
to the add-agent invite flow instead of presenting it as a blocked
runtime card.
- Updated invite/onboarding docs, storybook coverage, and server-side
onboarding copy toward generic agent language while preserving existing
gateway compatibility.
## Verification
- `pnpm -r typecheck`
- `pnpm build`
- `FAKE_BIN="$(mktemp -d)/bin"; mkdir -p "$FAKE_BIN"; printf
'#!/bin/sh\nexit 1\n' > "$FAKE_BIN/tailscale"; chmod +x
"$FAKE_BIN/tailscale"; PATH="$FAKE_BIN:$PATH" pnpm test:run`
- `pnpm test:run` without the fake `tailscale` shim was also attempted;
it failed only in two pre-existing CLI tailnet fallback tests because
this host has a real Tailscale address (`100.125.202.3`) where those
tests expect no Tailscale.
- Focused confirmation for that host-env issue: `FAKE_BIN=...
PATH="$FAKE_BIN:$PATH" pnpm exec vitest run --project paperclipai
cli/src/__tests__/network-bind.test.ts
cli/src/__tests__/onboard.test.ts`
- Manual UI verification: served UI locally in light mode, opened
add-agent modal, generated external agent prompt, verified the generated
prompt replaces the form and Back returns to the form.
### Screenshots



## Risks
- Existing OpenClaw gateway compatibility remains, but operators now
discover external agent onboarding from the add-agent modal instead of
company settings.
- Agent invites still appear in the invite history table, so that page
may show agent-scoped invite rows even though it no longer creates agent
onboarding prompts.
- Low migration risk: no schema changes.
> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.
## Model Used
- OpenAI Codex, GPT-5 coding agent in Codex desktop; tool-enabled
repository, shell, browser, and GitHub workflow. Context window size was
not exposed by the runtime.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies.
> - Heartbeat runs are the control-plane record of each agent execution
window.
> - Long-running local agents can exhaust context or stop while still
holding useful next-step state.
> - Operators need that stop reason, next action, and continuation path
to be durable and visible.
> - This pull request adds run liveness metadata, continuation
summaries, and UI surfaces for issue run ledgers.
> - The benefit is that interrupted or long-running work can resume with
clearer context instead of losing the agent's last useful handoff.
## What Changed
- Added heartbeat-run liveness fields, continuation attempt tracking,
and an idempotent `0058` migration.
- Added server services and tests for run liveness, continuation
summaries, stop metadata, and activity backfill.
- Wired local and HTTP adapters to surface continuation/liveness context
through shared adapter utilities.
- Added shared constants, validators, and heartbeat types for liveness
continuation state.
- Added issue-detail UI surfaces for continuation handoffs and the run
ledger, with component tests.
- Updated agent runtime docs, heartbeat protocol docs, prompt guidance,
onboarding assets, and skills instructions to explain continuation
behavior.
- Addressed Greptile feedback by scoping document evidence by run,
excluding system continuation-summary documents from liveness evidence,
importing shared liveness types, surfacing hidden ledger run counts,
documenting bounded retry behavior, and moving run-ledger liveness
backfill off the request path.
## Verification
- `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts
server/src/__tests__/run-continuations.test.ts
server/src/__tests__/run-liveness.test.ts
server/src/__tests__/activity-service.test.ts
server/src/__tests__/documents-service.test.ts
server/src/__tests__/issue-continuation-summary.test.ts
server/src/services/heartbeat-stop-metadata.test.ts
ui/src/components/IssueRunLedger.test.tsx
ui/src/components/IssueContinuationHandoff.test.tsx
ui/src/components/IssueDocumentsSection.test.tsx`
- `pnpm --filter @paperclipai/db build`
- `pnpm exec vitest run server/src/__tests__/activity-service.test.ts
ui/src/components/IssueRunLedger.test.tsx`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm --filter @paperclipai/server typecheck`
- `pnpm exec vitest run server/src/__tests__/activity-service.test.ts
server/src/__tests__/run-continuations.test.ts
ui/src/components/IssueRunLedger.test.tsx`
- `pnpm exec vitest run
server/src/__tests__/heartbeat-process-recovery.test.ts -t "treats a
plan document update"`
- `pnpm exec vitest run server/src/__tests__/activity-service.test.ts
server/src/__tests__/heartbeat-process-recovery.test.ts -t "activity
service|treats a plan document update"`
- Remote PR checks on head `e53b1a1d`: `verify`, `e2e`, `policy`, and
Snyk all passed.
- Confirmed `public-gh/master` is an ancestor of this branch after
fetching `public-gh master`.
- Confirmed `pnpm-lock.yaml` is not included in the branch diff.
- Confirmed migration `0058_wealthy_starbolt.sql` is ordered after
`0057` and uses `IF NOT EXISTS` guards for repeat application.
- Greptile inline review threads are resolved.
## Risks
- Medium risk: this touches heartbeat execution, liveness recovery,
activity rendering, issue routes, shared contracts, docs, and UI.
- Migration risk is mitigated by additive columns/indexes and idempotent
guards.
- Run-ledger liveness backfill is now asynchronous, so the first ledger
response can briefly show historical missing liveness until the
background backfill completes.
- UI screenshot coverage is not included in this packaging pass;
validation is currently through focused component tests.
> 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, GPT-5.4, local tool-use coding agent with terminal, git,
GitHub connector, GitHub CLI, and Paperclip API 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 run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
Screenshot note: no before/after screenshots were captured in this PR
packaging pass; the UI changes are covered by focused component tests
listed above.
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip is the control plane for autonomous AI companies.
> - V1 needs to stay local-first while also supporting shared,
authenticated deployments.
> - Human operators need real identities, company membership, invite
flows, profile surfaces, and company-scoped access controls.
> - Agents and operators also need the existing issue, inbox, workspace,
approval, and plugin flows to keep working under those authenticated
boundaries.
> - This branch accumulated the multi-user implementation, follow-up QA
fixes, workspace/runtime refinements, invite UX improvements,
release-branch conflict resolution, and review hardening.
> - This pull request consolidates that branch onto the current `master`
branch as a single reviewable PR.
> - The benefit is a complete multi-user implementation path with tests
and docs carried forward without dropping existing branch work.
## What Changed
- Added authenticated human-user access surfaces: auth/session routes,
company user directory, profile settings, company access/member
management, join requests, and invite management.
- Added invite creation, invite landing, onboarding, logo/branding,
invite grants, deduped join requests, and authenticated multi-user E2E
coverage.
- Tightened company-scoped and instance-admin authorization across
board, plugin, adapter, access, issue, and workspace routes.
- Added profile-image URL validation hardening, avatar preservation on
name-only profile updates, and join-request uniqueness migration cleanup
for pending human requests.
- Added an atomic member role/status/grants update path so Company
Access saves no longer leave partially updated permissions.
- Improved issue chat, inbox, assignee identity rendering,
sidebar/account/company navigation, workspace routing, and execution
workspace reuse behavior for multi-user operation.
- Added and updated server/UI tests covering auth, invites, membership,
issue workspace inheritance, plugin authz, inbox/chat behavior, and
multi-user flows.
- Merged current `public-gh/master` into this branch, resolved all
conflicts, and verified no `pnpm-lock.yaml` change is included in this
PR diff.
## Verification
- `pnpm exec vitest run server/src/__tests__/issues-service.test.ts
ui/src/components/IssueChatThread.test.tsx ui/src/pages/Inbox.test.tsx`
- `pnpm run preflight:workspace-links && pnpm exec vitest run
server/src/__tests__/plugin-routes-authz.test.ts`
- `pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts
server/src/__tests__/workspace-runtime-service-authz.test.ts
server/src/__tests__/access-validators.test.ts`
- `pnpm exec vitest run
server/src/__tests__/authz-company-access.test.ts
server/src/__tests__/routines-routes.test.ts
server/src/__tests__/sidebar-preferences-routes.test.ts
server/src/__tests__/approval-routes-idempotency.test.ts
server/src/__tests__/openclaw-invite-prompt-route.test.ts
server/src/__tests__/agent-cross-tenant-authz-routes.test.ts
server/src/__tests__/routines-e2e.test.ts`
- `pnpm exec vitest run server/src/__tests__/auth-routes.test.ts
ui/src/pages/CompanyAccess.test.tsx`
- `pnpm --filter @paperclipai/shared typecheck && pnpm --filter
@paperclipai/db typecheck && pnpm --filter @paperclipai/server
typecheck`
- `pnpm --filter @paperclipai/shared typecheck && pnpm --filter
@paperclipai/server typecheck`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm db:generate`
- `npx playwright test --config tests/e2e/playwright.config.ts --list`
- Confirmed branch has no uncommitted changes and is `0` commits behind
`public-gh/master` before PR creation.
- Confirmed no `pnpm-lock.yaml` change is staged or present in the PR
diff.
## Risks
- High review surface area: this PR contains the accumulated multi-user
branch plus follow-up fixes, so reviewers should focus especially on
company-boundary enforcement and authenticated-vs-local deployment
behavior.
- UI behavior changed across invites, inbox, issue chat, access
settings, and sidebar navigation; no browser screenshots are included in
this branch-consolidation PR.
- Plugin install, upgrade, and lifecycle/config mutations now require
instance-admin access, which is intentional but may change expectations
for non-admin board users.
- A join-request dedupe migration rejects duplicate pending human
requests before creating unique indexes; deployments with unusual
historical duplicates should review the migration behavior.
- Company member role/status/grant saves now use a new combined
endpoint; older separate endpoints remain for compatibility.
- Full production build was not run locally in this heartbeat; CI should
cover the full matrix.
## Model Used
- OpenAI Codex coding agent, GPT-5-based model, CLI/tool-use
environment. Exact deployed model identifier and context window were not
exposed by the runtime.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge
Note on screenshots: this is a branch-consolidation PR for an
already-developed multi-user branch, and no browser screenshots were
captured during this heartbeat.
---------
Co-authored-by: dotta <dotta@example.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Heartbeat service now resolves session state per-task using agentTaskSessions,
with resolveNextSessionState handling codec-based serialization and fallback
to legacy sessionId. Queued runs are chained — when a run finishes or is reaped,
the next queued run for the same agent starts automatically. Queued runs for
an agent with an already-running run wait instead of failing.
Add task-sessions list endpoint and extend reset-session to accept optional
taskKey for targeted session clearing. Block pending_approval agents from
API key auth. Update agent/company delete cascades to include task sessions.
Update spec docs with task-session architecture.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move doc/specs/ui.md to doc/spec/ui.md. Move plans/module-system.md to
doc/plans/. Add doc/spec/agents-runtime.md and docs/ reference specs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add run log store as sixth component with pluggable storage adapter.
Rename wakeup triggers (ping→on_demand, add automation). Clarify
lightweight event timeline vs full-log storage separation. Fix
Companies page loading/error state layout shift.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Define agent execution runtime, adapter protocol, wakeup orchestration,
and live status delivery. Covers process and HTTP adapters, heartbeat
scheduling, run lifecycle, and status streaming.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>