Commit Graph
4 Commits
Author SHA1 Message Date
DottaandPaperclip bf7f77d8cd fix: avoid response recovery self-contention (#18715)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The server must present accepted agent responses as comments under
current chat authority.
> - The recovery worker can check four tasks at the same time.
> - Different tasks can share a chat endpoint or external principal.
Their authorization transactions then compete for endpoint or identity
locks.
> - A failed transaction leaves the accepted response pending and
repeats its source queries on a later retry.
> - This pull request groups checks that share a task, endpoint or
principal before dispatch. It keeps every transactional authority check
and lock.
> - The benefit is less failed recovery work and prompt, exactly-once
presentation of valid accepted responses.

## Linked Issues or Issue Description

Refs #17714 for a separate publication-commit lock-order fix. Refs
#18686 for separate run-list JSON work. Neither changes this recovery
admission path.

**What happened?**

A response-presentation worker reported `could not obtain lock on row in
relation "chat_endpoints"`. Four real PostgreSQL recovery fixtures
reproduced three such failures in one pass with no external ingress. The
worker grouped by task, while authorization locks shared endpoints and
principals. Review also exposed two valid Slack endpoints in one
workspace that share one principal and compete for its try-advisory
lock.

**Expected behavior**

Recovery checks that share an endpoint or principal should retain task
order without competing with one another. Unrelated endpoints should
make progress. The server must still reject stale authority and retry
legitimate external contention.

**Steps to reproduce**

Run the shared-endpoint regression or the portable comparison helper
linked below. The fixture creates four accepted historical responses for
distinct tasks and principals on one actual endpoint.

## What Changed

- Read optional endpoint and principal scheduling hints through a
company-scoped join to the canonical wake action. The join does not
change eligibility or grant authority.
- Extend existing bounded check groups to merge intersecting resource
keys. Preserve task order, transitive conflicts, independent-group
progress, shutdown, drain and pending scopes.
- Add real PostgreSQL controls for shared endpoints, a principal shared
across two endpoints, an observed blocked transaction with independent
endpoint progress, external locks, exact selected output, and endpoint
revocation despite a forged hint.
- Add a portable helper that materializes the pinned baseline with `git
show`, runs the existing real fixture, retains results, and restores
temporary files.

## Verification

- Final principal-extension head
`57047441b28765ed1cf49b8924efc69f5c03dcb4`: 34 focused scheduler/chat
controls passed on Node 24.22.2 / pnpm 9.15.4. Independent exact-head
source review is green. Full local `pnpm -r typecheck` and `pnpm build`
pass on this head. Fresh Greptile and Paperclip reviews are both 5/5
with no findings. All 59 final-head contexts are complete: 55 success, 3
skipped, and the neutral Paperclip review at 5/5. There are no failures
or pending checks.
- Earlier endpoint-only head `eea437e7edbe7eb41eb880d4d8fd6d99a9c247da`:
full local typecheck/build and all remote CI passed. The redundant local
full suite was interrupted for this review fix after 956 passing chat
cases; it is not a full local pass.
- Final shared-principal counts-only comparison completed the same two
exact responses: product calls 165 → 147, rows 114 → 100, outer
contention failures 1 → 0. SQL query errors stayed zero; advisory-lock
refusal is not a failed SQL query.
- The earlier endpoint-only study completed five alternating pairs / ten
measured runs: median calls 443 → 293, rows 314 → 200, query errors 6 →
0 for four exact responses. Its instrumented shared-host CPU data
predates the principal extension and is not a final-head or hosted CPU
claim. Retry clocks were accelerated; wall time is not hosted latency.
- [Raw samples, final principal work counts, portable commands and
failure
accounting](https://github.com/paperclipai/paperclip/blob/57047441b28765ed1cf49b8924efc69f5c03dcb4/doc/performance/2026-11-03-response-presentation-contention.md).
- Initial server4 CI reported three provider calls instead of two in the
unchanged Anthropic identity fixture. The exact local case passed; the
full 88-case file passed with observations showing the two expected
identity-route calls. The third CI call's origin remains unknown. One
bounded rerun of the failed job and its dependent CI aggregate passed.
No assertion or source change was made for that failure.
- The causal benchmark baseline worker/query is
`82c033ed127d07862e6765aa4b69a3cf339bde81`. The PR base is `36df8933f0`.
They are not claims about the currently serving revision.

## Risks

- Connected resource groups can reduce parallelism when tasks link
several endpoints. This preserves the existing task ordering contract.
- Missing or stale endpoint/principal hints retain current transactional
checks. Other workers and ingress can still cause legitimate NOWAIT
retries.
- There is no schema, API, permission or provider-transport change.
Endpoint revocation and company isolation remain enforced by their
existing owners.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`), with tool use and code execution,
produced and reviewed this change. The runtime does not expose the
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-11-03 06:04:25 -06:00
DottaandPaperclip 53f480d1b3 fix(native): preserve warm continuity and deferred review replies (#18631)
## Thinking Path

> - Paperclip manages AI agents and their saved work.
> - Product E2E tests must check saved personal files across separate
turns.
> - The server records file collection in the durable `instruction_save`
run-log event.
> - The warm test read optional terminal result metadata instead and
rejected a recorded successful save.
> - This pull request reads the complete event stream for the current
run and uses its latest save receipt.
> - The prompt now specifies the exact nine bytes required by the
temporary-file transfer count.
> - Human review actions select the actual interaction card, which can
share its interaction ID with a navigation button.
> - A later real three-turn run exposed a missing reply after workspace
finalization moved to its durable recovery owner.
> - Reply recovery handled completed tasks but omitted ordinary tasks
that awaited review.
> - This pull request also publishes their recorded final reply once
while preserving the pending review.

## Linked Issues or Issue Description

**What happened?**

The [retained live continuity
attempt](https://github.com/paperclipai/paperclip/actions/runs/41477302876/job/125420001074)
saved the correct memory file and unchanged 8 MiB binary. Its durable
run log contained a successful `instruction_save` receipt. The oracle
read `resultJson.instructionSave`, which was absent, and failed before
turn two. The temporary file also had a trailing LF. Its prompt allowed
that result, while the byte-count check required nine bytes.

**Expected behavior**

The oracle must use the documented authoritative save event. A missing
receipt, a later failed save, incorrect transfer counts, or another
run's events must fail. The prompt must specify the bytes that its
independent check requires.

**Steps to reproduce**

1. Run `daytona-warm-continuity.runner-codex.daytona.warm-three-turn`
with the configured protected credentials and immutable image.
2. Complete a native turn whose terminal result has no `instructionSave`
field.
3. Compare the oracle output with the same run's successful
`instruction_save` event.

A subsequent [three-turn
attempt](https://github.com/paperclipai/paperclip/actions/runs/41495337334/job/125451304553)
passed every personal-file assertion and reused the same warm process.
Its first final reply was recorded as a completed agent-message event
but was absent from comments. The log shows
`native_workspace_finalization_busy`; the durable recovery path excluded
`needs_review` replies. The final message matcher correctly failed. This
failure remains recorded.

The observed application revision was
`aab87ce70744660a4a21c77278b0ede267c04720`. Related work: #14695 and
#18494. The retained failed result keeps its original grade and
definition.

## What Changed

- Read all run-event pages through the existing bounded collector.
- Require events to belong to the requested run and select the latest
`instruction_save` event.
- Retain strict byte counts and reject missing, failed, pending or
superseded receipts.
- Specify nine ASCII bytes and no trailing newline for the temporary
file.
- Scope human review actions to the interaction card and its exact
interaction ID.
- Advance the warm suite definition to version 5 and document its
evidence source.
- Recover recorded final replies for ordinary native tasks with an
accepted `needs_review` result and terminal state.
- Preserve pending reviews, existing reply selection,
company/turn/digest checks and external governed-response authorization.
- Update the task feature and agent access maps.

## Verification

- Real PostgreSQL regression: deferred review reply discovery failed
before the production repair (expected one candidate; found zero). The
final-message event and pending review were present.
- Recovery cases cover one publication, no repeated provider run,
unchanged review, and rejection of absent/wrong-turn final messages, bad
digest and suppressed comments.

- Red: seven new boundary regressions failed against the old receipt
lookup.
- Green: 169 focused oracle, event pagination and catalog checks passed.
Product E2E typecheck passed after rebuilding local package
declarations.
- Retained-evidence replay confirms that the new lookup finds the real
successful save event. The original attempt remains failed because its
temporary file included an LF.
- Recursive typecheck passed before the final recovery change; server
typecheck passed afterward. The recovery and control-plane suites passed
all 112 tests. Full build and map checks passed.
- The broad local test run reached one unrelated 30-second timeout in
`attention-retention-work.test.ts` (maintained-review/confirmation
batching). The same unchanged case then passed on one targeted retry
(39.9 seconds including module load). The original failure remains
retained. The broad run also reported one unchanged workspace-conflict
case, which passed on its targeted retry (14.85 seconds including module
load). Both original failures remain retained. The redundant broad local
run was stopped after current-head CI completed all required gates: 55
successful checks and 3 selection skips. No all-green local broad-run
claim is made.
- The separate artifact-transfer cell already passed on the recorded
application revision: independent source and delivered bytes matched at
407,485 bytes, with a completed task, succeeded native run and cleared
execution locks. This does not establish a three-turn continuity pass.

- [Real native three-turn
acceptance](https://github.com/paperclipai/paperclip/actions/runs/41499102994/job/125465795210)
**passed** at `3b207a42943e9eeb371d4f2d5623de72093eb6d5`, suite
definition 5. Turn one exercised `committed_task_response_recovered`.
All three completed final replies were persisted once and in order. All
three strict personal-file receipts passed. The unchanged 8 MiB binary
survived; later transfers copied only 36 and 54 bytes. The lease was
created, resumed, and resumed with the same runner PID/start time,
runner instance, native session and provider session. Final task was
`done`, all three runs succeeded, and checkout/execution locks were
null.
- The aggregate startup summary has no separate provider-process PID
proof. The raw run records independently prove the stable runner process
and provider session stated above. This single native cell does not
qualify the legacy cell or a full provider matrix.
- The passing campaign reused the signed immutable runner image. It
required no disk expansion. Earlier campaign image builds used the
recorded temporary 120 GiB mitigation; default 60 GiB build capacity
remains unqualified. All scoped completed probes were removed and
independently returned 404; org CPU/disk usage returned to zero. This
does not resolve unknown historical resources under a different
credential identity.
- Current-head Greptile is 5/5; review-thread pagination is complete
with zero threads. All 55 current-head checks are successful; 3
selection checks are skipped. The paid campaign, result enforcement and
report publication all completed successfully.

## Risks

- Publishing a reply must not approve the work. Recovery only copies the
accepted turn’s completed final message. It preserves the pending review
and does not start an executor.
- Conversation and external governed-response paths retain their
existing separate authorization.

The latest save event can record failure after an earlier success. The
oracle rejects that case. Event pagination, missing receipts and
cross-run evidence also fail closed. The exact temporary-file byte count
remains required. The review selector still requires the intended
interaction ID and enabled action on its actual card. The production
change is limited to ordinary internal-task reply recovery. It still
requires an accepted result, a matching successful terminal disposition,
the completed final message, and existing publication authority.

## Model Used

OpenAI Codex, based on GPT-6, with shell and code tools. The exact
deployment variant and context-window size are not exposed in this
session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs: #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change 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-11-02 14:19:48 -06:00
Dotta 12b0cc6304 fix(chat): recover committed native Agent Chat replies (#18465)
## Thinking Path

> - Paperclip manages agent work and keeps its results available to
users.
> - Agent Chat needs a visible reply before the conversation can wait
for more input.
> - Native result commitment and reply presentation are separate
obligations.
> - A completed conversation can retain a valid final message without a
saved reply.
> - Existing reply recovery excludes these completed conversation turns.
> - This pull request repairs that persistence gap through the existing
recovery worker.

## Linked Issues or Issue Description

**What happened?**

A native Agent Chat turn completed successfully and saved its workspace.
Its accepted result and final assistant message were durable, but no
reply appeared in the conversation. The chat stayed active. The
deployment hiring journey in #18351 then reached its deadline while
waiting for the first reply.

**Expected behavior**

Recover the exact accepted turn's final reply once, then use normal
conversation settlement. Keep later user input active. Do not run the
agent again or replace a selected or deleted reply.

**Steps to reproduce**

1. Create an active conversation with one admitted native turn.
2. Commit an accepted DONE result and a final-channel assistant message
for that exact run, session and turn.
3. Finish workspace finalization before live heartbeat reply
presentation. Leave no saved reply.
4. Run normal response recovery. Before this fix it finds no
conversation candidate and leaves the chat active.

**Paperclip version or commit**

Reproduced with actual services at frozen master
`8bcc5a01edd5d87540401521e6f30d3df43e1848`. The production predicate
also exists in the deployed revision that exposed the failure.

Related work: #18351. The broader receipt and recovery work in #18118
and #18409 does not touch these source files.

## What Changed

- Discover unanswered committed Agent Chat turns through the existing
native response presentation worker.
- Recheck company, agent, responsible user, current execution and
conversation generation under the normal transaction locks.
- Require the accepted result digest and an exact final message from the
same native run, session and accepted turn. Keep external publication
authority separate.
- Commit the reply and presentation receipt before normal conversation
settlement. Later input stays active. Recovery does not repeat agent
work.
- Preserve skip decisions and selected or deleted replies. Add database
controls for foreign identity, stale sessions, partial commitment,
duplicates and ordinary internal task behavior.
- Document the recovery boundary in the developer guide.

## Verification

- Real-service RED/GREEN uses all 418 canonical migrations in isolated
PGlite and the exact new regression fixture. Before the fix: zero
candidates, no reply, recovery returns false and the chat stays active.
After the fix: one candidate, one exact reply, recovery returns true and
the chat waits. A repeat returns false and creates no second reply.
- All 20 canonical regression cases pass locally through a fixture-only
PGlite bridge. Only local database provisioning and `createDb` selection
differ from the normal embedded PostgreSQL fixture. Production services,
SQL queries, transactions, protocol validation and assertions remain
real. Linux embedded PostgreSQL CI is required before merge.
- Focused current-source no-emit typing passes for both production
modules and the new regression file, with normal Express augmentation
and source aliases. The broader local presentation/ownership and
conversation-settlement PGlite bridge run was interrupted before it
reported results; it is not counted as a pass. No repository-wide local
build is claimed from borrowed workspace dependencies. Clean-build CI
and canonical PostgreSQL consumer tests remain required.
- `git diff --check` and the scoped source/test secret scan pass. No
captured run data, credentials or private target identities are
committed.
- No live journey retry, deployment, configuration change or test-plan
admission was performed. The original failed journey remains failed;
this production fix still needs deployed qualification through the
unchanged journey.

- Current-head [canonical Linux
CI](https://github.com/paperclipai/paperclip/actions/runs/41207018345)
passed all 57 terminal checks with no failure or pending check. The new
20-case database regression actually passed in [server shard
8](https://github.com/paperclipai/paperclip/actions/runs/41207018345/job/124555006090),
at 13:59:25 UTC (2,643 ms). Typecheck, build and the existing consumer
lanes passed. Fresh [Greptile
review](https://github.com/paperclipai/paperclip/pull/18465#issuecomment-6544208002)
on exact `f32a432e10b377ae6277d6f728995d5fedcf9d7b` is 5/5; the
review-thread inventory is empty with no pagination. No live deployment
or journey pass is claimed by these checks.

## Risks

Eligible active conversations can gain a previously missing reply.
Recovery accepts only the exact saved final message under its accepted
result and current conversation identity. It does not run a model,
repeat hiring or change a prior test grade. Reply persistence precedes
waiting-state settlement; existing conversation recovery retains
ownership of a later interrupted settlement. No schema or public API
changes are included.

## Model Used

OpenAI Codex, GPT-6 family. The session does not expose a more specific
backend model ID or fixed context window. Used reasoning, repository
tools, TypeScript and real database test execution.

## Checklist

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

> - Paperclip manages AI agents and their work.
> - Native runs retain finalization records for recovery and audit
history.
> - Idle sleep checks durable work before it stops an instance.
> - The current check treats every retained finalization as pending
work.
> - A committed record can remain after its run and status effects have
finished.
> - This pull request recognizes complete records without deleting them.
> - Instances can sleep while unfinished execution and recovery work
remain protected.

## Linked Issues or Issue Description

**What happened?**

A retained `native_run_finalizations` row prevents idle sleep even after
the run has finished and its status decision has been applied. The
current gate checks whether any row exists.

**Expected behavior**

Complete finalization history should remain available without counting
as pending work. Active leases, retries, accounting, recovery, and
incomplete status effects must still prevent sleep.

**Steps to reproduce**

1. Finish a native run and retain its committed finalization.
2. Confirm that its accepted result, assessment, applied decision, and
delivered effects agree.
3. Request an idle report under a valid quiet admission hold.
4. Observe that the retained row reports background work before this
change.

**Paperclip version or commit**

Reproduced on master at `cd0c86e5e1d427c8fa8aa8c3a9499391ee9b425b` with
a local PostgreSQL fixture.

**Deployment mode**

Server with PostgreSQL. No provider calls are needed to reproduce the
gate failure.

Related PR and issue searches found no duplicate for this check.

## What Changed

- Replace the blanket finalization-row check with a completion proof
bound to the same company, issue, run, accepted result, assessment, and
applied decision.
- Require the owning run's successful workspace-finalization receipt;
retain unresolved leases, retries, accounting, recovery, and status
effects.
- Share final-reply candidate discovery with the presentation recovery
worker, so a completed run cannot hide a required reply. The pure query
stays with native presentation; idle inspection uses it in the existing
read-only transaction and five-second statement limit.
- Register open warm sessions and in-flight close/checkpoint promises
with local idle inspection. Historical controller/provider process
metadata remains preserved.
- Add PostgreSQL and local-warm regressions and document the
retained-history rule.

## Verification

- PostgreSQL sleep/finalization and chat-monitor continuation suites:
300 tests passed, including 56 finalization cases.
- Local-warm regression: passed; an open session and its pending
close/checkpoint both block sleep until retirement completes.
- Server typecheck and server build: passed after review fixes.
- Full workspace typecheck and build: passed before the review
additions; hosted checks cover the updated revision.
- An earlier local full invocation encountered two chat recovery
failures that passed in isolation, and two existing Git workspace
fixture failures caused by Xcode system Git initializing `main`. Those
two pass with `init.defaultBranch=master` scoped to the test subprocess.
That superseded full invocation was stopped for review revisions; no
full local pass is claimed. No machine configuration or unrelated source
was changed.
- Fresh Apex review: 5/5 on `6846203fe2383bae1ede888fbaaedf83e9946e73`,
with all findings addressed.
- Hosted CI: fully green on `6846203fe2383bae1ede888fbaaedf83e9946e73`,
including the final verify gate. Twelve jobs were interrupted by a
simultaneous runner shutdown; rerunning the failed jobs completed
successfully.
- No hosted deployment of this change is claimed.

## Risks

This changes an automatic-stop gate. An incomplete proof could stop an
instance with pending work. The SQL fails closed and retains the
existing admission, local work, plugin, schedule, backup, and
provider-allocation gates. PostgreSQL cases cover unresolved leases,
retry/recovery intent, accounting, projections, rejected results,
unapplied decisions, and pending effects.

No migration or history deletion is required. Reverting the predicate
restores the conservative gate.

## Model Used

OpenAI GPT-6 through Codex, with repository tools and local PostgreSQL
verification.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 11:11:22 -07:00