Commit Graph
13 Commits
Author SHA1 Message Date
DottaandPaperclip 5e4cc01073 feat(workspaces): keep remote files off the webserver disk (#18403)
Keep native sandbox workspace files independent of the webserver disk. Use encrypted saved versions and Postgres ownership so a replacement server can recover files and continue work. Enable the path by default for new eligible workspaces when durable storage is configured.

Preserve explicit opt-outs and existing host workspaces. Include safe snapshot repair, Files access, import, migration and retention. Bound saved-Files resources, preserve imported Git recovery, reject unfinished Git operations, publish immutable concurrent captures, and verify permanent object-version deletion.

Validated 471 targeted local controls, build/typechecks, all 40 CI partitions, fresh Greptile 5/5 and security review. The PR records original failed attempts and scoped retries.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 14:54:01 -05:00
DottaandPaperclip dce383c733 perf(server): stop recurring attention retention scans (#18388)
Reviewed and verified at a61af9888e.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 12:28:40 -05:00
28e38da7e6 fix(server): wake native result commits from durable work (#17748)
## Thinking Path

> - Paperclip manages AI agents and preserves their results through
failures.
> - Native completion must save workspace output before it commits the
accepted result.
> - The orphan recovery pass repeatedly revisits this work even when the
subsystem is idle.
> - Accepted results, workspace receipts, retry dates and leases already
provide durable truth.
> - This PR wakes a scoped worker from those writes and schedules only
real unfinished work.
> - It preserves existing finalization authority and keeps later
projection and resource recovery separate.

## Linked Issues or Issue Description

Refs #17734 and #17717. This is slice 53 of the existing sleep stack,
targeting master after parent #17734 merged at
`a019d00a393b57f531afe8dd8ab0b8a1820d1c4c`.
A current search found no duplicate accepted-result commit PR.

**What problem does this solve?**
Native accepted-result recovery currently depends on periodic orphan
scanning. Quiet instances keep doing work to discover that no result
needs a commit.

**What improvement do you propose?**
Use the shared delivery coordinator with transaction-bound producer
signals. Reconstruct unfinished results at startup. Preserve saved retry
and lease deadlines. Remove only uncommitted-result execution from the
periodic pass.

**Why is this useful?**
The accepted-result worker becomes quiet with no work or retained
completed history. Real results and completed workspace operations
reactivate it without a polling delay. This does not claim that the
whole server or database can sleep yet.

## What Changed

- Track the initial result-commit sweep through shutdown without
blocking HTTP readiness on recovery locks.
- Keep ordinary company-only finalization hints from reconstructing
dormant result work. Existing company settings and dedicated owner
signals remain supported.

- Add a native result-commit worker. Bind candidates by company, issue,
run, accepted result and a successful workspace receipt. Exclude
committed, terminal, held and pending-effect work.
- Signal both accepted-result writers and workspace receipt writes
before their transaction changes. Extend the existing finalization
fanout for retry, lease, effect and completion transitions.
- Add an optional atomic due-date check to the existing finalizer claim.
A lease collision or later retry does not consume a failed attempt.
- Signal native retry cancellation so it removes the saved wake after
commit.
- Register through the existing heartbeat suppression and shared
delivery lifecycle. Preserve outer commit/rollback, drain/resume,
settings activation and shutdown behavior.
- Delegate only uncommitted-result execution from the periodic orphan
pass. Keep committed projection and resource settlement recovery
enabled.
- Add real producer/lifecycle tests and a detailed audit. No new tables,
provider branches or per-feature timers.

## Verification

- Current local source `2af88fa55f961a74340880240019f6cd31e21bf1`
incorporates the parent with a normal merge. All 1,203 parent-only, nine
owned-only and 12 automatic shared paths are preserved. The only manual
conflict keeps the new result fanout inside the existing ordinary
issue/run scope guard. The complete package tree matches parent profile
80 byte-for-byte.
- Controlled real-database regression: the original result-only unscoped
fanout produces three candidate SELECTs for routine company hints. The
same zero-query assertion passes after restoring the scoped fanout. A
real workspace receipt and accepted result then commit exactly one
decision and return to quiet. Red and green restore production bytes
exactly. Twenty cases outside the focused pattern are not counted as
passing there.
- The complete main selection passes **1,746 cases in 16 files**,
without skips, in 277.97 seconds. This includes all 21 result-worker
lifecycle cases and 82 startup cases, including held result recovery,
HTTP readiness and shutdown joining. Separate process recovery passes
410 cases in 162.42 seconds and external-chat response passes 273 in
53.41 seconds. Total: **2,429 distinct passes in 18 complete files**,
with no skips. Normal merge `998239b019defe52e7b5d64f884de4e871ccd736`
adopts the actual parent squash and preserves this complete tested child
tree.
- Production server typecheck, build, module boundaries, migration order
and source identity checks pass. Fifteen dedicated PostgreSQL 17
databases use the unchanged migration 413 schema. Embedded-only calls
use the existing fresh-per-call recovery helper. All temporary imports
restore byte-exact, and every selected test hash matches after
completion. No assertion or timeout is relaxed.
- Runner validation belongs to the unchanged parent package tree: 130
passing installation/compatibility/transport cases, 22 installed
ACPX/Grok contract cases and 26 native-provider Rust cases. One existing
opt-in closed Pi snapshot case is skipped because its distribution root
is not configured. This does not claim live provider qualification.
- Earlier Greptile 4/5 on `656f6722be1aedf3d52b7f853956e15838204278`
correctly identified startup blocking on result recovery. The prior
branch `108cf0dc8296bf451b721ddac55ecbcd035d00f0` already tracks its
ready promise through the existing lifecycle owner. Current full startup
acceptance verifies the fix in the merged context. The later Greptile
service error is not a pass; current-head acceptance now passes: all 57
checks are clean, including protected CI and security. Greptile gives
5/5 on `b2efdb2dbbbef5b2227ffa2bd2a9a6cfe3867fe2`, with no actionable
findings. No Ponytail verdict is present under the authorized
missing-review policy.
- The owner audit at
`doc/plans/2026-10-26-native-result-commit-sleep-audit.md` retains
earlier failures and their disposition. These checks do not claim a full
local repository suite, deployed app/database suspension, expanded Cloud
wake coverage or measured cost savings.

## Risks

- Process-local signals cover instrumented application writes in the
owning server process. They do not cover independent SQL writers or
another replica without supported ingress. Durable startup
reconstruction remains enabled.
- The initial native decision and its run projection are separate
transactions. The periodic reconciler still repairs already-committed
results and releases resources. This PR must not be used to infer that
committed means fully settled.
- Candidate discovery adds bounded, narrow reads at startup and after
signals. No large-fleet query benchmark is claimed.
- Existing Cloud alarm coverage, host sleep safety and resource blockers
are unchanged. No deployed sleep or savings claim is made.
- Parent #17734 has merged. This PR targets master at
`a019d00a393b57f531afe8dd8ab0b8a1820d1c4c`. Fresh current-head CI and
review remain required before merge.

## Model Used

OpenAI Codex, GPT-6 family, with repository tools and code execution.
The exact serving model ID and context-window size are not exposed in
this session. No subagent was used for this slice.

## 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: Codex <noreply@openai.com>
2026-10-29 04:53:11 -05:00
a019d00a39 fix(server): wake native workspace finalization from committed work (#17734)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runs can accept a result before workspace copy-back finishes.
> - The periodic orphan pass repeatedly tries this recovery, including
cases that require operator action.
> - Copy-back needs exact ownership evidence. A generic timer cannot
grant that authority.
> - This pull request wakes workspace recovery from committed changes
and local owner completion.
> - Saved retries use the existing scheduler. Empty work, completed
barriers, and operator holds become quiet.

## Linked Issues or Issue Description

Refs #17717. This is slice 52 of the recurring-server sleep stack,
targeting master after parent #17717 merged at
`4c56702e06c698cc10d4a86514669aba0f4d9a9b`. Related work: #17709 (status
reassessment), #17687 (unsafe export recovery), and #16478 (workspace
repair holds).

This PR covers native workspace copy-back and validation. Result
commit/projection and resource settlement remain separate recovery
duties. It does not claim full-instance sleep.

## What Changed

- Register a company/run/task-scoped workspace worker. Reconstruct
accepted, unfinished work from existing records. Use saved retry and
lease deadlines.
- Notify from both accepted-result writers (control-plane and PRP
coordinator), workspace receipts, coordinator changes, operator
confirmation, retained workspace repair, and relevant task updates.
Notifications follow the outer transaction.
- Distinguish active local ownership, busy external ownership, pending
Cloud evidence, operator-required evidence, and changed bindings. Only
concrete external ownership/evidence waits receive a scoped retry.
- Preserve advisory locks, signed stop proof, exact binding checks,
physical callback joins, and existing failure policy. Join physical
operations during shutdown.
- Respect the existing heartbeat execution-suppression policy before
discovery and execution; wake suppressed work on settings activation.
- Skip physical workspace recovery in the enabled periodic orphan pass.
Keep direct/startup reconciliation and the remaining result/cleanup
recovery paths.
- Keep routine company-only finalization hints quiet. Ordinary work
requires issue/run scope; explicit settings and owner-release events
keep their company-wide contract.
- Preserve the parent's entire Runner/package tree, profile 80 and all
historical identities. Add the dated obligation, producer, lifecycle and
limitation audit.

## Verification

- Current local source: `4059b24e3ea5c623be54ade18ec9b6ab78eb0289`,
prepared by a normal merge of the current parent. The sole manual
conflict keeps ordinary workspace fanout inside the existing issue/run
guard. All 1,198 parent-only, 15 owned-only and 10 automatic shared
paths are preserved. The complete package tree matches the parent
byte-for-byte.
- Controlled regression: the original workspace-only unscoped fanout
performs three candidate SELECTs for routine company hints. The same
zero-query assertion passes with scoped fanout. A real accepted result
then produces one successful workspace settlement and returns to quiet.
The failed baseline remains in the audit.
- The first complete local group passes **1,693 cases in 14 files**,
including all 19 workspace-worker cases. It covers both accepted-result
producers, physical ownership, export retry/failure, finalization
recovery, arbiter corpus, issue recovery actions, control-plane port,
workspace recovery, heartbeat recovery, startup, retained cleanup and
native execution.
- Separate process-recovery and external-chat response files qualify the
changed recovery/settlement paths without sharing their general test
database with other files. Both pass in full: 410 process-recovery cases
in 162.79 seconds and 273 external-chat cases in 53.79 seconds. The
total is **2,376 distinct passes in 16 complete files**, with no skips.
Normal merge `5c46c52873158529736b8349e4d44658865108ee` adopts the
parent squash with this entire tested child tree unchanged.
- Production server typechecking, build, module boundaries, migration
order and source-profile checks pass. Thirteen dedicated PostgreSQL 17
fixtures use the unchanged migration 413 schema. Embedded-only paths use
the existing recovery helper with fresh per-call fixtures. All temporary
imports are restored byte-exact. No test assertion or timeout is
relaxed.
- Runner validation belongs to the unchanged parent package tree: 130
passing installation/compatibility/transport cases, 22 installed
ACPX/Grok contract cases and 26 native-provider Rust cases. One existing
opt-in closed Pi snapshot case is skipped because its distribution root
is not configured. These are source-scoped checks, with no live provider
qualification claim.
- The owner audit at
`doc/plans/2026-10-26-native-workspace-finalization-sleep-audit.md`
preserves earlier failures and their disposition. Current-head
acceptance: all 57 checks are clean, including protected CI and
security. Greptile gives 5/5 on
`7df5c9c44ea9e171be3c61b4430d3727b10f3337` with no actionable findings.
Earlier scores do not substitute for this result. No Ponytail verdict is
present under the authorized missing-review policy.
- No claim of a full local repository suite, deployed app/database
sleep, expanded Cloud wake coverage or measured cost savings is made.

## Risks

- Supported wake producers are in-process application services. This
adds no cross-replica or independent SQL-writer transport.
- A real unresolved export still needs recovery. Busy owners and pending
Cloud stop evidence retain a 30-second scoped check. No timeout
authorizes copy-back.
- Result projection and resource release still use their existing
recovery. Some existing cleanup failures remain best effort; this PR
does not infer cleanup success from a workspace barrier.
- Cloud alarm coverage and host-sleep safety remain unchanged. No
deployed suspension or cost savings have been measured.
- Parent #17717 is merged. Current base is master at
`4c56702e06c698cc10d4a86514669aba0f4d9a9b`. Fresh current-head CI and
review must pass before this slice merges.

## Model Used

OpenAI Codex, GPT-6 family, with repository tools and code execution.
The exact serving model ID and context-window size are not exposed in
this session. No subagent was used for this slice.

## 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: Codex <noreply@openai.com>
2026-10-29 04:40:01 -05:00
df6156c2e3 fix(server): wake native status reassessment from committed changes (#17709)
## Thinking Path

> - Paperclip manages agents, tasks and their durable native results.
> - Changed evidence, task authority or review retirement can require a
new status assessment.
> - Periodic orphan recovery repeatedly reads history to find these
changes.
> - This change gives reassessment an owner driven by committed changes
and saved deadlines.
> - Existing result, assessment, decision and task rows remain durable
truth.
> - The status committer still verifies current sources and authority
before writing.
> - Settled or insufficient evidence becomes quiet until a supported
producer changes it.

## Linked Issues or Issue Description

Refs #17702 (merged), #17679 and #17680. This is slice 50, now based on
master. It owns native status reassessment; workspace settlement,
retained sessions and other orphan duties remain separate.

**What happened?**

Periodic recovery repeatedly inspects completed native results. Removing
that scan without complete writer coverage or current authority checks
could strand new evidence or commit an old result over newer work.

**Expected behavior**

Reassess from existing durable facts after relevant outer transactions
commit. Retain real retry/lease deadlines and restart/drain recovery.
Preserve current authority, quality-review and supersession checks. Make
no recurring SQL when work is settled or dormant.

**Steps to reproduce**

Complete a native result awaiting evidence or review, leave it idle,
then approve a real work product or retire the selected automatic
review. Its saved result should advance once when authorized, or record
the existing nonterminal business gate, without a periodic scan.

## What Changed

- Extract reassessment and its pure status policy from finalization
recovery into their owning modules. Add a scoped worker using the
existing delivery coordinator and scheduler; no queue table or migration
is added.
- Retain the three durable discovery triggers: changed work-product
history, authoritative task status/version, or retirement of the
selected automatic completion review. Preserve selected-source,
ownership, effects, retry and lease fences under the existing committer.
- Notify from actual task/work-product, claim release, approval,
interaction, OAuth, event evidence and workspace-settlement owners
before their transaction writes. Keep provider calls outside short
transactions and nested writes behind outer commit.
- Scope ordinary milestone/finalization/coalesced-input wakes to an
issue/run. Keep genuine company authority restoration explicit. Real
Photon and coalescer regressions cover all three response/status queues.
- Move the current parent's required quality policy into the owner and
apply it to every reassessment that could complete a task. An unmet
review records the existing in-progress decision and next action,
avoiding an operational retry loop. Preserve conversation/session reset
locks and the workspace omission-barrier signal.
- Skip reassessment in periodic recovery while preserving
explicit/startup recovery and the historical supersession guard before
independent workspace work. Document the source contract, producer
inventory, failures and qualifications in the linked audit.

## Verification

- Broad source `9fddb3f0b1157df32b64fb1f22e9d6e9624470e8` passes **2731
distinct cases in 28 complete files**, with no skips: 2458
producer/owner/authority/workspace/quality cases in 394.43 seconds and
all 273 governed-response cases in 53.74 seconds. Nineteen dedicated
fresh PostgreSQL 17 databases migrate through 0413; eighteen
embedded-only invocations preserve fresh-per-call isolation through the
existing recovery helper. All 22 temporary imports restore exactly and
all 28 hashes match.
- Final runtime source `5ea3b0fd016bf7e63ba82a7044825a46a0cd2082` passes
**1211 cases in five complete affected files** in 108.23 seconds after
the narrowly reproduced evidence-trigger fix: all 43 worker, 145 corpus,
32 finalization-recovery, 968 native-session and 23 quality-review
cases. Four fresh databases plus the quality helper's own fresh fixture
use PostgreSQL 17. Its one adapted import restores exactly; all five
hashes match. The other 27 broad-run test files are unchanged. These
qualifications are source-scoped and not cumulatively double-counted.
- Required/optional real regressions reproduce retry loops on
retired-review and evidence-approval paths before repair; both become
SQL quiet afterward with unchanged assertions/time limits. Controlled
removal of only ordinary scope guards reproduces two coarse-hint SQL
failures; exact guard restoration passes. Real producer, outer
transaction, claim, authority, 103-item backlog, retry and drain cases
pass. Photon transport is mocked; callbacks, locks and observed SQL are
real.
- Normal merges preserve 12661 parent/unrelated entries, 35 owned
entries and 21 automatic shared results, with five original conflicts
reviewed explicitly. The parent's actual squash reconciliation preserves
the entire held child tree. The final quality fix changes only its owner
and tests. Fourteen added comments are removed with identical nontrivia
tokens; no directives are removed and the final comment check is empty.
- Database build, server types/build, boundaries and exact-head
migration order pass. The database tree is identical to merged #17702:
no new SQL, queue table or snapshot is generated. Earlier benchmarks,
host limitations, failed assertions and their repairs remain in
`doc/plans/2026-10-26-native-status-reassessment-sleep-audit.md` and
`doc/idle-native-status-reassessment.md`.
- This qualifies targeted external PostgreSQL behavior, not embedded
bootstrap on the semaphore-exhausted host, a full local repository
suite, deployed sleep or measured fleet savings. Fresh exact-head CI and
review remain required.

## Risks

- Notifications retain the process-local supported-writer contract.
Independent SQL writers and uncoordinated replicas are not covered by a
new transport.
- Reassessment competes with current authority changes. Existing
row/source locks and retries remain required; arbitrary missing
identities have no row to lock, so this is not a general predicate-lock
guarantee.
- Discovery pages 100 rows but retains outstanding candidates in memory.
It remains proportional to backlog size, and cancellation occurs between
queries.
- Other orphan/workspace/session duties and Cloud sleep eligibility
remain unchanged. Missing supported producer coverage could strand
dormant work, so the producer audit and real callback/transaction tests
remain part of acceptance.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, shell
execution and PostgreSQL tests. The runtime does not expose a more
specific serving snapshot or context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Codex <noreply@openai.com>
2026-10-29 03:40:01 -05:00
5e26b733b9 fix(server): finish workspace operations when the log write fails (#17415)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Before a run starts, Paperclip prepares the execution workspace (for
example `git worktree add`). Each step is a workspace operation. The
workspace operation recorder writes it as a row and as a log file on
disk.
> - When an operation fails, the recorder writes the error to the log
file, then sets the row to `failed`.
> - If that log write also fails (for example ENOSPC when the disk is
full), the recorder throws before it updates the row.
> - The row stays `running` with no `finishedAt`. The log write error
also replaces the real error of the operation.
> - This pull request makes the failure-path log write best-effort, so
the row always reaches `failed` and callers get the correct error.
> - The benefit: on a full disk, the operator sees a terminal operation
with the real failure reason. Operations do not stay "running" for ever.

## Linked Issues or Issue Description

No public issue exists. Bug description:

**What happened?**
A run failed during workspace setup on a host with a full disk (`ENOSPC:
no space left on device, write`). The stack shows the error in the
workspace operation log append inside `recordOperation`. In the failure
path, the recorder calls the log append before it updates the row.
Because the append threw again, the row stayed `running` with no
`finishedAt`. When the operation itself failed (for example a git
error), callers got the ENOSPC log error and not the git error.

**Expected behavior**
A failed workspace operation always reaches `failed` with `finishedAt`
set. Callers get the operation's own error. A log write failure must not
hide that error.

**Steps to reproduce**
1. Make the operation log append throw ENOSPC (the new tests stub
`fs.appendFile` for the log root).
2. Record an operation whose `run` throws, or whose output append
throws.
3. Before this fix: the row stays `running`, and the caller gets the
ENOSPC error and not the operation's error.

**Paperclip version or commit**
`ee29e28` (current `master`).

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

Related open PRs with disk-full handling in other places (no overlap
with this code path): #5882 (run-log rotation), #16773 (backup disk
use).

## What Changed

- `server/src/services/workspace-operations.ts`: in the
`recordOperation` failure path, the stderr log append is now best-effort
(`.catch(() => undefined)`). The stderr excerpt still records the
message, because the excerpt updates before the file write.
`logStore.finalize` was already best-effort in this path.
- `server/src/__tests__/workspace-operations-reconciliation.test.ts`:
two regression tests with log appends that fail with ENOSPC:
- The output append fails after a successful run. The row reaches
`failed` with `finishedAt` and the ENOSPC message in the stderr excerpt.
The caller gets the ENOSPC error.
- The operation itself throws. The row reaches `failed` and the caller
gets the operation's own error, not the log write error.

## Verification

- Red before the fix: both new tests failed on `master`. The row stayed
`running`, and the caller got the ENOSPC error and not the git error.
- Green after the fix: `pnpm exec vitest run
src/__tests__/workspace-operations-reconciliation.test.ts
src/__tests__/workspace-runtime-control-recovery.test.ts` passes (17
tests).
- Sibling suites that use the recorder (26 files, 945 tests): all pass
except 4 tests in `workspace-runtime.test.ts`. Those 4 tests also fail
on unchanged `master` in the same sandbox, because they need the local
pnpm and worktree CLI. This change does not cause them.
- Typecheck: `tsc --noEmit` on `workspace-operations.ts` passes. The
full server `tsc` was not run locally because the 4 GB sandbox ran out
of memory. CI runs the full typecheck.

## Risks

- Low risk. The change affects only the failure path, and only the log
file write. The success path does not change: if a log write fails after
a successful run, the operation still fails with the write error.
- The log file for a failed operation can lose its last stderr line on a
full disk. The row's stderr excerpt still has the message.

## Model Used

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

## Checklist

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

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Devin Foley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 00:30:06 -07:00
DottaandPaperclip 8751e2de46 fix(ui): distinguish finalization recovery from live observation (#14326)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The task board shows which recovery actions are active.
> - A native run can stop while a person must repair its workspace.
> - The board previously called that state “Recovery in progress.”
> - The label implied that work would continue without operator action.
> - This pull request derives the label from the recovery owner and live
continuation.
> - Operators can distinguish scheduled recovery from a repair that
needs attention.

## Linked Issues or Issue Description

**What happened?**
A blocked task showed “Recovery in progress” after native finalization
stopped and no automatic continuation remained.

**Expected behavior**
Show “Recovery needed” for an idle board repair or when no live recovery
path exists. Show “Recovery in progress” while the recorded continuation
can run, including an explicitly admitted export whose exact callback is
executing even if the old recovery action remains board-owned.

**Steps to reproduce**
1. Complete a native run whose workspace export cannot be recovered
automatically.
2. Inspect the task recovery action and badge.
3. Compare the board-owned action with the old “Recovery in progress”
label.

Related work: #14314 serializes native workspace finalization and fences
stale recovery outcomes. This change reports the recovery action that
currently owns the task.

## What Changed

- Show “Recovery needed” for board-owned active-run recovery unless the
exact native export callback is positively verified as executing.
- Require the native continuation run and a live or future continuation
before showing progress.
- Project native activity from the exact company, source issue, and run.
Include active workspace export while the original heartbeat remains
failed.
- Require an executing callback before using a running export row as
evidence. Preserve activity for long exports and clear it when the
callback joins.
- Give native resume its own card explanation. Preserve ordinary
watchdog observation behavior.
- Remove the redundant ownership sentence from all six recovery-card
explanations that used it.
- Document the labels and add regression cases for stopped, scheduled,
and active recovery.

## Verification

- Copy-only follow-up (`c68aef04c`): all 167 focused recovery UI tests
and token gates pass. No UI occurrence of the removed sentence remains.
`pnpm -r typecheck`, `pnpm build`, and current-head CI pass (54
successful checks, two optional Storybook checks skipped). Greptile is
5/5 with no open review threads. The duplicate local `pnpm test:run` was
stopped after the full CI suite passed; it did not complete locally.
- Original regressions: seven failures before the change, then 52
focused cases pass.
- Review regressions: seven UI failures and nine database failures
before the follow-up. All 75 database/API recovery tests, 167 UI tests,
and 18 workspace lifecycle/finalizer tests pass. A further three RED
cases cover explicit board retry activity; one RED case rejects orphaned
running export rows after controller loss. Wrong company, issue, run,
service, phase, and completed-operation cases remain inactive.
- Final recursive typecheck, production build, token gates, and complete
local suite coverage pass. Embedded PostgreSQL startup/socket failures
passed in isolated retries with the canonical test environment; no
expected behavior was weakened. The recovery regression added during the
earlier full run passed in its final complete 75-case file.
- Before the copy-only follow-up, all 56 CI checks passed on
`c2f84cd89c905cda85c53aaf5bb83b7250900fe6`; Greptile is 5/5 with no
unresolved review threads. The final native-activity staging repeat
passed on integrated source `2bedd0f23bf4698b1f8b818f6796900647030427`.
- Verified on a separate staging instance: a real failed Daytona
workspace export retains its board-owned repair action and displays
“Recovery needed” in the task list. The repair card remains actionable
without starting another provider turn.

- Real staged export-only repair: the actual task list showed “Recovery
in progress” while the original run had a positively identified running
export operation, then Done after exact copyback of all 20,000
nonce-bound files. The accepted result and full provider
session/turn/terminal envelopes remained unchanged. All 17 independent
final checks passed; the browser downloaded the exact 19-byte result.
The separate fixture was cleaned up with independent provider-absence
verification. A control transport process restarted during repair; it
did not submit another provider turn.

- Final deployed-source repeat on
`d884e1ab046cc76004e35e6091e9e6e2c918c9eb`: explicit per-turn ephemeral
Daytona allocation, actual browser export repair, and a saved full
activity projection referencing the exact executing export operation
with no scheduled retry. The task list showed recovery in progress, then
Done; all 21 final checks passed, including 20,000 exact host files,
unchanged provider provenance, and provider deletion only after
committed copyback. The downloaded 19-byte result matched independently.
This integrates #14334; no source change was required here.

## Risks

- The label depends on the persisted recovery action. A separate runtime
defect can still stop work; this change makes that condition visible.
- Future recovery kinds must supply a valid continuation path before
they can display progress.

## Model Used

OpenAI Codex, based on GPT-6, with code execution, browser testing, and
subagent tool use. The runtime does not expose an exact serving model
variant or context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-28 09:33:39 -05:00
DottaandPaperclip a2bf936f9a feat(workspaces): sign the workspace login handoff and gate readiness (#11671)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Managed worktree services run isolated Paperclip instances with
cloned databases.
> - A reachable service was reported as ready even when its database,
runtime identity, or login path was not usable.
> - The first candidate added verified database seeding and managed
repair in #11665.
> - This pull request consolidates that candidate with signed login
handoff and a complete readiness contract.
> - Post-QA fixes close five defects in repair identity, repair
responses, UI retry, seed journal handling, and seed-source trust.
> - The benefit is a workspace that either opens safely or reports one
accurate recovery action.

## Linked Issues or Issue Description

No public GitHub issue exists for this work, so the problem is described
here.

**What happened**

Managed workspace URLs could return HTTP 200 and report ready while
login failed. QA also found cases where repair used the wrong instance
identity, returned a generic error, left the UI stuck, rejected a safe
journal lag, or trusted a mutable workspace manifest.

**Expected behavior**

Opening a ready workspace signs the board user in to the correct
isolated instance. Provisioning and repair use a registered source and
report a structured recovery state.

**Actual behavior**

Entry depended on a password copied into the clone. Several failure
paths could publish stale readiness, hide the repair precondition, or
trust state that the workspace could modify.

**Additional context**

This pull request includes the commits first published in #11665. That
pull request keeps the original base head for review history. This
consolidated pull request is the merge candidate. Related open readiness
work includes #11575 and #11621.

## What Changed

- Adds a short-lived, signed, single-use login ticket. It binds the
user, workspace, instance, and runtime origin.
- Exchanges the ticket through Better Auth. It creates the session and
cookie through the supported adapter path.
- Adds protected workspace readiness fields for the database, clone
data, login handoff, seed phase, and runtime identity.
- Fails readiness closed when the guest has no company or
execution-workspace binding.
- Binds ticket issuance to the exact cloned user and active company
membership selected for the handoff.
- Verifies every current active board identity through the exact-user
handoff before publication or reuse.
- Gates managed runtime publication on the readiness contract and the
recorded worktree instance identity.
- Refreshes runtime work products from the live runtime row after a port
change.
- Adds one workspace access card with ready, degraded, repairing, and
failed states.
- Uses the runtime response identity for repair. It returns structured
repair precondition errors.
- Lets a valid source journal lag converge during provisioning.
- Binds seed and repair manifests to a source registered outside the
agent-writable worktree.
- Clears recovered UI errors so a successful retry can open the
workspace.
- Makes runtime tests register canonical sources and avoid ports owned
by live host listeners.
- Keeps Vitest on source suites when compiled `dist` trees exist.
- Isolates CLI and adapter tests from ambient AWS and runtime API
environment variables.
- Preserves a 404 response for cross-company workspace ID lookups before
runtime authorization.
- Makes concurrent single-flight coverage independent of
path-canonicalization scheduling order.

## Verification

The following checks passed on the integrated head:

```sh
pnpm -r typecheck
pnpm build
pnpm check:token-gates
pnpm --filter @paperclipai/db check:migrations
```

- The server source lane passed 420 files and 4,953 tests. Five tests
were skipped.
- The CLI lane passed 57 files and 385 tests.
- The database lane passed 26 files and 97 tests.
- The shared package passed 58 files and 506 tests.
- The adapter utility lane passed 640 tests. Four tests were skipped.
- The Claude adapter passed 220 tests. One test was skipped.
- The Codex adapter passed 323 tests.
- The OpenClaw adapter passed 13 tests.
- The OpenCode adapter passed 42 tests.
- The plugin SDK passed 45 tests.
- The workspace runtime suite passed 124 tests.
- The caller-scoped readiness and handoff suite passed 52 tests.
- The workspace provisioning shell suite passed 7 tests.
- The runtime exposure suite passed 17 tests while live host mappings
occupied fixed test ports.
- `git diff --check` passed and the worktree is clean.

The serialized route lane will run in GitHub CI with its normal shards.
No deployment or active-workspace migration was performed.

## Risks

- This is a medium-risk authentication and runtime-readiness change.
- The login ticket uses exact origin, workspace, instance, and user
binding. It has a short expiry and a one-time nonce.
- Runtime publication is stricter. A real readiness, identity, per-user
handoff, or control-plane database disagreement now blocks publication.
- This pull request supersedes #11665 as the merge candidate. Close
#11665 after this pull request merges.
- No new database migration is included. The lockfile and workflow files
are unchanged.
- Deployment and active-workspace migration are intentionally outside
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 — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

Claude Opus 5 (`claude-opus-5[1m]`), 1M context, extended thinking, tool
use, and code execution produced the main candidate. OpenAI GPT-5
(`gpt-5`) through Codex, with agentic reasoning, tool use, and code
execution, integrated the post-QA fixes and hardened the test gates. The
Codex context-window size was not exposed.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-19 02:37:02 -05:00
Dotta 4c349fe6b7 feat(runtime): managed Tailscale HTTPS lifecycle, durable runtime leases, and bounded control recovery (#11525)
<!-- Simplified Technical English (ASD-STE100). -->

> **Stacked pull request.** This targets #11524. Merge #11524 first.
Review only the second commit, `feat(runtime): managed Tailscale HTTPS
lifecycle...`.

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Paperclip starts and supervises managed runtime services, so an
agent's branch can be previewed while the agent works
> - The previous pull request added the host broker, the shared
contract, and the database columns, but no code used them
> - A managed runtime can only be exposed over HTTPS if it holds a
stable loopback port pair for the whole life of the service. The current
control path cannot promise this: two controls can race the same
execution workspace, a stranded control can stay `running` forever, and
a start can adopt a port it does not own
> - This pull request adds the HTTPS lifecycle and the control-path
hardening that the lifecycle depends on
> - The benefit is that a managed preview becomes reachable from another
device, and a managed control now always reaches a terminal state

## Linked Issues or Issue Description

No public GitHub issue exists. The change follows the feature request
template.

**Subsystem affected**

Managed workspace runtime services, workspace operations, the execution
workspace routes, and the workspace runtime UI.

**Problem or motivation**

A managed runtime service is reachable only on loopback, so a preview
cannot be opened from a phone or a second computer. Exposing it safely
needs an exclusively held port pair. Three existing gaps block that.
Overlapping controls can race the same workspace. A control whose owner
dies stays `running` and blocks the lane forever. Port allocation does
not confirm that the process holding a port is the process Paperclip
spawned.

**Proposed solution**

Add the exposure lifecycle on top of the broker from #11524: reserve
before spawn, expose after readiness, validate the public URL, and
remove on stop. In the same change, make managed controls mutually
exclusive per workspace, give each control a durable issue-owned lease
and a terminal state, and verify port ownership before use.

**Alternatives considered**

- Add HTTPS exposure without the control hardening. This was rejected
because a raced or stranded control makes exposure point at the wrong
process.
- Guard the lane with an in-memory lock only. This was rejected because
the lock does not survive a server restart, so the lane can be lost or
double-claimed.
- Trust the requested bind address. This was rejected because a checkout
that predates managed HTTPS overwrites `PAPERCLIP_BIND` from its own
`--bind` argument, and then binds the wildcard address.

**Roadmap alignment**

This completes the managed workspace runtime capability that already
exists. It adds no new product surface beyond the HTTPS link.

**Additional context**

This is the second of three pull requests. The third adds central
mediation of leased port pairs.

## What Changed

Exposure lifecycle:

- Add the server-side broker client and the exposure lifecycle manager.
The manager reserves the mapping before spawn, exposes after backend
readiness, validates the public URL, and removes the mapping on stop.
- Default managed worktree runtimes to `tailscale_https`, read exposure
intent from legacy `expose` blocks, and backfill runtimes that are still
HTTP-only.
- Verify listener ownership for the app port and its Vite HMR companion
before the broker is asked to expose anything. An unrelated listener on
either port fails the start closed.
- Force the loopback bind through argv instead of environment hints.
Leave a non-Paperclip service's `--bind` argument alone.
- Probe loopback for readiness instead of the public URL, and give Vite
HMR its own loopback-bound server in middleware mode.
- Preserve operator-declared Serve mappings across the managed
lifecycle, so cleanup never removes a mapping that Paperclip did not
create.
- Name which listener predicate denied an expose, so an operator can act
on the message.

Control-path hardening:

- Make `start`, `stop`, `restart`, and job `run` mutually exclusive per
execution workspace. An overlap gets `409
workspace_runtime_control_in_progress`, and authorization is still
checked first.
- Take a durable exclusivity lease on the execution workspace, owned by
the controlling issue. A different issue gets `409
workspace_runtime_lease_conflict` before any operation is recorded.
Board and operator actions bypass the lease.
- Give every control a terminal state. Each control stamps its owning
process and pid, heartbeats while it runs, and has a wall-clock ceiling.
Recovery of a stranded control uses a compare-and-swap on `updated_at`,
so a live owner is never stolen.
- Bound readiness probes, verify allocated port ownership on POSIX and
Windows, harden sibling port allocation, and reconcile desired runtimes
on server startup.
- Surface exposure state and bounded runtime errors in the workspace
runtime UI.
- Record the new behavior in `doc/DEVELOPING.md`.

## Verification

Focused checks, all run on this branch:

- `npx tsc --noEmit -p server/tsconfig.json` — 139 errors, exactly the
count on `master`. All 139 come from the unbuilt
`@paperclipai/plugin-sdk` package.
- `pnpm --filter @paperclipai/ui typecheck` — clean.
- Server suites, 177 tests pass across 9 files:
`workspace-runtime.test.ts`, `workspace-runtime-leases.test.ts`,
`workspace-runtime-control-recovery.test.ts`,
`execution-workspace-runtime-control-conflict.test.ts`,
`execution-workspace-runtime-lease-route.test.ts`,
`workspace-operations-reconciliation.test.ts`,
`workspace-runtime-start-terminality.test.ts`, `app-hmr-port.test.ts`,
and `workspace-runtime-ready-comment.test.ts`.
- Exposure unit suites, 77 tests pass: `src/services/runtime-exposure/`
and `workspace-runtime-exposure-backfill.test.ts`.
- UI: `WorkspaceRuntimeControls.test.tsx` and
`WorkspaceServiceControlBar.test.tsx` — 34 tests pass.

**One suite is red on the development host and is expected to be green
in CI.** `server/src/services/workspace-runtime-exposure.test.ts` has 10
failures on the machine used to write this branch. The cause is host
contamination, not the code. That machine already runs an HTTPS canary
that holds ports 42000, 42001, 52000, and 52001 on a tailnet address.
The suite allocates from the same range, so the new listener-ownership
check correctly reports:

```
listener_ownership_mismatch — port 42000 is bound to 100.123.243.20, 127.0.0.1,
fd7a:115c:a1e0:0:0:0:dd3a:f314 ... instead of loopback only
```

A CI runner has no listener on those ports, so the check sees loopback
only and the suite passes. Please confirm this from the CI result on
this pull request rather than from a local run on a host that already
exposes a managed runtime. This is a real weakness of the current test
fixture, and the third pull request in the series removes it by
allocating the pair through a central mediator instead of a stubbed
availability check.

`workspace-runtime-https-live-exercise.test.ts` needs a live `tailscale`
host and was not run locally.

## Risks

- This is the behavior-bearing pull request of the three, so it carries
the most risk.
- Two new `409` responses appear on managed control routes. A caller
that assumed a control always starts must handle a conflict. Board and
operator actions are deliberately exempt, so an agent lease cannot lock
an operator out.
- Managed worktree runtimes now default to `tailscale_https`. If the
host has no working broker, the start fails closed and reports the
exposure failure instead of silently serving plain HTTP. This is
intended, and it is the reason the failure message names the denying
predicate.
- Startup reconciliation touches persisted runtime rows. It is scoped to
desired state and does not resurrect a service that never came up.
- The lease has a 30-minute time to live and explicit release paths, so
a crashed owner cannot hold a lane forever.
- No migration runs in this pull request. The tables and columns land in
#11524.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR.

## Model Used

Claude Opus 5 (`claude-opus-5`), 1M context window, extended thinking,
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, with the one
host-contaminated suite explained above
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] 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
2026-08-17 06:23:33 -04:00
DottaandPaperclip e68188c438 fix: upstream deployed document-comment, routine-annotation, workspace & board-polling fixes (#8536)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - This change touches several already-shipped subsystems —
document-comment annotations, the selected-agent Conference Room chat
surface, routine description annotations, workspace-operation tracking,
and the board polling/inbox UI
> - A batch of incremental fixes and two small backend additions had
accumulated on a local mainline and were deployed to a live instance,
but never landed upstream — so each `origin/master` sync kept
re-diverging
> - Leaving them un-upstreamed means the same delta has to be re-merged
on every sync and risks being lost or silently reverted
> - This pull request rebases that delta cleanly on top of current
`origin/master` (preserving recent upstream work such as reusable
sandbox leases and the relation-list collapse controls) and brings it up
for review
> - The benefit is that mainline and the deployed instance converge, and
these fixes/additions get normal review + CI + Greptile coverage

## Linked Issues or Issue Description

No single GitHub issue tracks this; it is a bundle of bug fixes and two
small feature additions. Following the issue-template fields:

**Bug fixes (what was wrong → what this does):**
- Document comments rendered out of document order, didn't live-update
across clients, swallowed save failures, and lost the markdown text
selection on re-render. Now: doc-order sort, live updates, surfaced
save-failure state, stable selection across re-renders.
- The board polling hot path returned oversized payloads on every poll.
Now: an opt-in `summary` projection trims the heartbeat-run list
payload.
- Assorted UI fixes: sidebar nav peek/streamlining edge cases, markdown
file-viewer re-mount/line-height issues on iOS Safari, inbox badge/skill
deep-link tab selection, and `⌘.` work-mode cycling on iOS.

**Feature additions:**
- `workspace_operations.issue_id` — associate a workspace operation with
the issue that triggered it (new migration `0106`, schema, service,
shared type).
- Routine **description annotations** — comment threads on a routine's
description document, mirroring issue document annotations (new
migration `0107`, `routine_documents` schema, routes/service,
editable-sections UI).
- Selected-agent **Conference Room chat** surface wiring and live
issue-thread updates.

**Related PR:** #8229 (`feat(control-plane): add annotation and
workspace controls`, draft) covers overlapping
annotation/workspace-control territory — flagging it so a reviewer can
reconcile the two rather than double-merging.

## What Changed

- `feat(workspace)`: `workspace_operations.issue_id` migration +
schema/service/type; issue workspace property controls reconciled with
upstream's evolved "Service" row.
- `feat(routines)`: routine description annotations —
`routine_documents` schema, migration `0107`, routes/service,
`editable-sections` UI.
- `fix(document-comments)`: doc-order sort, live updates, save-failure
surfacing, stable markdown selection (+ storybook story, rerender test).
- `feat(chat)`: selected-agent Conference Room chat surface and live
issue-thread updates (`LiveUpdatesProvider`, `issue-chat-messages`,
interactions service).
- `perf(board)`: opt-in `summary` projection for the board
polling/heartbeat-run list payload, plus assorted sidebar / file-viewer
/ inbox / IssueProperties UI fixes.

Organized into 5 logical commits. Migrations are numbered incrementally
after upstream's latest (`0105`) — `0106` then `0107`, no journal
collision.

## Verification

- Built by 3-way merging the deployed delta onto current
`origin/master`; the only merge conflict (`IssueProperties.test.tsx`,
two adjacent test blocks) was resolved in favor of upstream's evolved
"green service link above the workspace row" layout, which matches the
merged component's rendered output.
- Confirmed recent upstream work is preserved post-merge: reusable
sandbox lease teardown (`#8513`), the IssueProperties relation-list
collapse controls, and the sidebar streamlined-nav default.
- Confirmed the net diff vs `origin/master` is exactly the intended
feature delta (65 files) and that overlapping server files (`issues.ts`,
`agents.ts`, `heartbeat.ts`) only add feature code without disturbing
upstream logic.
- This delta is already running on a live deployed instance.
- Full typecheck/test suite + Greptile to run in CI (see checklist).

## Risks

- Two new migrations (`0106`, `0107`). Both are additive (new table /
new nullable column) and ordered after upstream's `0105`; no data
backfill, low risk. If another migration-bearing PR merges first,
renumber before merge.
- Largest blast radius is in the merged overlapping UI/service files;
covered by the existing test suites for those files plus CI.
- Overlaps thematically with draft PR #8229 — reviewers should reconcile
rather than merge both blindly.

## Model Used

Claude Opus 4.8 (`claude-opus-4-8`), extended thinking, with tool use
(git, shell). Agentic coding workflow.

## 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)
- [ ] 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
- [ ] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-06-23 09:00:14 -05:00
DottaandPaperclip 16b2b84d84 [codex] Improve agent runtime recovery and governance (#4086)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies.
> - The heartbeat runtime, agent import path, and agent configuration
defaults determine whether work is dispatched safely and predictably.
> - Several accumulated fixes all touched agent execution recovery, wake
routing, import behavior, and runtime concurrency defaults.
> - Those changes need to land together so the heartbeat service and
agent creation defaults stay internally consistent.
> - This pull request groups the runtime/governance changes from the
split branch into one standalone branch.
> - The benefit is safer recovery for stranded runs, bounded high-volume
reads, imported-agent approval correctness, skill-template support, and
a clearer default concurrency policy.

## What Changed

- Fixed stranded continuation recovery so successful automatic retries
are requeued instead of incorrectly blocking the issue.
- Bounded high-volume issue/log reads across issue, heartbeat, agent,
project, and workspace paths.
- Fixed imported-agent approval and instruction-path permission
handling.
- Quarantined seeded worktree execution state during worktree
provisioning.
- Queued approval follow-up wakes and hardened SQL_ASCII heartbeat
output handling.
- Added reusable agent instruction templates for hiring flows.
- Set the default max concurrent agent runs to five and updated related
UI/tests/docs.

## Verification

- `pnpm install --frozen-lockfile`
- `pnpm exec vitest run server/src/__tests__/company-portability.test.ts
server/src/__tests__/heartbeat-process-recovery.test.ts
server/src/__tests__/heartbeat-comment-wake-batching.test.ts
server/src/__tests__/heartbeat-list.test.ts
server/src/__tests__/issues-service.test.ts
server/src/__tests__/agent-permissions-routes.test.ts
packages/adapter-utils/src/server-utils.test.ts
ui/src/lib/new-agent-runtime-config.test.ts`
- Split integration check: merged this branch first, followed by the
other [PAP-1614](/PAP/issues/PAP-1614) branches, with no merge
conflicts.
- Confirmed this branch does not include `pnpm-lock.yaml`.

## Risks

- Medium risk: touches heartbeat recovery, queueing, and issue list
bounds in central runtime paths.
- Imported-agent and concurrency default behavior changes may affect
existing automation that assumes one-at-a-time default runs.
- No database migrations are included.

> 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 tool-enabled coding model, agentic
code-editing/runtime with local shell and GitHub CLI access; exact
context window and reasoning mode are not exposed by the Paperclip
harness.

## 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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-20 06:19:48 -05:00
dottaandPaperclip 39878fcdfe Add username log censor setting
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-20 08:50:00 -05:00
Dotta 4da13984e2 Add workspace operation tracking and fix project properties JSX 2026-03-17 09:36:35 -05:00