Commit Graph
77 Commits
Author SHA1 Message Date
DottaandPaperclip 7afee8f062 fix(server): schedule direct GitHub webhook recovery from saved deadlines (#17666)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/218/changes/paperclip/218
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - GitHub callbacks can fail before the app records an inbox row.
> - Direct GitHub integrations need bounded recovery from provider
delivery history.
> - The chat timer checks for due recovery every second, even without an
eligible integration.
> - Existing recovery checkpoints already store the next scan time and
runtime epoch.
> - This pull request schedules those saved obligations and wakes on
committed configuration changes.
> - It removes the final chat maintenance interval while preserving
authenticated recovery.

## Linked Issues or Issue Description

**What happened?**

The app queries due GitHub recovery endpoints every second. This still
runs when no direct GitHub integration needs recovery. Other chat
maintenance duties already have independent workers in the preceding
stack.

**What did you expect?**

Reconstruct existing recovery deadlines at startup and after committed
changes. Run only when an eligible endpoint reaches its saved deadline.
Make no recurring SQL or HTTP calls for unconfigured, disabled, or
Cloud-relayed integrations.

**Steps to reproduce**

Start an instance without an active direct GitHub integration. Leave it
idle. The chat maintenance interval continues to call
processFailedGitHubWebhookDeliveries each second.

Follows merged #17664. Related #15981 owns the original GitHub webhook
ingress/recovery separation. #17662 preserves review-check recovery,
which is a separate obligation. No duplicate scheduling migration was
found in the related-PR search.

## What Changed

- Put deadline reconstruction, scopes, and registration in the GitHub
provider owner. Read existing recovery checkpoints in pages of 100.
Reload current eligibility before each dispatch.
- Dispatch batches of five through the existing shared helper. Preserve
company fairness and the default limit of 25 for other consumers.
- Notify inside configuration, credential, checkpoint,
installation-lifecycle, and Cloud-registration transactions. A signed
installation deletion reproduced a missing wake before the fix.
- Detect credential-only epoch changes during a future backoff. Preserve
the existing floor reset without adopting old events into new
credentials.
- Gate every new recovery HTTP call on dispatch admission and shutdown.
Join in-flight work and retain its existing outcome/uncertainty
settlement. Other queues remain independent.
- Remove the final chat reconciliation interval and its unused
coordinator. Update the old coordinator fixtures; preserve the voice
retention worker acceptance.
- Restore known-unsent redelivery claims after drain/shutdown, guarded
by exact attempt identity. Preserve uncertain outcomes after transport
starts and never overwrite a newer receipt.
- Keep all existing redelivery, source, authority, lease, receipt, and
callback checks. Add no table, migration, or external wake contract.

## Verification

Current source: `ab00fc5b30d51d6c85891536599e7bdfd0c822fe`.

- **751 distinct cases pass** at
`3d7f163bc5259b60f9bd19b7fc90b402f0a6e925`: 274 complete GitHub review
cases, 294 other GitHub-named cases, 30 publication cases, 145
voice/retention cases, and eight startup cases.
- All 19 new recovery worker cases and all six stop-before-transport
variants pass. Coverage includes configured eligibility, callback-only
admission, committed configuration changes, outer transaction
settlement, restart/drain/standby, saved deadlines, fair batches,
independent queues, held HTTP, joined shutdown, known-unsent
restoration, and newer-receipt fencing.
- The first workflow filter omitted the separate recovery group. The
saved case list exposed the gap. The second selection ran the remaining
GitHub cases in a new database. Passed-name sets are disjoint. The two
commands filtered 1,504 and 1,484 unrelated cases respectively. No full
chat or repository-suite claim is made.
- Database build, server typecheck/build, module boundaries, and
migration order pass. Five fresh PostgreSQL fixtures receive the
unchanged parent migration history through 0403. This slice adds no
database migration or table.
- The parent browser-fixture repair is carried with both complete
patches preserved. At predecessor
`836acef0370d42323fdfdbd6d62a805b2469f1d4`, entire server, package and
UI source trees and owned hashes match the 751-case acceptance. The
current follow-up adds three test cases and audit evidence; production
source remains unchanged. The parent has merged.
- [The owning
audit](https://github.com/paperclipai/paperclip/blob/ab00fc5b30d51d6c85891536599e7bdfd0c822fe/doc/plans/2026-10-25-github-webhook-recovery-sleep-audit.md)
preserves earlier failures and exact acceptance scope. Fresh exact-head
Greptile and all CI gates remain required.

## Risks

- Direct GitHub endpoints still require the existing one-minute external
history cadence, with five-minute failure/claim backoff and provider
backoff up to one day. Cloud relay endpoints are excluded. This does not
promise network-idle direct integrations.
- The existing history, envelope, attempt, and lease limits remain.
Provider history never substitutes for a genuine authenticated callback.
- Supported producers share the current database owner's process-local
signals. Independent SQL writers and other server processes need their
own integration. Unknown transaction outcomes remain held by the
existing reconciliation protocol.
- Already-started HTTP keeps its existing timeout and is joined during
shutdown. No later request starts after drain or stop; durable attempt
uncertainty is preserved.
- Host-sleep eligibility and Cloud alarm coverage stay unchanged. Local
worker tests do not prove host/database suspension or fleet savings.
- Each remaining sleep slice needs its own current review and CI checks
before merge.

## Model Used

OpenAI Codex (GPT-6), with reasoning and code execution. The exact
serving model ID and context-window size were not exposed.

## Checklist

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


Parent startup-test correction: #17664 fixes its legacy coordinator
boundary marker. This slice removes that coordinator and timer entirely,
so its existing absence assertions supersede that obsolete inspection.
All other parent and upstream changes are preserved. At predecessor
`836acef0370d42323fdfdbd6d62a805b2469f1d4`, complete server, package and
UI trees match the 751-case acceptance; all eight startup cases also
pass after the explicit conflict resolution. Fresh review and CI are
required for this new head.


## Required review finding: orphan assignment investigation

The reported orphan endpoint cannot be committed through the existing
schema: assigned_agent_id is NOT NULL, its agent FK is ON DELETE
RESTRICT, and a validated nondeferrable composite FK enforces the same
company. A first reproduction failed at fixture mutation with PostgreSQL
23502 before reaching the worker; that failure remains recorded. Three
new real-PostgreSQL cases verify NULL/missing/deleted assignments are
rejected, then prove the preserved valid endpoint recovers once, saves
its next deadline, and makes no SQL reads during a 15-second
pre-deadline interval. All 22 recovery-scheduling cases pass (19
previous plus three new); unselected cases are not counted. The
preceding style-only commit preserved production behavior and
non-comment tokens, and the prior 751-case evidence retains its original
scope (754 distinct cases across both selections). A new review must
assess this evidence before merge; the old conditional verdict is not
waived. Actual parent squash ancestry is carried with whole-tree
identity before this test-only follow-up.


Repository style follow-up removes seven new code-comment lines from the
recovery ingress owner and constraint tests. Their explanations remain
in the audit. Both files retain identical non-comment TypeScript token
streams, preserving all guards, assertions and deadlines. Production
eligibility SQL is unchanged. Fresh current-head CI and reviews remain
required.


## CI test corrections

The original strict deletion assertion reproduced CI's PostgreSQL-18
failure locally: the forbidden delete reports 23001 (restrict
violation), versus 23503 on PostgreSQL 17. The corrected assertion
accepts only these integrity codes for deletion, retains exact codes for
NULL/missing assignments, and verifies the original agent and assignment
remain. All 22 recovery cases pass on embedded PostgreSQL 18; the same
three integrity probes pass on PostgreSQL 17.

A delayed real announcement response reproduced the attachment E2E's
filechooser timeout: the dismiss handler tried to click outside an
already-open modal menu. It now closes the menu, dismisses through the
UI, and restores that menu so the original action resumes. Controlled
late-announcement acceptance passes; the temporary fault is removed. All
11 complete attachment receipt journeys pass, retries zero and original
assertions/budgets unchanged, using a fresh supported external
PostgreSQL-17 database with canonical isolated
onboarding/server/UI/storage. An earlier embedded-cluster startup
failure occurred before tests and remains recorded. Production server
typecheck passes; production source and schema are unchanged. Fresh
current-head CI and review are required.

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 20:05:31 -05:00
DottaandPaperclip 8bc051245f fix(server): wake stale GitHub review repair from committed changes (#17664)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/215/changes/paperclip/215
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - GitHub checks and task admission can finish in either order.
> - A check can reject an old head before admission creates its review
row.
> - The chat maintenance loop repeatedly scans for that late review.
> - Existing cancellation and delivery receipts already identify the
repair.
> - This pull request wakes repair from committed changes and leaves
settled history quiet.

## Linked Issues or Issue Description

**What happened?**

GitHub chat maintenance repeatedly scans all review projections. Empty
instances and retained history incur database work even when no repair
is owed.

**What did you expect?**

A committed stale-head cancellation or admitted review should wake
repair. Only the exact delivery's unassessed queued/running review
should become superseded. When no repair remains, this duty should stop
making database calls.

**Steps to reproduce**

Configure a GitHub chat endpoint and leave it idle after all reviews
settle. The previous maintenance callback continues to call
repairSupersededReviews. A rapid push can also cancel a check before
admission inserts its review, which explains why recovery must remain.

Refs #17662, the merged review-check publication parent. Related #17661
and #17656 migrate terminal responses and acknowledgements. This slice
owns only late stale-head projection repair.

## What Changed

- Move the repair predicate and execution into the GitHub provider
owner. Match the original admitted delivery and cancellation receipt.
Recheck state and assessment in the update.
- Register a scoped worker with the existing coordinator. Use keyset
pages and fair bounded dispatch. Keep retries only for unresolved repair
or failed reconstruction.
- Signal before cancellation, automatic receipt insertion,
automatic-review binding, and check-driven review-state writes. Preserve
existing transaction ownership and outer commit behavior.
- Remove the periodic provider wrapper and publication-maintenance
callback. Preserve explicit manual recovery and independent
missed-webhook recovery.
- Add two concurrent, idempotent partial indexes. Use a guarded delivery
UUID lookup and a bounded exact-receipt lookup. Add no tables.
- Add ten real-database lifecycle and producer cases. Document the
producer audit, failure history, and remaining limits.

- Keep YAML browser reads scoped to the editor after focus changes, with
the original journey assertions and deadlines.

## Verification

Current source: `0886a0229b1c4f68d2f582da86aa1f248e9124f3`.

- At `dd6bca0485c3444d6e3d0ee10ec4aa651e801392`, **287 distinct cases
pass**: 274 complete GitHub workflow cases and 13 startup cases. The
GitHub command filters out 1,485 unrelated cases. The workflow suite
uses a new, pre-migrated PostgreSQL database.
- Coverage includes both orders of cancellation and admission, outer
commit and rollback, restart, drain, standby, failed-update retry,
concurrent assessment under an observed row lock, shutdown during that
wait, more than one candidate page, manual history, and settled-history
quiet.
- Database build, server typecheck/build, module boundaries, and target
migration order pass.
- Canonical migration `0403_natural_cerise.sql` preserves both original
index definitions and concurrent idempotent creation. All 401 parent
migration receipts remain unchanged during upgrade. One new receipt is
added. Replay adds none. Both indexes are ready and valid on fresh and
upgraded databases. The five newest snapshots remain.
- The normal parent merge preserved the prepared tree. The later browser
fixture repair changes only its central read helper and verification
note. Entire server, package, and UI trees remain identical to the
accepted source.
- [The owning
audit](https://github.com/paperclipai/paperclip/blob/0886a0229b1c4f68d2f582da86aa1f248e9124f3/doc/plans/2026-10-25-github-review-projection-sleep-audit.md)
records the exact evidence and earlier failures. Earlier query-plan
measurements retain their historical revision scope.
- Fresh current-head CI and Greptile review remain required. No deployed
sleep, full repository-suite, or fleet-savings claim is made.

Failure accounting: browser shard 7 failed twice on
`1453a4447c0d4d33f713ae3e00734c7950f95426` because the YAML helper read
whole-page clipboard text while main was focused. Three isolated
unchanged local passes did not resolve that failure. A controlled native
focus-loss probe reproduced the same error before the repair and passed
after it. The helper now clears stale clipboard data, focuses the
editor, and waits within the existing expectation budget for a fresh
YAML copy. All six complete YAML journeys pass with zero retries in 50.9
seconds. Journey assertions and deadlines are unchanged. The temporary
fault is removed. The exact CI focus-change trigger remains unknown.
[Both CI
attempts](https://github.com/paperclipai/paperclip/actions/runs/40777754306)
remain part of the verification record. Fresh new-head checks are
required.

Ponytail follow-up: the 4/5 review of `b3c81ba` was conditional on
fixing a stale startup-test slice marker, so the merge was held.
Boundary assertions reproduced the invalid -1 end index. The test now
uses the existing timer declaration and checks both bounds; all 13
startup/hostname cases pass. The optional no-op coordinator cleanup is
already in #17666. The six YAML journeys and all production code remain
unchanged. Fresh review and CI are required for this corrected head.

## Risks

- Missing a future producer signal could delay discovery until restart.
Supported writers share the current database owner's process-local
notification scope. Independent SQL writers and other server processes
need their own integration.
- The migration builds indexes concurrently. The existing migration
runner handles interruption and invalid index recovery.
- Direct GitHub missed-webhook discovery remains periodic. This change
does not make the whole chat service idle.
- Existing Cloud wake coverage and sleep blockers remain unchanged.
These tests do not prove deployed host or database suspension.
- Each remaining sleep slice needs its own review and CI checks before
merge.

## Model Used

OpenAI Codex (GPT-6), with reasoning and code execution. The exact
serving model ID and context-window size were not exposed.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 18:42:54 -05:00
DottaandPaperclip 65fa1cd617 fix(server): schedule GitHub review checks from committed changes (#17662)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/213/changes/paperclip/213
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - GitHub review checks report the state of admitted agent work.
> - The chat maintenance loop searches for check work even when none
remains.
> - Existing action rows already record unfinished publication and retry
deadlines.
> - Committed changes can wake those rows through the shared
coordinator.
> - An unresolved check must still detect a remote head change when a
webhook is missed.
> - This pull request schedules only outstanding checks and leaves
settled history quiet.

## Linked Issues or Issue Description

**What happened?**

The GitHub chat maintenance callback repeatedly queries review-check
actions. Empty queues and completed history still incur database reads.
Local state changes wait for the maintenance callback.

**Expected behavior**

Committed check creation, review binding, run changes, and
publication-lease release wake the worker. Existing retry and
remote-head deadlines apply only to unfinished checks. A settled worker
makes no recurring database or provider calls.

**Steps to reproduce**

Configure a GitHub bot with no outstanding checks, or finish all of its
checks. Leave the instance idle. The old maintenance callback continues
to call the check service.

Refs #17661, the merged terminal-response parent. Related #17656
migrates response acknowledgements. Related #16385 changes branch-policy
admission; this PR preserves that separate policy boundary. Late
stale-head projection repair remains a separate follow-up slice.

## What Changed

- Move the existing check-state reader into the GitHub provider owner.
Preserve current authority, run selection, assessment ownership, and
check replacement behavior.
- Register a scoped worker with the existing coordinator and scheduler.
Existing received and retryable-failed actions remain durable truth. No
new table is added.
- Signal check enqueue, task review receipts, manual review
insertion/binding, run lifecycle changes, and publication-lease release
through existing transaction ownership.
- Preserve the saved failure backoff, eight-attempt policy, and
competing lease expiry. Keep five-second remote-head reconciliation only
while a received check remains unresolved.
- Check admission before each HTTP request. Shutdown leaves durable work
recoverable without spending a provider failure attempt.
- Remove check dispatch from the periodic GitHub callback. Keep the
separate late-projection repair and the manual combined recovery method
compatible.
- Add an idempotent concurrent partial index for unfinished check
selection. Retain the newest five generated snapshots.
- Add eleven real-database worker cases and startup wiring coverage.
Document producer coverage and the external reconciliation limit.

## Verification

Current reviewed source: `2bba08403b195bf646eda48992b46d6f5cebf756`.

- Normal merges preserve the complete review-check patch, the landed
terminal-response parent, and current master changes. No landed SQL
migration or journal entry changes.
- At `6995f84b240a14a7b8660e1cf095b3aa1e1e3168`, **331 distinct tests
pass**: 264 complete GitHub workflow cases, 30 completion cases, eight
issue-tree producer cases, 16 login-cleanup cases, and 13 startup cases.
The GitHub command filters out 1,485 unrelated cases. Login cleanup uses
its real embedded PostgreSQL fixture.
- Combined-master acceptance: **277 distinct tests pass** at
`9c538aed1251fd7f7cecb829a0ecbce6110fb1ed`: 264 complete GitHub workflow
cases and 13 startup cases. The GitHub command filters out 1,485
unrelated cases. A new PostgreSQL database receives all migrations
through 0402..
- Migration `0402_ancient_malice.sql` preserves the original partial
index definition and concurrent idempotent creation. All 400 prior
migration receipts stay unchanged during upgrade. One new receipt is
added. Replay adds no receipt. The index is ready and valid on fresh and
upgraded PostgreSQL databases. The five newest snapshots are retained.
- A rollback-only query probe adds 10,000 processed actions and one
pending action. The actual parameterized candidate predicate selects the
one pending row through the partial index, with two shared buffers and
0.007 ms execution time. This measures candidate discovery, not all
lease or provenance reads.
- Database build, server typecheck and build, module boundaries,
migration safety and migration order pass. Audit: [GitHub review-check
scheduling](https://github.com/paperclipai/paperclip/blob/2bba08403b195bf646eda48992b46d6f5cebf756/doc/plans/2026-10-25-github-review-check-sleep-audit.md).
- Fresh checks and Greptile review are required for this head. Prior
scores do not count. These checks do not prove deployed host suspension
or fleet savings.

## Risks

- Unresolved queued/running checks still make remote-head requests at
the existing five-second deadline. GitHub webhook receipt does not prove
future pushes cannot be missed. This PR does not claim active reviews
become network-idle.
- Run and configuration hints rebuild outstanding checks for the
affected company. Enqueue, review, and lease hints narrow to the
affected endpoint/repository/PR. Startup and scope reconstruction read
existing pending rows; they are not constant-cost operations.
- Delivery admission failures remain discoverable through the unresolved
check's external reconciliation deadline. Not every shared delivery
mutation gains a new immediate signal.
- Notifications use the existing process-local database ownership
contract. Independent SQL writers and other replicas need their own
supported integration.
- Provider markers, publication leases, and saved actions preserve
recovery after uncertainty. This change does not expand Cloud alarm
coverage or prove deployed host/database suspension.
- Each remaining sleep slice needs its own review and CI checks before
merge.

## Model Used

OpenAI Codex (GPT-6), with reasoning and code execution. The exact
serving model ID and context-window size were not exposed.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 17:08:27 -05:00
DottaandPaperclip f8226b0515 fix(server): wake GitHub terminal responses from committed changes (#17661)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/210/changes/paperclip/210
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip coordinates agent work and presents results in chat.
> - GitHub acknowledgements already persist the response action and
provider receipt.
> - A terminal run can still owe a final response after acknowledgement.
> - Periodic maintenance searches those rows even when no relevant state
changed.
> - Committed run, issue, presentation, lease and publication changes
identify when recovery can advance.
> - The owner should recover from those events and real deadlines, then
become quiet.

## Linked Issues or Issue Description

Refs #17656, which is merged. This existing terminal-response slice
targets master.

**Problem:** A saved GitHub response can remain nonfinal while its run,
native presentation, publication or source is unresolved. Removing
maintenance without covering those producers loses recovery. Polling
settled history keeps the tenant active.

**Expected behavior:** Committed supported changes wake the terminal
owner. It reconstructs existing actions, preserves provider authority
and pending publication ownership, waits at saved deadlines where
needed, and becomes quiet after settlement.

## What Changed

- Register terminal GitHub response work with the shared scoped deadline
coordinator, using existing action/delivery/publication/run rows.
- Notify response availability from supported run milestones, native
identity, recovery resolution, issue updates and tree/workspace
restoration writes. Preserve outer transaction commit/rollback.
- Keep GitHub response interpretation in its platform owner. Use the
bounded run projection for both direct authorization and scheduling,
including native presentation guards and deliberate passive outcomes.
- Retain the existing publication lease, markers, source/principal
checks and final receipt precedence. A publication owner or uncertain
outcome keeps its existing authority; the worker does not replay it.
- Remove only recurring terminal-response recovery, preserving the
manual path and neighbouring duties. Add no table or scheduler service.
- Regenerate the original sparse terminal-work index as
`0401_yummy_ultimates.sql`, concurrently and idempotently through the
existing top-level migration runner. Preserve all prior SQL/journal
entries and the five newest snapshots.

## Verification

Published head: `88a209e28b969b5229e9a621aeddfd3cbae9b0cd`, integrated
with landed #17656 (`ba5bba86dcdde32b14d4d7dec1b51898e5f6f22d`) and
master `52b86c2032a189b0ea259c5b0cb7158b07ef788c`.

- **74 distinct current cases pass:** 17 terminal-response
lifecycle/producer cases (1,721 other chat cases skipped), all six
queued-comment consumption regressions for the new upstream query
optimization, all 30 heartbeat completion cases, all eight real/unit
issue-tree control cases and all 13 startup cases. Database build,
server typecheck/build, module boundaries and four fresh migrations
through 0401 pass.
- The earlier **304-case** prepared-parent matrix passes at
`aa72f32641b2e2c680342cd49477272349aca9db`: all 253 GitHub workflow
cases, 30 completion cases, eight issue-tree cases and 13 startup cases.
It retains that revision scope. Repeated cases are not added to the
current 74.
- The terminal matrix covers finalized-history quiet, deleted Board
sources, pending presentation/passive outcomes, outer rollback/commit,
paused/new runs, restart/drain/standby, committed native identity, lease
waits, full-page unrelated history, uncertain publication ownership and
tree/workspace/exhausted-recovery producers.
- A populated 0400 database upgrades to 0401 with all 399 prior
migration receipts identical, exactly one added, and none added on
replay. The terminal index is valid/ready on fresh and upgraded
databases. Its SQL matches the original draft after whitespace
normalization; generation keeps snapshots 0397–0401.
- Normal integration `3c8339a541bf68bc9957b9d5a8df80d3a7c3452d`
preserves the complete 24-path owned binary patch and all five new
master paths. The landed parent tree also equals the previously
published parent tree byte for byte. Both normal merge parents and the
exact composition tree are checked. No force push or rebase occurs.
- [The owner
audit](https://github.com/paperclipai/paperclip/blob/88a209e28b969b5229e9a621aeddfd3cbae9b0cd/doc/plans/2026-10-25-github-terminal-response-sleep-audit.md#acceptance-on-the-landed-github-parent-and-current-master)
preserves the original producer, quietness, failure-isolation,
skipped-suite and presentation-wait results with their scopes. Current
passes do not erase earlier failures or turn skips into passes.
- The audit-only follow-up leaves all owned source/test/migration hashes
unchanged. **Fresh exact-head CI and Greptile 5/5 with no actionable
findings remain required.** No full local repository suite, live GitHub
tenant or deployed sleep result is claimed.

## Risks

- Process-local notifications cover supported application writers and
shared pools. Independent SQL writers and other replicas gain no new
wake guarantee.
- Native terminal status alone does not authorize fallback publication.
Pending presentation and existing publication ownership remain separate
obligations.
- Stop can leave an in-flight provider request settling; admission
fences stop a subsequent request. Unknown outcomes retain their existing
recovery rules.
- Index creation can take time on large histories. Concurrent/idempotent
migration and existing replay recovery remain in charge.
- Worker quiet does not establish host/database suspension. Cloud alarm
coverage and sleep admission remain unchanged.

## Model Used

OpenAI Codex, using reasoning, repository inspection, code execution and
real PostgreSQL tests. The exact model identifier and context-window
size are not exposed in this session.

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 16:51:57 -05:00
DottaandPaperclip ba5bba86dc fix(server): wake GitHub acknowledgements from committed changes (#17656)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/206/changes/paperclip/206
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip coordinates agent work and presents its progress in chat.
> - GitHub deliveries save acknowledgement actions and provider
receipts.
> - Periodic maintenance currently searches for unfinished
acknowledgements even when idle.
> - Committed delivery, lease, response and presentation changes
identify when work can advance.
> - The existing owner should wake on those changes and recover only at
saved deadlines.
> - Completed history should become quiet without losing unfinished
provider effects.

## Linked Issues or Issue Description

Refs #17653, which is merged. This existing GitHub acknowledgement slice
targets master.

**Problem:** A saved GitHub acknowledgement can wait for a publication
lease, fast-response result or native presentation decision. Polling
empty or unchanged work keeps the tenant active. Removing maintenance
without covering these producers can strand the acknowledgement.

**Expected behavior:** Committed changes wake the scoped owner. It
reconstructs existing actions on startup, retries at saved deadlines,
parks unchanged presentation waits and becomes quiet when settled.

## What Changed

- Register GitHub acknowledgement work with the shared scoped deadline
coordinator. Reuse existing action, delivery, lease and fast-response
rows.
- Add transaction-aware response-availability notifications at supported
writes. Keep GitHub protocol details in its platform owner and shared
notifications limited to IDs.
- Share the bounded latest-request/run projection between scheduling and
direct response authorization. An absent native presentation decision
parks the action until its real writer commits.
- Retain publication leases, source/principal authority, version
fencing, response markers and final receipt precedence. Check admission
before each new provider request; let in-flight work settle. Stop does
not consume the provider retry budget.
- Remove only recurring acknowledgement recovery and keep its manual
path. Add no work table or scheduler service.
- Regenerate the three original indexes as
`0400_absent_phantom_reporter.sql`: pending acknowledgement IDs,
fast-response delivery lookup and publication comment/destination
lookup. Each uses concurrent/idempotent creation and the existing
top-level migration runner. Preserve all landed SQL/journal entries and
the five newest snapshots.

## Verification

Published head: `09ca00b9f029838434ec042cda691345d67b493e`, on landed
continuation parent `063cfd43813cabf18417605fb9eefb9aacf95c8d`.

- **87 distinct current cases pass:** 18 real PostgreSQL acknowledgement
lifecycle/presentation cases, all 26 fast-response service cases, all 30
heartbeat completion cases and all 13 startup cases. Database build,
server typechecking/build, module boundaries and three fresh migrations
through 0400 pass. The current Runner bundle rebuild also passes after
upstream provider-event changes.
- The lifecycle matrix covers empty/history quiet, lease release,
restart, drain/standby, fast-response failure/expiry/publication/unknown
outcome, streaming quarantine, outer rollback/commit, saved provider
retry, stop between requests and receipt state. The real presentation
writer proves quiet while pending, rollback, committed reactivation and
final quiet.
- The earlier **305-case** matrix (236 full GitHub workflow cases, 26
fast-response service cases, 30 completion cases and 13 startup cases)
passes at `337f272853d4f8a51b5b9300900a46eb4e13f698`. It retains its
prepared-parent scope. Repeated cases are not added to current 87.
- A populated 0399 database upgrades to 0400 with all 398 prior
migration receipts unchanged, one new receipt and no additional receipt
on replay. All three indexes are valid/ready on fresh and upgraded
databases. Their SQL definitions match the original draft after
whitespace normalization; migration history and retained snapshot bytes
are preserved.
- Normal integration `9b3607e159153e00ccdfe538d52b591bd38d6499`
preserves the full 28-path owned binary patch and all 20 unrelated
master paths, including native retry, provider-event and evaluation
workflow changes. Both normal merge parents and the exact tree are
checked. No force push or rebase occurs.
- [The owner
audit](https://github.com/paperclipai/paperclip/blob/09ca00b9f029838434ec042cda691345d67b493e/doc/plans/2026-10-25-github-chat-maintenance-sleep-audit.md#acceptance-on-the-actual-landed-continuation-parent)
retains the original missing-notification, JSON precedence, receipt
lifecycle, external-database fixture and migration-registry failures.
Earlier 69/228/broad counts keep their original scope. Skips and failed
revisions are not relabelled as current passes.
- The final audit-only edit leaves all owned source/test/migration
hashes unchanged. **Fresh exact-head CI and Greptile 5/5 with no
actionable findings remain required.** No full local repository, live
GitHub tenant or deployed sleep result is claimed.

## Risks

- Process-local transaction hints cover supported application writers
and shared pools. Independent SQL writers and other replicas do not gain
a new wake guarantee.
- Provider effects remain guarded by the existing publication lease and
current source/principal authority. Unknown outcomes retain their
existing recovery semantics.
- Presentation waits depend on their supported milestone/transaction
producers. A missing producer can defer recovery until another supported
change or restart.
- Index creation can take time on large histories and runs concurrently
outside a transaction. Existing migration recovery handles replay; prior
SQL is unchanged.
- Worker quiet is distinct from host/database suspension. Cloud wake
coverage and sleep admission remain unchanged; later maintenance duties
are separate slices.

## Model Used

OpenAI Codex, using reasoning, repository inspection, code execution and
real PostgreSQL tests. The exact model identifier and context-window
size are not exposed in this session.

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 16:06:42 -05:00
DottaandPaperclip 063cfd4381 fix(server): wake interaction continuations from committed responses (#17653)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/204/changes/paperclip/204
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip coordinates agent work and human approvals.
> - Human decisions already persist the continuation action that resumes
an agent.
> - A response can commit before its callback or publication finishes.
> - Periodic maintenance repeatedly discovers those rows, including when
idle.
> - Committed writes should wake the existing owner; saved retries and
claims supply real deadlines.
> - Startup reconstructs durable work, and settled history becomes
quiet.

## Linked Issues or Issue Description

Refs #17651, which is merged. This existing continuation slice targets
master and removes its duty from periodic chat maintenance.

**Problem:** A saved `interaction_wakeup` action can survive a committed
human response whose callback crashes. Without producer coverage,
removing maintenance strands the continuation. Repeated empty
maintenance also keeps the database active.

**Expected behavior:** The outer transaction's settlement wakes the
continuation owner. It handles ready conversation publications,
dispatches under existing authority, preserves interrupted/retry work,
and becomes quiet after settlement.

## What Changed

- Register continuation recovery with the shared scoped deadline
coordinator. Reconstruct existing issued/processing actions and retain
the existing retry and stale-claim deadlines.
- Notify from both enqueue producers and owner-local claim/settlement
writes. Preserve outer commit/rollback and avoid moving provider or
heartbeat calls into database transactions.
- Give the existing publication queue an optional
company/endpoint/conversation scope. The continuation owner gives ready
cards in that conversation a bounded delivery opportunity before
claiming the action; FIFO, capacity, ambiguity and provider authority
remain with the queue.
- Carry admission/cancellation through publication preparation and check
before every new send. Join in-flight requests and retain pending
actions/publications through drain, standby, shutdown and resume.
- Remove only recurring continuation recovery; keep the manual API. Add
no table. A concurrent partial index on existing pending continuation
actions and matching company/id keyset paging prevent retained history
from being scanned. Parent #17651's indexed confirmation discovery and
current master are retained.

## Verification

Published head: `a1d16f84b3fae361d5d648670a5964486370c3a3`, on actual
landed terminal-confirmation parent
`ee67d2ece9bda157dfad9bdf25175b1d004ed341`.

- **75 distinct current cases pass:** 32 selected real PostgreSQL chat
cases (14 continuation lifecycle/producer/stop cases, one new
continuation query-cost case, and 17 parent confirmation/query-cost
cases; 1,671 skipped), and all 43 cases in complete
interaction-publication and app/startup suites. Database build, server
typecheck/build, module boundaries and fresh migrations through 0399
pass. The original landed-parent matrix passed 74 cases before the
additional query-cost repair; those are not added again.
- The new real-SQL regression seeds 20,000 completed/unrelated actions
and one pending processing claim. Before repair it examines 20,345 rows
and hits 20,421 buffers. The final startup and company-scoped queries
must examine at most two action rows and fewer than 20 action buffers;
empty scoped recovery must also stay below 20 buffers. Planner settings
are unchanged. Migration `0399_ambitious_onslaught.sql` is
concurrent/idempotent and uses the existing top-level migration runner;
prior SQL/journal entries and the five newest snapshots are preserved.
- The matrix covers callback recovery, concurrent responses, malformed
prefixes, more than one page, saved retries/stale claims, outer
rollback/commit, deferred/future/paused publication states, restart,
drain and stop before each new provider request. Quiet assertions
inspect real selects/transactions across virtual idle time.
- Normal integration `db5a84c0f8b73a0ce863f4d2fbaee0a115cf044f`
preserves the complete 12-path owned binary patch and all 12 unrelated
current-master paths, including managed Cloud sandbox changes. A
verified semantic base resolves squash-ancestry conflicts; both normal
parents and the exact tree are checked. The subsequent index/keyset
repair is a deliberate additional change, tested separately; the final
patch is not claimed identical to the original 12-file implementation.
No force push or rebase occurs.
- The same 74 pre-index cases passed on the earlier prepared and actual
landed parents. The new query-cost regression failed before its repair,
then passes on the repaired source. Earlier 57-case and broad acceptance
retain their original revision scopes; repeated cases are not added to
the current count. The audit-only follow-up leaves all owned server
source/test hashes unchanged.
- [The owner
audit](https://github.com/paperclipai/paperclip/blob/a1d16f84b3fae361d5d648670a5964486370c3a3/doc/plans/2026-10-25-interaction-continuation-sleep-audit.md#acceptance-on-the-actual-landed-terminal-confirmation-parent)
retains the original missing-signal regression, the skipped standalone
publication suite, and the review's stop-before-send failures with their
corrections. Skips and earlier failing revisions are not relabelled as
current passes.
- **Fresh exact-head CI and Greptile 5/5 without unresolved actionable
findings remain required.** The former remote head's reviews are stale.
No full local repository suite, live provider or deployed sleep result
is claimed.

## Risks

- Process-local transaction hints cover supported application writers
and shared pools. Independent SQL writers and other replicas do not gain
a new wake guarantee.
- The publication queue's existing FIFO, capacity, retry/ambiguity and
authorization contracts still govern effects. In-flight provider
requests can settle after Stop; the fence prevents a subsequent request
from starting.
- Missing a supported producer can defer recovery until another change
or startup. Producer and rollback tests cover this slice's supported
paths.
- Worker quiet is separate from host/database suspension. External alarm
coverage and Cloud sleep gates are unchanged.

## Model Used

OpenAI Codex, using repository inspection, code execution and real
PostgreSQL tests. The exact model identifier and context-window size are
not exposed in this session.

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 15:45:18 -05:00
DottaandPaperclip ee67d2ece9 fix(server): wake terminal confirmation recovery from committed changes (#17651)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/202/changes/paperclip/202
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip persists confirmation clicks and interaction decisions
before dispatch completes.
> - A crash after a decision commits can leave a processing confirmation
action.
> - Periodic publication maintenance repeatedly scans those actions even
when idle.
> - Saved decisions and the supported board/admin writers already
identify when settlement can change.
> - This owner reconstructs durable actions, reconciles real changes and
then becomes quiet.

## Linked Issues or Issue Description

This existing terminal-confirmation slice follows merged #17649. It
removes only terminal-confirmation recovery from periodic chat
maintenance while retaining the explicit manual API and existing durable
action/interaction/publication rows.

**Problem:** An accepted response can commit before its dispatch
settles. Removing periodic recovery without covering board decisions,
expiry and ownership changes would strand processing actions. Pending
human decisions must remain recoverable without polling indefinitely.

**Expected behavior:** Committed supported changes wake the scoped
owner. It reconciles terminal responses once, parks unresolved human
decisions, preserves concurrent commits/restart/drain and becomes quiet
when settled.

## What Changed

- Register terminal-confirmation work with the existing delivery
coordinator and scoped lifecycle. Reconstruct processing action IDs,
bound selection pages, preserve concurrent wakes and keep current
authorization in the existing interaction owner.
- Add the existing transaction-aware confirmation notification topic at
real resolution writes and callback settlement. Reuse milestone signals
instead of adding per-caller recovery wrappers.
- Cover ordinary and checkbox confirmations, suggestions and connection
intents through their owning service. Cover board accept/reject,
cancellation/withdrawal, opt-in comment supersession, expiry,
reassignment and already-satisfied connection resolution.
- Preserve task/actor authority, one-use callback tokens and immutable
provider publication semantics. Explicitly fail malformed missing
bindings instead of silently retaining unrecoverable processing actions.
- Remove only this duty from recurring publication maintenance. Add no
table or scheduler infrastructure. A concurrent partial index on
existing action rows prevents recovery discovery from scanning completed
history.

## Verification

Published repair head: `a35e78d076c1b618bc643391b7520fa6952fc996`,
targeting master after normal integration of
`644937c93150c423f12674992c7ea1e8b5dbc98c`. [Detailed acceptance and
preserved
failures](https://github.com/paperclipai/paperclip/blob/a35e78d076c1b618bc643391b7520fa6952fc996/doc/plans/2026-10-25-terminal-confirmation-sleep-audit.md#bound-retained-history-reads--october-28-review-repair).

- **New query-cost regression:** Capture the actual SQL emitted by
startup and company-scoped confirmation discovery. Seed 20,000
completed/unrelated action rows and one pending human decision. Before
the index, the regression fails because recovery examines 20,009 action
rows. After the partial index, startup and scoped discovery must examine
at most two action rows and fewer than 20 table/index buffers; the
no-pending scoped path must also stay below 20 buffers. Planner settings
are unchanged, and returned IDs remain correct.
- Match startup keyset ordering to `(company_id, id)`, the partial index
order. The index alone still let PostgreSQL choose the primary key and
scan 20,206 rows for `ORDER BY id`; the final query fixes this without
forcing a planner setting or adding a second index. Fixed kind/status
predicates stay literal for prepared-plan index eligibility.
- Add the generated `0398_yielding_random.sql` migration, using `CREATE
INDEX CONCURRENTLY IF NOT EXISTS` and the existing top-level migration
runner. Keep the five newest generated snapshots and preserve every
prior SQL/journal entry. No work table is introduced.
- **110 distinct cases pass:** 17 final confirmation
lifecycle/query-cost cases (1,671 skipped), seven real Runner descriptor
variants (295 skipped), and all 86
app/startup/bundled-plugin/plugin-database cases. Server/database
typechecking and builds, migration safety/numbering, module boundaries
and a fresh PostgreSQL migration through 0398 pass. The final test-only
vacuum precondition is followed by another 17-case confirmation pass and
server typecheck. Counts are not added across repeated runs. Normal
integration of master `644937c93150c423f12674992c7ea1e8b5dbc98c`
preserves the complete owned patch and all 18 unrelated master paths.
- Previous landed-parent acceptance: 29 distinct cases (16 confirmation
lifecycle/producer cases with 1,671 skipped, plus all 13 startup cases)
passed on `32e64a7e9ea5b457e54ca7b268be90e1e155b451`; the earlier
80-case matrix remains scoped to
`c1e8542b588a4fa59b62f9829541d3daea4f1ddc`. Counts are not added across
repeated runs.
- Actual producer cases prove parking/quiet, caller-owned outer
transaction rollback, commit-driven automatic settlement, restart/drain
and concurrent commits. Checkbox, suggestion, connection-intent and
Telegram/Slack callback paths retain existing authority and immutable
publication semantics.
- **Fresh exact-head CI and Greptile 5/5 with no unresolved actionable
findings are required.** The preceding head's Runner CI failed its
timeout-attachment durable-suspension case (1 failed/1,955 passed/4
skipped); that failure is retained and not counted as a pass. The new
head must pass this job. No full local repository, live provider or
physical suspension claim is made.

The owner audit retains the earlier missing-board-producer regressions
and their corrections, including the invalid supersession fixture that
assumed a new checkbox expires an older one. Existing behavior was
preserved by using the supported opt-in human-comment path. Prior
scheduler/backoff, route and plugin test failures remain at their
original revisions; no old pass is substituted for current remote gates.

## Risks

- Process-local notifications cover supported application writers and
their shared pools, not independent SQL writers or other replicas.
- Processing actions waiting on a human response are deliberately
parked. Supported interaction resolution/expiry writers must use the
notification boundary; a missing producer delays settlement until
restart.
- Invalid bindings have explicit failure evidence. Source, actor, task
and publication authority remain checked by their existing owners.
- Following continuation/GitHub duties remain separate. Cloud sleep
gates and external alarms are unchanged; local worker quiet does not
establish physical host/database suspension or fleet savings.

## Model Used

OpenAI GPT-6 / Codex, with reasoning, repository inspection, code
execution, and PostgreSQL tests. The exact runtime model identifier and
context-window size are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 15:00:31 -05:00
DottaandPaperclip f4f02880ca fix(server): wake failed retry notices from committed changes (#17649)
## Thinking Path

> - Paperclip keeps exact failed chat retries in durable action and wake
receipts.
> - Deferred and declined retries owe safe notices to their original
conversation.
> - Periodic publication maintenance repeatedly inspects those receipts
when idle.
> - Committing receipt, authority, lifecycle and lease changes already
identifies when eligibility can change.
> - A scoped owner reconstructs durable obligations, drains bounded
candidates, retains contention, then becomes quiet.

## Linked Issues or Issue Description

This existing failed-retry notice slice follows #17647. It removes the
failed-retry notice duty from periodic publication maintenance while
preserving the explicit manual API. Existing action, receipt,
publication and source rows remain authoritative; no new table or
scheduler is added.

**Problem:** Removing the scan alone loses notices after real admission,
cancellation, early refusal, requester or agent restoration, and
relevant lease settlement. Millisecond cursor truncation can also repeat
denied history.

**Expected behavior:** Committed supported writes wake the scoped notice
owner, which uses current authorization and precise cursors. Real
retries survive failure, contention, restart and drain; settled work has
no recurring SQL.

## What Changed

- Extract failed-retry projection under the existing authorization
owner. Preserve current receipt/source authority and provider transport
authorization.
- Register bounded scoped work using the existing delivery
coordinator/scheduler. Preserve exact PostgreSQL cursor precision,
contention and a wake arriving during reconciliation.
- Extend the shared transaction-aware notification boundary to
failed-retry notices. Cover admission, conditional denial, early
refusal, requester changes, and agent lifecycle transitions to an
invokable status. Two shared receipt hooks and their budget fixture
correction already landed in the preceding inbound slice; preserve them
once.
- Notify when relevant native lease cleanup completes or a reusable
lease is retired, preserving claim fencing and caller-owned
transactions.
- Avoid the discovery scan identified in #17647: known task scopes
require zero discovery SQL; company/startup discovery uses a single
DISTINCT projection from the same candidate predicate. Bounded current
authorization still runs afterward.
- Remove only this duty from periodic publication maintenance, retain
manual behavior and startup reconstruction, and add real
producer/lifecycle/query-budget regressions with an audit.

## Verification

Published head: `fa95a1f2fb9d546aa62dbd3b43aa714f5c88bd35`, targeting
master after #17647 merged at
`1aa3a21ac41f602977638cf0be875b01a243e69f`.

- **42 distinct current combined-master cases pass:** 21
retry-notice/native-lease/restored-input producer cases (1,651 skipped),
plus all 21 app/startup and task-drain admission-release cases. Server
typechecking, build and module boundaries pass. The final follow-up adds
acceptance documentation only; all 17 owned server source/test hashes
are unchanged.
- The prior **404-case** matrix passes at prepared revision
`c2c53b839497be6f5e28aa2cd5ba50cfd1d76d4a`: 259 across six complete
consumer/lifecycle/environment suites, 20 notice/lease cases, 53
ordinary-notice and 72 Retry/budget cases. Those chat selections skip
1,651/1,618/1,599 cases. A subsequent 21-case combined producer check
passes after the parent restoration repair. These earlier runs retain
their revision scope.
- The normal two-parent integration
`43d0f84ea56845b8fc4946a7533ecbf7f07b679a` preserves the complete
19-path owned binary patch and all 23 unrelated master paths/deletions.
The semantic merge base is the verified landed parent head
`41f7e2c9e351efa6cfa5ef699c0e69df7425012b`; squash ancestry otherwise
causes historical conflicts. Both parent commits and the exact resolved
tree are verified; no rebase or force push occurs.
- Three scope-discovery regressions fail before the fix. The first SQL
projection fails with PostgreSQL 42702 (ambiguous company column), then
passes after using a distinct company alias. Known task hints have zero
discovery SQL; company/startup discovery has one query returning only
distinct task scopes. Existing bounded projection/current authorization
remain intact.
- Current producer tests cover commit/rollback, parked authority
restoration, real agent resume, early refusal, requester changes, native
lease cleanup/replacement, drain/restart/shutdown, precise cursors and
contention. Parent shared admission/denial/restored-input notifications
are preserved once. No polling backstop or storage is added.
- [The owner
audit](https://github.com/paperclipai/paperclip/blob/fa95a1f2fb9d546aa62dbd3b43aa714f5c88bd35/doc/plans/2026-10-25-failed-retry-notices-sleep-audit.md#final-landed-parent-acceptance--october-28)
records current commands, fixtures, failure history and limits. Fresh
exact-head remote checks and Greptile 5/5 are pending; old-head reviews
do not count.

The owner audit preserves prior failures and their original revision
scope. The old remote head's Runner receipt timeout, cancelled gate, and
review error are not current passes; fresh exact-head checks and
Greptile 5/5 are required. No full local repository suite, live provider
tenant, external wake alarm, physical suspension or savings claim is
made.

### Final remote gates

Exact published head `fa95a1f2fb9d546aa62dbd3b43aa714f5c88bd35` has
Greptile 5/5 with no actionable findings, successful current main CI and
ready-triggered security scan. The final dependency/quality review
workflow `40747725096` passed after waiting for a GitHub-hosted runner.
No Ponytail verdict is present.

Two automatic main CI requests and two identical-head quality-review
requests were created one second apart. The older main run was
automatically cancelled; only the proven duplicate, unstarted quality
request was cancelled manually. Their same-head, same-workflow
replacements both finish successfully. The merge guard verifies these
replacements, all current checks and current required-status integration
rules before excluding the superseded cancellation contexts. No actual
failing review or current check is waived and no protection bypass is
used.

## Risks

- Process-local signals cover supported writers using this boundary, not
independent SQL or other replicas.
- Lease completion now reads/locks the exact row before updating.
Reusable lease retirement wakes company scope because its previous issue
can differ. Claims and transaction ownership remain enforced.
- Broad discovery can inspect history inside PostgreSQL; DISTINCT
reduces returned rows and round trips, without claiming constant
database cost. Task hints are wake requests, so bounded reconciliation
handles already exhausted scopes.
- Native filesystem activation belongs to execution authorization and is
not an eligibility input for this notice projection. Other
notice/maintenance duties and Cloud sleep gates remain separate.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, local code inspection,
shell execution, and PostgreSQL testing. The exact serving model
identifier and context-window size are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 14:14:28 -05:00
DottaandPaperclip 1aa3a21ac4 fix(server): wake inbound queue notices from committed changes (#17647)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat users receive a notice when accepted input waits for execution.
> - Periodic publication maintenance scans those receipts even when
nothing changes.
> - Admission, cancellation, source removal, and authority changes
already define when a notice can change.
> - Existing action, receipt, publication, and provider-link rows
preserve that work across restart.
> - This PR gives ordinary inbound queue notices a commit-driven owner
using the shared scheduler.
> - Settled notices stop querying while unfinished batches and
contention retain recovery.

## Linked Issues or Issue Description

This ordinary inbound-notice slice follows merged #17895 and now targets
master. Related extraction: #16187. Failed-run retry notice projection
remains a separate following slice (#17649); its two shared
receipt-writer notifications move forward here because ordinary input
can attach to those receipt owners.

**What happened?**

Publication maintenance scans accepted input to project queued,
not-started, and removed-source notices. Empty scans keep touching the
database. Its cursor also loses PostgreSQL timestamp precision, so a
full page of suppressed candidates can repeat.

**Expected behavior**

Committed changes should wake the notice owner. The worker should
reconstruct saved candidates after restart and stop scanning when
settled. It must retain a wake across drain, failed selection,
contention, and a commit during reconciliation.

**Steps to reproduce**

Start an otherwise idle instance with chat history. Observe the ordinary
inbound notice scan in periodic publication maintenance. For the cursor
defect, retain a full page of denied candidates with microsecond
timestamps before an eligible notice.

## What Changed

- Register an ordinary inbound-notice owner with the existing delivery
coordinator and scheduler. Bound each pass to 100 candidates, preserve
precise continuation cursors and earlier-page contention, and reset
scoped discovery after committed changes.
- Notify from real admission, failed action settlement, source removal,
task/tree/agent/budget/company cancellation, signed Slack Stop, and
deferred queue cancellation/failure. Preserve pending-status and
absent-run guards so concurrent promotion wins.
- Cover task privacy/grants, project membership/visibility and current
authority through their persistence owners. Keep receipt ownership,
current authorization, provider policy and closed notice text in the
existing chat service.
- Cover shared retry-owned receipts through the existing durable
authorization callback and a notifying transaction around conditional
denial retirement. These small producer fixes already exist in #17649;
no per-caller recovery wrappers are added. Retain its matching
budget-refusal fixture correction.
- Remove only ordinary notices from periodic maintenance. Preserve the
separate failed-retry pass at 50 and keep the explicit combined manual
API.
- Preserve timestamp precision, fairness, restart, drain/resume,
rollback and quiet behavior. Add two real producer transaction
regressions and update the audit. Add no storage or scheduler
infrastructure.

## Verification

Current publication head: `41f7e2c9e351efa6cfa5ef699c0e69df7425012b`,
after normal merge of master `d30c8f42b842327ee1c18c41a2efd6ba623da5cd`
(#17960). The integration preserves both complete added/removed patches,
all non-overlap upstream blobs/deletions, and task-before-comment lock
order before the notice source lock/intent. Full binary identity is not
claimed for the overlapping files. The final follow-up changes
acceptance documentation only.

- **202 distinct combined-master cases pass on
`1720b685d9d5fb9cb4377223fdaa0a9fae2aff9c`:** 148 across the real
PostgreSQL receipt concurrency and two comment route suites, plus 54
notice/FIFO/producer cases (1,598 skipped). Current server
typechecking/build and module boundaries pass; all 21 owned source/test
hashes are unchanged after the documentation follow-up.
- The earlier CI voice-reconstruction quiet assertion failed once after
105 fetches. All 15 voice lifecycle cases pass unchanged locally; no
assertions or production code were relaxed and no CI retry was used. The
original failure remains in the audit, and current-head full CI must
pass.
- **Earlier restoration repair (head
`28c898e93504318056d7a6ab2bbc5eafa6b639ae`): 126 distinct selected cases
pass (54 ordinary-notice/producer cases with 1,598 skipped, plus 72
separate Retry/budget cases with 1,580 skipped).** Fix the blocking
[restored input stays
silent](https://github.com/paperclipai/paperclip/pull/17647#discussion_r4404007181)
finding. A failed Retry's earlier receipt wake can drain before
`releaseUnadmittedTaskRetryInput` restores ordinary receipts in a later
transaction. The restoring transaction now awaits the existing
company/task notification before its guarded write.
- The new causal regression builds a durable unadmitted failed-Retry
owner, uses the real input-claim owner, consumes an earlier committed
wake, and proves two minutes of worker quiet with no notice. The real
release transaction then restores the ordinary row, emits intent/commit
settlement, and reactivates the coordinator to create its queued notice.
It fails before the hook with the restored row visible but no intent.
This is real PostgreSQL producer/consumer boundary proof with seeded
Retry-refusal state; the separate compatibility selection exercises
existing supported GitHub Retry flows. It is not a claimed complete
public-request failure walkthrough.

- **Earlier discovery-repair acceptance (revision
`4a713edfa06b9d3dcc0e81e900006fbdb973b2d9`): 267 distinct selected cases
pass:** 142 complete cancellation/app/admission consumer cases, 53
ordinary-notice cases, and 72 separate retry/budget cases. The
selections skip 1,598 and 1,579 other cases. The final master
integration leaves this complete patch byte-identical; the new master
paths concern provider workspace/session reuse and E2E reports.
- Fix the valid P2 [discovery rereads denied
history](https://github.com/paperclipai/paperclip/pull/17647#discussion_r4386889825),
despite the previous head's 5/5 summary. Task hints now need zero
discovery SQL; company/startup discovery returns DISTINCT company/task
identifiers with one query. Bounded projection still checks current
authority and candidates. Three real database regressions with 250
denied actions and a second company fail before the fix and pass
afterward, checking actual query and returned-row counts. Broad SQL may
still inspect candidate history; no constant database-cost claim is
made.
- Both new producer tests fail before their fixes and pass afterward.
One observes intent before a callback-owned receipt write and settlement
after outer commit. The other uses real heartbeat admission/recovery and
a PostgreSQL row lock to prove exact company/task intent exists before
conditional denial retirement; the outside connection still sees
deferred status until commit.
- The reader can select a retry-owned deferred receipt for later
ordinary input, and receipt resolution follows its owner. Disabling
coalescing on the retry's own request does not exclude that later path.
The two transferred notifications close the actual writer gaps; current
authorization remains enforced by existing consumers. This is
producer/transaction proof, not a claimed complete mixed-ingress
walkthrough.
- The moved callback exposes an old test mock that authorized against
the root DB. The existing #17649 fixture correction authorizes and
writes in one transaction; original requester, comment, skipped-status
and budget assertions remain. Both the initial invalid lock fixture and
the corrected missing-intent failures are preserved in the audit.
- Updated shared dependency build, server typechecking/build and
module-boundary checks pass. Because master also changed agent
configuration, upgrade admission and runner contracts, the same 264
cases were rerun on combined revision
`875a6ee8d211cba7f0499aace7fcea7f6880c4a2` with new isolated databases.
Repeated checks are not 528 different tests. Tests under `src/__tests__`
were executed separately from production typechecking.
- [Current acceptance and preserved failure
ledger](https://github.com/paperclipai/paperclip/blob/41f7e2c9e351efa6cfa5ef699c0e69df7425012b/doc/plans/2026-10-25-inbound-wake-notices-sleep-audit.md#shared-retry-receipt-producer-gap-resolved-october-28)
records current scope, exact commands, actual fixtures, source hashes
and remaining limits. Earlier baseline/full-suite counts retain their
original revision scope.
- Server typechecking/build and module boundaries pass after the current
restoration hook. The earlier combined-master compilation at
`661f2f6da8c6c22cdcc25edccd57502ee6fa8c4b` retains its original scope.
- **Current exact-head CI is green and Greptile is 5/5.** The old head's
review error is not a pass. No full local repository matrix, live
provider tenant, external alarm, physical suspension or savings claim is
made. Following notice duties retain their separate owners.

### Final merge verification

- Reviewed PR head remains `41f7e2c9e351efa6cfa5ef699c0e69df7425012b`:
exact-head Greptile 5/5, all 55 check contexts clean, no unresolved
review threads, and no Ponytail verdict present.
- One Runner shard initially failed descriptor suspension and a
five-second OpenCode fixture deadline. The same package passed on the
preceding head. The first local attempt was invalid because required
Rust fixture binaries were absent; after building them, all eight
relevant cases pass with unchanged timeouts. One failed-job retry then
passes 1,956 cases (four skipped). No source/assertion/time-budget
change or second CI retry was used.
- Current master `0e365768f032a472807b5720da8431f92d2f07ce` adds manual
monitor and task-drain fixes. Its routes file overlaps but merges
cleanly. Local normal-merge validation commit
`2720b79c769cb609ad4d392512331e67b910ff3f` preserves both complete
added/removed patches and every unrelated master blob/deletion. This is
not raw binary identity for overlapping files.
- **156 distinct cases pass on that exact combined tree:** all 102
monitor/drain/policy cases plus 54 notice cases (1,598 skipped). Types
and build pass. An initial competing-cold-check run failed setup hooks
(38 passed, two hook failures, 62 skipped); the same four suites pass
alone with all original hook/test timeouts and assertions intact. The
failed run remains recorded, not counted as full acceptance.
- This merge proof changes no published source or review head. The
protected pinned-head merge guard recomputes both patches and requires
the exact tested master/tree/head, successful validation receipts and
unchanged live merge gates. Previous acceptance counts retain their
original revision scope; no local full-repository or deployed-sleep
claim is made.

Master then advanced to `75754ffb7af2b7ee7dce1e915a145faa82a8fb2a` with
#17976 (five UI/e2e/map files only). The entire `server` and `packages`
trees are identical to the validated composition. Both complete patches
and all newly landed UI files are preserved in the final clean merge
tree; the protected gate checks these exact source-root hashes and
changed paths. No additional UI-test result is claimed.

## Risks

- Missing a supported producer could delay a notice until restart. Tests
cover real service and API producers; durable rows remain authoritative.
Notifications cover supported application writers in the owning process,
not arbitrary external SQL writers.
- Privacy invalidation can affect descendants, so those changes use
company scope. Ordinary admission and publication changes use task
scope. Settled history causes no recurring scan.
- Provider output remains subject to current authority and receipt
ownership. A cancelled request without a visible queued notice does not
acquire a new failure message.
- This establishes worker quiet, not host or database suspension. Cloud
alarms and conservative sleep gates do not change. Other maintenance
remains in place.
- Remaining stacked slices still need their own integration, review, and
CI. This slice merges only under the user’s explicit campaign
authorization after current-head gates pass.

## Model Used

OpenAI Codex, GPT-6 family, with repository inspection and code
execution tools. The exact serving variant and context-window size are
not exposed in this session.

## Checklist


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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 13:34:38 -05:00
DottaandPaperclip 5f0da562db fix(server): wake chat lifecycle milestones from committed changes (#17606)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connected chats show safe notices when a run starts, waits,
finishes, or fails.
> - A recurring scan projected these notices even when no eligible work
existed.
> - Eligibility depends on committed run state, conversation lineage,
and current authority.
> - Existing database rows can reconstruct that work after restart.
> - This PR wakes a scoped worker from those writes and removes
lifecycle polling.
> - Native progress events keep their separate existing owner until the
next migration.

## Linked Issues or Issue Description

**What happened?**

The chat maintenance timer repeatedly scanned run lifecycle state. Empty
and settled instances still queried the database. A run-status event
alone cannot replace the scan: prompt receipts, continuation receipts,
identity changes, and restored authority can make a run eligible later.

**What did you expect?**

Committed changes wake projection. Startup reconstructs eligible work. A
completed pass stops until another relevant change arrives. Failed work
retains recovery without scanning settled history forever.

**Steps to reproduce**

Configure an automatic chat endpoint. Finish its work, or leave it
unused. Observe recurring lifecycle projection queries from the chat
maintenance callback.

Stacked on #17592. Related foundation: #15625. This PR owns lifecycle
milestones only.

## What Changed

- Preserve upstream coalesced Cloud membership writes together with
locked membership restoration and its committed chat notification.

- Signal milestone eligibility from the real Slack account-link
transaction.

- Register the lifecycle worker with the existing delivery coordinator.
Remove lifecycle projection from the periodic chat callback. Keep native
progress in a separately named lane and preserve the explicit combined
API.
- Reconstruct company/issue scopes from the existing selector. Drain
bounded batches with company fairness. Retry failures, retain writes
through drain/resume, and disarm settled work.
- Signal from supported run, presentation, interaction, receipt,
lineage, conversation, recovery, and authority writers. Preserve their
transaction ownership, including nested savepoints and uncertain
settlement. No new table is added.
- Preserve provider authorization, authored-final suppression,
responsible-user continuity, deduplication, the 24-hour selection
window, and raw-output restrictions. Keep provider interpretation in its
owner.
- Preserve PostgreSQL timestamp precision in lifecycle pagination.
Rejected submillisecond candidates must not repeat the same page and
starve later notices.
- Document producer coverage and alternate-writer dispositions in
`doc/plans/2026-10-25-chat-run-milestone-sleep-audit.md`.

## Verification

Published head: `1d056f68c5b1005933b9e12de8745bf1c4cbeeca`, targeting
master after #17592 merged at
`7d75ae0569e41786640cf09647ae8849411d2f22`. A normal merge integrates
the actual landed parent. The entire 77-path milestone patch is
binary-identical to the locally verified preparation across that
ancestry reconciliation; both unrelated master paths are preserved. The
four earlier producer/test integration conflicts retain scoped milestone
and voice notices, current onboarding completion admission, and expanded
identity query/read-scope coverage.

- **330 distinct selected cases pass on the verified unchanged patch:**
305 across 14 complete suites (all five milestone worker suites, run
identity, board claim, Cloud provisioning, auth session routes, Cloud
actor authentication, stale-lock recovery, GitHub credentials, project
Git authorization, and app admission wiring), plus 25 selected real chat
producer cases. The remaining 1,590 chat integration cases were skipped,
not passed.
- The real producer cases cover saved milestone discovery, GitHub and
Slack identity changes, account-link rollback/reconfirmation, ordinary
ingress reactivation, post-close action/delivery receipt settlement, all
ten authority-restoration paths including Cloud synchronization, and
changed native review metadata.
- Worker coverage verifies outer commit, rollback, uncertain-write
recovery, restart, bounded batching/fairness, timestamp precision,
retries, drain/resume, and settled SQL quiet. Authorization and existing
publication deduplication remain with their owning services.
- Server production typechecking, build, and module-boundary checks
pass. The tests above were executed separately. Production typechecking
excludes `src/__tests__` and does not replace those runs. Each database
owner uses its own newly created and app-migrated PostgreSQL fixture.
- [Current-parent acceptance and preserved failure
ledger](https://github.com/paperclipai/paperclip/blob/1d056f68c5b1005933b9e12de8745bf1c4cbeeca/doc/plans/2026-10-25-chat-run-milestone-sleep-audit.md#current-parent-integration-and-acceptance-october-28)
records commands, counts, producer scope, conflict dispositions, and
limits. Earlier combined-stack counts and failures keep their original
revision scope; local acceptance does not erase old CI failures.
- No new migration, queue table, dependency, workflow, or shared
scheduler contract is introduced. Parent migration 0397, bounded consent
recovery, voice cleanup/retention repairs, and runner checkpoint
restoration remain present.
- **Exact-head Greptile is 5/5 and all 55 current checks are clean.** No
Ponytail review is present, which is an explicitly authorized
nonblocker; no failing review is waived. Older reviews and parent checks
are not current passes. Actual failing Ponytail findings must be fixed;
an absent/stopped/paused turn without a verdict is an authorized
nonblocker. Active unfinished Ponytail uses its original request/start
timer, with a 25-minute monitor cutoff respecting the user's 30-minute
maximum.
- No complete local repository matrix, live provider tenant, external
alarm, physical host/database suspension, or fleet savings claim is
made. Native progress remains a separate following slice.

## Risks

- A future eligibility writer must notify the existing projection
boundary. Independent SQL writers or another active server process are
outside this process-local signal contract.
- Authority and lineage remain sensitive. The worker uses the existing
selectors and publication policy; it does not grant execution or
disclosure authority.
- Native progress and other publication maintenance still have recurring
work. This PR removes one reason, not the entire chat maintenance timer.
- Worker quiet does not prove database suspension, host sleep, or
external alarm coverage. Cloud sleep blockers remain unchanged.
- Merge eligibility requires passing current-head CI and Greptile 5/5
after this actual-master reconciliation. Subsequent stack slices retain
their own gates.

## Model Used

OpenAI Codex, GPT-6 family. The exact serving model ID and
context-window size are not exposed. Used repository inspection,
reasoning, shell execution, PostgreSQL tests, browser E2Es and GitHub
tools.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details available in this session)
- [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 the documented focused 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-28 11:07:54 -05:00
DottaandPaperclip 7d75ae0569 fix(server): recover Teams attempts from saved claim deadlines (#17592)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Teams file delivery saves a claim before each provider operation.
> - A crashed operation can leave that claim unfinished.
> - Periodic maintenance scans for abandoned claims even when none
exist.
> - This PR wakes recovery from committed changes and the saved claim
deadline.
> - Empty work becomes quiet while unknown effects remain safe to
review.

## Linked Issues or Issue Description

**What existing behavior does this improve?**
Teams abandoned file-transfer recovery. This is slice 27, stacked on
consent expiry #17590.

**Current behavior**
The remaining Teams maintenance callback scans every 30 seconds for
expired transport claims. It runs from shared publication maintenance.

**Proposed behavior**
The Teams owner reconstructs existing claim deadlines at startup and
reloads a transfer after its committed update. At expiry it clears the
claim and preserves the existing unknown-outcome or conflict state.
Normal receipt settlement removes the deadline.

**Reason and benefit**
Remove the last periodic Teams maintenance scan without resending a
possibly delivered card or file.

**Breaking changes**
No schema or public API change. Explicit diagnostic recovery methods
remain compatible. Consent expiry stays with its separate parent worker.

## What Changed

- Add a Teams-owned worker for consent_sending, uploading,
file_info_sending and conflict rows with a saved attempt expiry.
- Notify from the existing versioned update before writes. Preserve
transaction ownership and shared uncertain-write reconciliation.
- Expose a narrow per-transfer recovery method that uses the existing
lock order, integrity checks and atomic projection.
- Remove the periodic Teams maintenance callback and its
publication-maintenance invocation.
- Add real claim, receipt, conflict, backlog, restart, precision,
failure, drain and shutdown tests. Wire the owner through existing app
admission gates.
- Retain the existing signoff cancelled-run selection test and GitHub
inline retry-window race assertion.
- Document supported writers, remaining sleep limits and the failure
ledger in `doc/idle-teams-attempt-recovery.md` and its linked audit.

## Verification

Published head: `24c54399909105984e2a10f5869064984f69c472`, targeting
master after consent #17590 merged at
`4a89456bb3f9aef87cfe0e922e8b9d1a777a6c7e`. A normal ancestry merge
reconciles the landed squash with the previously verified child. The
complete 13-path binary patch is identical before and after
reconciliation, and all 30 unrelated master paths are preserved. This
adds no new worker behavior; the 239-case local evidence below belongs
to the verified unchanged patch. All 58 current-head checks are now
clean, including the complete required CI run. Greptile is 5/5 at this
exact head. The current Ponytail turn is paused without a verdict, which
is an explicitly authorized nonblocker; no failing review is waived.

The complete 13-path slice preserves the reviewed attempt implementation
and inherits the parent's report migration 0397, bounded consent worker
and retention CI test repair. No new schema, queue table, shared
scheduler contract, workflow or lockfile change is added by this duty.

- **239 distinct selected cases pass:** 221 across five complete
transfer/publication/consent/runtime/app-wiring suites, 16 selected real
Board/Teams-authority/GitHub-retry integration cases, and two delegated
Slack policy cases. Other chat integration cases (1,579) and
connection-management cases (81) were skipped, not passed. Each database
owner uses a new isolated PostgreSQL database.
- Real Board publication saves an active attempt deadline; its confirmed
receipt retires recovery, and SQL stays quiet afterward. The inherited
consent producer and authority cases still pass. Lifecycle coverage
exercises claim stages, unknown-outcome quarantine without repeating
provider I/O, conflicts, rollback, restart, precision, backlog/fairness,
failure recovery, drain and shutdown. The changed GitHub metadata/retry
race passes without duplicate assessments.
- The old server10 CI failure, run `40557802358` job `122390238707`, was
a delegated Slack invitation rate-window assertion (2,122 passed/one
failed/15 skipped in that shard). The verified parent already contains
its Date-only fixture fix. Both linked and invitation cases now pass
their full caller/target/shared-policy scenarios on a fresh server
fixture; no duplicate policy change or new owned file was added. That
old failure is preserved rather than called a pass.
- Server production typecheck, build and module-boundary checks pass.
Test files were executed; production typechecking does not statically
check them. The existing test-only signoff cancelled-run selection fix
is retained but was not executed locally in this acceptance; fresh
remote E2E gates remain required.
- [Current-parent acceptance and preserved failure
ledger](https://github.com/paperclipai/paperclip/blob/24c54399909105984e2a10f5869064984f69c472/doc/plans/2026-10-25-teams-attempt-recovery-sleep-audit.md#current-consent-parent-preparation-and-acceptance-october-28)
records current scope, commands, counts and limits. Earlier 235-case and
combined-stack counts belong to their stated revisions and are not added
to 239. The [stack
ledger](https://github.com/paperclipai/paperclip/blob/24c54399909105984e2a10f5869064984f69c472/doc/plans/2026-10-24-recurring-server-sleep-stack.md)
retains inherited failure history. No complete local repository suite,
live Teams/Slack tenant, external wake, physical suspension or savings
claim is made.
- **Exact-head Greptile 5/5 and all 58 checks are clean.** Actual
failing Ponytail findings must be repaired; a missing/stopped/paused
turn without a verdict is an authorized nonblocker. An active no-verdict
turn waits at most 30 minutes from its original request/start (25-minute
monitor cutoff). Older reviews and parent checks are not treated as
current passes.

## Risks

- Recovery must not infer that an expired claim means a provider effect
did not happen. It retains unknown outcomes and does not resend.
- Late receipts must still match current claim identity. Current-state
rechecks and existing protocol tests preserve this fence.
- Supported deployment uses one active writer process through its owning
DB client. Independent SQL and additional processes need a separate wake
contract.
- Cloud external alarm coverage and sleep eligibility are unchanged.
Other chat duties still run periodically until their own migrations.
- Voice-report parent review repairs are propagated: explicit
single-active-writer scope and an indexed report window. Thirty
report-worker/startup tests pass on the combined child. Fresh remote
checks, older stack findings and final master reconciliation remain
required.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either linked existing issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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-28 10:51:16 -05:00
DottaandPaperclip 4a89456bb3 fix(server): schedule Teams consent expiry from saved deadlines (#17590)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Teams file delivery saves consent and transfer state in the
database.
> - Unused consent must expire even when no new message arrives.
> - The maintenance loop currently checks this state every 30 seconds.
> - This PR schedules each existing consent deadline and wakes on
committed changes.
> - Empty or settled consent work stops querying while expiry remains
recoverable.

## Linked Issues or Issue Description

**What existing behavior does this improve?**
Teams unused file-consent expiry. This is slice 26 of the
recurring-server migration stack, following merged #17586 and targeting
master.

**Current behavior**
The Teams maintenance callback scans for expired unused consent and
abandoned transport attempts together, even when consent work is empty.

**Proposed behavior**
The Teams owner reconstructs unused consent at startup and reloads one
transfer after a committed write. The shared scheduler runs its saved
expiry. Abandoned attempts keep their current recovery until a separate
slice migrates them.

**Reason and benefit**
Remove unnecessary consent queries without losing expiry, atomic
publication projection, or recovery after restart.

**Breaking changes**
No schema or API change. The explicit combined recovery method remains
available. Cloud sleep eligibility and external alarms remain unchanged.

## What Changed

- Add a Teams-owned scoped deadline worker for the three unused consent
phases. Registered reconstruction yields after one 100-row page per
scope refresh and resets cursors on registration; the explicit
diagnostic inventory still returns every eligible row.
- Signal before insertion and the existing versioned update inside the
owning transaction. Nested writes wait for outer settlement.
- Extract the existing locked per-transfer recovery operation. Preserve
authority checks, atomic projection, bounded lock waits and
unknown-outcome quarantine.
- Remove unused consent from periodic maintenance selection and
execution. Keep abandoned attempts as a separate obligation.
- Register the worker through existing app lifecycle gates. Add
lifecycle, producer, production wiring and precision regressions.
- Document supported writers, remaining sleep limits and the failure
ledger in `doc/idle-teams-consent-expiry.md` and its linked audit.

## Verification

Published head: `9e84cfab1f795279c8cec413a946631f1d781bd2`. This
follow-up changes only the inherited voice-retention test and its CI
failure ledger; all production behavior is unchanged from `36f43922`. It
normally merges actual landed master/report parent
`8049fbf51d0701ca6b242e4b1198e5449f7661b2`. The verified 12-path Teams
patch was byte-identical across the actual-parent ancestry integration.
This test-only CI follow-up adds one existing retention test path,
bringing the final scope to 13 paths. Every unrelated master change,
report documentation fix, and migration 0397 is preserved. No database,
shared-worker, workflow or lockfile change belongs to this slice.

- **223 distinct selected cases pass:** 209 across five complete
transfer/publication/consent/runtime/app-wiring suites, plus 14 selected
real Board-producer and Teams-authority integration cases. The other
1,580 integration cases were skipped, not passed. The protocol and
production consumers use separate new PostgreSQL databases migrated
through the application migrator.
- A real 105-transfer regression failed against the original worker
because one registered startup pass selected 105 rows instead of
yielding at 100. The corrected worker uses the existing paged shared
contract. Restarting the same service midway through discovery selects
the first 100 again, restores all 105 saved deadlines and expires them
at the original deadline. SQL is quiet before the deadline and after
settlement, with no consent-card or upload requests. The one-shot
inventory still returns all 105 rows.
- A guarded mutation removing only cursor reset fails at five rows
instead of 100 after restart. The original production source was
restored before the complete suites. The initial regression fixture
incorrectly faked network timers before its first SQL connection and
timed out; that setup failure is retained separately from the corrected
105-versus-100 regression. No assertion or timeout was weakened.
- The real Board producer registers the worker before publication,
commits the transfer wake, preserves the saved expiry, remains SQL-quiet
until due and atomically projects expiry to a cancelled publication
without another provider request. Existing authority and consent
transitions remain covered.
- Complete lifecycle coverage retains all three consent phases,
precision rounding, rollback and held outer commit, exact-row hints,
expiry recheck, failed projection retry, corrupt-row fairness,
drain/resume, shutdown and separation from abandoned-attempt
maintenance. Production server typecheck, build and module boundaries
pass. Server production typechecking does not statically check test
files; those files were executed.
- [Current bounded reconstruction and failure
ledger](https://github.com/paperclipai/paperclip/blob/36f43922b0a408f76adb7de31280812e9b752019/doc/plans/2026-10-25-teams-consent-expiry-sleep-audit.md#bounded-reconstruction-and-current-parent-acceptance-october-28)
records exact scope, counts, guarded mutation, corrected timer setup,
earlier fixture failures and limitations. Earlier 222-case and
combined-stack results belong to their stated historical heads; they are
not added to 223 or claimed rerun here. The [stack
ledger](https://github.com/paperclipai/paperclip/blob/36f43922b0a408f76adb7de31280812e9b752019/doc/plans/2026-10-24-recurring-server-sleep-stack.md)
retains inherited failure history. No complete local repository-suite,
live Teams tenant, Cloud wake, host/database suspension or savings claim
is made.
- **Fresh exact-head Greptile 5/5 and all CI are required.** Actual
failing Ponytail findings must be repaired. A missing/stopped/paused
turn without a verdict is an authorized nonblocker; an active no-verdict
review waits at most 30 minutes from its original request/start
(25-minute monitor cutoff). Older scores and parent checks are not
accepted as current passes.

- **Preserved inherited CI failure:** prior head `36f43922` had
exact-head Greptile/Ponytail 5/5 but CI run `40708566195` server6 job
`122887395220` failed the retention fairness assertion (2,291 passed/one
failed/one skipped in that shard). A fixed final UUID reproduces the
wrong expectation that an undiscovered page-two row is already deleted.
The corrected test controls time, expects that row to remain before
discovery and requires its deletion in the next fair batch, then all
remaining history and idle SQL. The existing five-second wait budget and
global timeout are unchanged. All 13 retention lifecycle cases pass;
bypassing company rotation fails the corrected assertion, and the
original shared helper is restored byte-for-byte. Earlier 223-case Teams
acceptance remains valid for unchanged Teams source and is not relabeled
as a new complete repository run. [Full CI repair
ledger](https://github.com/paperclipai/paperclip/blob/9e84cfab1f795279c8cec413a946631f1d781bd2/doc/plans/2026-10-25-teams-consent-expiry-sleep-audit.md#inherited-retention-ci-fairness-repair-october-28).
Fresh CI and exact-head reviews are required for this test-only
follow-up; old scores are stale.

- **Current merge gates:** all 58 checks are now clean for this exact
head and Greptile is 5/5 with no actionable findings. The current
Ponytail turn is paused without a verdict, an authorized nonblocking
state. Workflow `40712464720` attempt 1 independently hit npm
`ECONNRESET` during the serialized8 job's tool self-installer, before
its tests ran. Exactly one targeted job retry was requested after the
original workflow finished; attempt 2 completed successfully on the
unchanged head. No code, dependencies, workflow, timeout or review timer
changed for that retry. The original setup failure is retained in its
[job
log](https://github.com/paperclipai/paperclip/actions/runs/40712464720/job/122901243926);
the successful replacement is [job
122910350074](https://github.com/paperclipai/paperclip/actions/runs/40712464720/job/122910350074).

## Risks

- Missed supported producer signals could delay expiry until restart.
Real insertion, cancellation, consent transitions, caller-owned
transactions and Board publication are covered.
- Corrupt or locked rows must retain retry without starving healthy
work. Paging, fairness, atomic rollback, redaction, drain/resume and
shutdown tests cover these paths.
- Independent SQL writers and other processes need their own
notification contract. No persistent DB listener is added.
- Attempt recovery still scans periodically until the next slice. A
local deadline is not a durable Cloud alarm. This PR does not claim
whole-instance sleep.
- This slice is reconciled with its landed parent; current-head remote
checks/review and live-master composition proof still gate merge. Later
stack duties remain separate PRs.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either linked existing issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [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-28 10:32:30 -05:00
DottaandPaperclip e93732c3d4 fix(server): deliver voice replies from commits and saved deadlines (#17578)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Phone calls receive approved answers from the existing chat
publication queue.
> - The chat maintenance timer checks for voice replies every second,
including when no reply is ready.
> - A reply can be saved before its publication commits. An early wake
alone can miss that final transition.
> - Existing session, reply, publication, and action rows already record
delivery and recovery work.
> - This pull request uses committed changes and saved deadlines to
drive phone reply delivery.
> - Empty reply queues become quiet while authorization, ordering, and
uncertain-send protection remain in place.

## Linked Issues or Issue Description

Stacked on #17576. Related delivery infrastructure: #15625. Related
voice connection work: #11418.

**What existing behavior does this improve?**

Background phone reply delivery and recovery of abandoned dispatch
intents.

**Current behavior**

Chat maintenance calls voice reply delivery every second. It also scans
old dispatch intents. Publication transport starts a direct push before
the final publication commit. The timer masks that timing gap.

**Proposed behavior**

Committed publication, reply, session, and configuration changes wake
the shared coordinator. Ready replies drain in bounded passes. Saved
rate-limit and dispatch-expiry deadlines retain recovery. An empty queue
or a permanent delivery barrier has no recurring reply scan.

**Reason and benefit**

Remove recurring SQL from idle phone reply delivery without dropping
replies, replaying uncertain sends, or adding a queue table.

**Breaking changes**

No API or schema change. Explicit manual recovery remains available.
Inbound admission cleanup, history retention, and reports remain on
their current paths for separate migrations.

## What Changed

- Extract ordered reply state and multipart policy within the voice
owner. Retain current authorization and atomic dispatch claims.
- Register a scoped reply worker with startup reconstruction, fair work
batches, failure backoff, drain/resume handling and shutdown ownership.
- Extend the existing shared dispatcher with normalized partial-page
results to preserve the bounded parent recovery contract. Existing
complete-array consumers retain their calls.
- Signal before relevant writes in their existing transactions. Both
normal publication completion and operator resolution wake the actual
conversation after commit.
- Bound reply inventory to 100 total headers per refresh. Preserve
partial scans, concurrent changes and newer denied-call restoration
obligations across reconstruction.
- Track abandoned dispatch actions independently of live calls.
Quarantine expired intents without resending them.
- Use existing active-call authorization checks to reactivate replies
that were previously denied. Healthy call inspections do not rescan
empty reply queues.
- Remove the periodic reply scan and the early direct publication push.
Keep provider requests outside database transactions.

## Verification

Published head: `1435cab10be3f95c38ab6672d2a890ae49e9d300`. Voice
recovery #17576 has landed at master
`e1ba77f06771a27114b3999004b0ca5e3c172dd4`. A normal merge reconciles
squash ancestry while preserving the complete reviewed 31-file reply
patch byte for byte and all unrelated master changes. The PR now targets
master; fresh exact-head CI and Greptile are required. The prior
449-case/typecheck/build results below cover the identical owned source,
not a new full-suite run.

- **449 distinct targeted cases pass**: 111 complete voice-store/reply;
19 complete parent recovery; and 319 complete tool-gateway,
secret-proposal, shared dispatcher/coordinator/batching/startup/hostname
cases. Production server typecheck and build pass. The policy checker
and its Node tests pass. Later edits record evidence only.
- Two real normal-publication/operator-resolution tests seed 105
unrelated calls and 105 future dispatches. Five publications selected
**1,065/1,060 inventory rows before repair**; both paths now pass the
same **125-row total budget** and deliver every answer once. This counts
selected SQL results, not physical tuple visits or host savings.
- Publication commits now signal their actual conversation. The voice
reader returns at most 100 total session/action headers per refresh,
preserves phase/cursor state and retries, and resets on worker
registration. Current-state checks and dispatch claims still own
provider effects. The 105-action case measures the page cap, restarts
the same owner during reconstruction, waits at saved future deadlines
and quarantines every abandoned action without resending.
- A real 403 fixture proves that an older broad scan cannot erase a
denied call first observed behind its cursor. Its owner callback still
emits the committed restoration wake after scan completion. The existing
actual-service authority-restoration and final-publication timing tests
remain in the full suite. They are not replaced by direct helper calls.
- Guarded removal of conversation scoping, cursor reset or the denial
revision fence fails the intended budget, 100-versus-5 restart or
missing committed-wake assertion; source is restored. An initial
shadowed fixture name and an inadequate due-action reset probe are
retained as failed attempts in the [current
audit](https://github.com/paperclipai/paperclip/blob/d2c0a7de8c3e9cac8382b1268f3f5d883a2067b3/doc/plans/2026-10-25-voice-reply-delivery-sleep-audit.md#publication-inventory-and-paging-acceptance-october-28).
- Parent recovery still passes paging, restart, behind-cursor insertion,
feature changes, actual disablement, quiet health observations, current
authority, exact-scope failure fences and wildcard-failure isolation
through the shared worker. Four existing array-based worker consumers
retain their API and pass their full suites.
- The two voice fixtures self-migrate separate empty databases. Legacy
tool-review/secrets suites use separate migrated clones. Earlier
full-local attempts remain limited by embedded PostgreSQL setup and are
not passing full-matrix claims. Older counts apply only to their stated
revisions. Fresh exact-head Greptile, Ponytail if present, security and
all CI remain merge gates. No live-provider, multi-writer,
external-wake, deployed-sleep or savings claim is made.

## Risks

- Missing a supported producer can strand work. Tests cover real
enqueue, retrieval, normal publication, and operator publication paths.
Startup reconstructs existing records.
- Signals cover the process-local database owner. Independent SQL
writers or other replicas need their own wake contract.
- Authority restoration relies on the existing live-call recovery check.
This dependency must be preserved if that owner changes later.
- A provider acceptance receipt does not prove speech. Unknown outcomes
remain blocked from automatic resend.
- This change does not extend Cloud alarms, allow sleep during live
calls, or prove deployed suspension or cost savings.

## Model Used

OpenAI GPT-6 via Codex, with repository inspection, reasoning, code
execution and test tools. The runtime does not expose a more specific
deployment identifier or context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used with the available 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 described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket identifier
- [x] I have run the selected 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 risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 07:50:27 -05:00
DottaandPaperclip dce0042593 fix(server): wake chat receiver discovery from configuration and lease deadlines (#17572)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat receivers own persistent provider connections and fenced
database leases.
> - The chat maintenance timer repeatedly queries all eligible
receivers, including when none exist.
> - Configuration changes and known lease deadlines already identify
when discovery is needed.
> - This pull request moves receiver discovery to the shared delivery
coordinator.
> - Empty or settled discovery stops querying, while ownership and
recovery remain explicit.

## Linked Issues or Issue Description

Refs #17557. This is the next stacked slice after Discord command
registration. The base is `codex/sleep-19-discord-command-registration`.

**What happened?**
The recurring chat maintenance lane scans receiver inventory and
reconciles Discord and Photon runtimes even when configuration has not
changed.

**Expected behavior**
Reconstruct receiver work at startup. React to committed configuration
changes and local listener retirement. Retry foreign ownership at the
saved lease expiry. Stop discovery when there is no remaining
obligation.

**Steps to reproduce**
Start an instance with no chat endpoints. Let startup finish. Observe
the recurring receiver inventory query from chat maintenance. With a
configured receiver, remove its ownership token while listener shutdown
is delayed and signal a configuration refresh: the old implementation
can replace the listener before shutdown completes.

## What Changed

- Preserve healthy receiver progress after a slow failed batch while
retaining per-receiver retry backoff.

- Register a receiver discovery worker with scoped refreshes, paged
startup inventory, fair batches, and per-receiver or scope failure
backoff.
- Keep owned receiver identities cached without a discovery deadline, so
deletion still stops their listeners.
- Use existing transaction signals for configuration, credentials,
health, access revocation, company deletion, and provider lifecycle
changes. Rename the generic command-only helper to describe its broader
configuration contract.
- Keep lease-key selection with the receiver owner. Shared scheduling
contains no provider protocol.
- Retain stopping ownership until listener shutdown and lease release
complete. Concurrent acquisition joins the existing stop promise.
- Remove receiver discovery from the periodic chat lane. Preserve voice
and the other unmigrated duties.
- Record producer coverage, failure evidence, limits, and remaining work
in `doc/plans/2026-10-25-chat-receiver-discovery-sleep-audit.md`.

## Verification

Published head: `ab39569250f4b699a0ab7a829e66dbe27c15020b`. Discord
#17557 has landed at master `5bf0142d45`. A normal merge reconciles its
squash ancestry by applying only the recorded 27-file receiver patch
from parent `547fdf2139`. Every other path matches that master. Every
server and package production/test file is byte-identical to the
published `6e88ca0201` source that passed the 131-case run, typecheck
and build. Unrelated upstream UI/eval/documentation changes are
preserved. This PR targets master. Fresh exact-head reviews and CI are
required.

- **131 distinct targeted cases pass.** Five complete receiver,
coordinator, batching, startup, and GitHub health error-projection
suites pass 99 cases. Twelve real Discord
automatic-registration/receiver and Slack held-transaction cases pass
separately, with 1,581 other chat integration cases deselected. The
complete Photon channel suite passes 20 cases.
- The standalone receiver and Photon fixtures each reproduced
missing-table failures on separate initially empty PostgreSQL 17
databases. Both now apply pending migrations before client use; their
complete 20-case files pass on those same databases. The large chat
producer suite uses a separate migrated clone.
- The old review concerns already have source fixes: discovery stops
suppress their own completion wake at `1604a9fcba`; slow failed batches
supply `nextRunAtOnError` at `ab56393acc`. Guarded mutations prove the
existing regressions: reenabling the stop wake yields two inventory
reads instead of one, and removing the error deadline fails the 1,100 ms
provider-delay next-wake assertion. Both original source files are
restored byte for byte. Normal full worker and real producer suites pass
with those fixes.
- All 131 distinct targeted cases, production server typecheck and build
pass on source `6e88ca0201`. Exact source comparison carries that
evidence to this normal merge; the unchanged suites were not rerun just
for unrelated upstream changes. Receiver and Photon fixtures
self-migrate separate initially empty databases; the large producer
fixture uses its own migrated clone. Source is unchanged after these
checks. Recorded listener-count warnings and controlled provider failure
logs remain; no assertion was weakened. An initial whole-file identity
check rejected expected parent queue additions; precise patch comparison
confirms those declarations are correctly preserved.
- Old server shard 12 failed because GitHub reports that its self-hosted
runner lost communication. The grouped-test step is cancelled, and the
retained log has no failing assertion or completed summary. The
underlying host/resource/network cause is unproven. That interrupted job
is not a pass; the updated parent and fixture source require a fresh
full CI run.
- [Current acceptance and failure
record](https://github.com/paperclipai/paperclip/blob/ab39569250f4b699a0ab7a829e66dbe27c15020b/doc/plans/2026-10-25-chat-receiver-discovery-sleep-audit.md#compatibility-after-discord-squash-merge-october-27).
Prior 218-case and full-workspace results describe earlier revisions. No
full local repository-suite, multi-writer deployment, Cloud wake, host
suspension, or fleet cost claim is made.

## Risks

- Process-local transaction hints cover the active database owner and
its shared clients. Arbitrary direct SQL or independent configuration
writers need explicit wake integration. Startup/resume reconstruction
and known foreign-lease takeover remain supported; this does not add
general multi-writer discovery.
- Active receiver sockets and lease renewals continue. This change does
not prove host suspension or extend Cloud alarm coverage.
- Configuration signals can arrive during drain, initialization, or
shutdown. The worker preserves dirty scopes and the owner joins listener
retirement before replacement.
- Voice, Teams, milestone projection, publication maintenance, GitHub
recovery, and the remaining stack inventory are separate work.
- The Discord parent has landed and the receiver child now targets
master. Fresh exact-head reviews and all CI must pass before merge.

## Model Used

OpenAI GPT-6 via Codex, with repository inspection, code execution, and
test tools. The runtime does not expose a more specific deployment
identifier or context-window limit.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 07:25:20 -05:00
DottaandPaperclip 5bf0142d45 fix(server): schedule Discord command registration from saved deadlines (#17557)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Chat connections register and verify provider commands in the
background.
> - Discord command recovery ran inside the recurring Gateway runtime
scan.
> - Its existing durable records already store verification and retry
deadlines.
> - This pull request gives command registration its own
shared-coordinator worker and scoped commit notifications.
> - Idle command work stops querying between real deadlines. Existing
command authority and recovery remain intact.

## Linked Issues or Issue Description

Refs #17554 and #17561. Both foundations have merged. This slice targets
master. Runtime discovery and the other chat maintenance duties remain
separate work.

**What happened?**

The chat runtime maintenance loop called Discord command registration on
every reconciliation. It repeatedly read durable command state even when
the next remote verification or retry was minutes away.

**Expected behavior**

Use committed producer changes and saved deadlines. Keep the existing
five-minute verification policy, Retry-After, uncertain-write
quarantine, namespace ownership, and credential fences. Do not add a
database table for the timer.

**Steps to reproduce**

Configure a Discord connection and let command registration settle. In
the parent revision, repeated runtime reconciliation still invokes
command recovery. This revision reconstructs command deadlines at
startup and removes that call from runtime reconciliation.

## What Changed

- Expose normalized deadlines from the existing registration store. Park
indefinite retries and invalid or foreign-owned records. Signal before
store-owned claims, receipts, and retry-result writes.
- Discover eligible endpoints in bounded pages. Refresh only affected
endpoint, connection, or company scopes after commits. Dispatch at most
25 due commands per pass with fair company rotation.
- Wire configuration, credentials, provider lifecycle/failure paths,
inbound activation, generic connection mutation/removal/health, access
revocation, and company deletion.
- Register the worker through the chat service and shared coordinator.
Preserve direct foreground setup calls. Refresh an existing local
Gateway through its current owner after command work.
- Preserve dirty work during drain and concurrent changes, back off
unresolved attempts, and join admitted provider work during shutdown.
- Document producer coverage, retained deadlines, supported writers,
verification failures, and remaining runtime/Cloud obligations in
`doc/idle-discord-command-registration.md` and its dated audit.

## Verification

Published head: `547fdf2139144e1e6484198278bf4bb0eade8794`. It normally
integrates master at `f8563d25077b17681ab6ef5949f7b07415a58ede`,
including landed health #17554 and company deletion #17561. Squash
ancestry caused merge conflicts; resolution applied this slice's exact
26-file owned patch from its recorded parent to pinned master. Every
other path matches master. Migration 0394 and the current lockfile are
preserved.

- **141 distinct targeted cases pass** on reconciled production source:
78 complete command-store, batching, coordinator and startup-timing
cases; 8 real automatic Discord and held-transaction Slack cases; and 55
complete startup/export and company-deletion cases. The 1,581 other chat
integration cases were deselected.
- Server typecheck and build pass. The company-deletion fixture
self-migrates an initially empty isolated database. The two Discord
fixtures use separate migrated clones; this is not a fresh-schema claim
for those fixtures. Signal-listener warnings remain recorded without
assertion failures.
- The parent integration preserves health and command notifications at
shared producer sites. It changes no provider behavior, schema or
coordinator contract. Prior producer, backlog, drain/resume,
malformed-hint, transaction, namespace, shutdown and retry regressions
remain in the complete command suite.
- [Landing compatibility
acceptance](https://github.com/paperclipai/paperclip/blob/547fdf2139144e1e6484198278bf4bb0eade8794/doc/idle-discord-command-registration.md#acceptance-after-the-company-deletion-parent-landed-october-27)
records current scope and the earlier failures. Older full-matrix or
combined-stack runs apply only to their stated revisions.
- Fresh exact-head Greptile, Ponytail if present and all CI are
required. No full local repository suite, live provider, Cloud alarm,
host suspension or savings claim is made.

## Risks

- Discord still has real five-minute verification and failure-retry
obligations. This does not prove host sleep or external alarm coverage.
- Runtime discovery, receipt-to-runtime projection, Gateway lease
renewal and persistent sockets remain separate. The remaining runtime
poll can still read command receipts; it no longer invokes the command
protocol.
- Process-local signals cover integrated writers. Independent SQL
writers and other replicas require an explicit wake contract. Existing
authorization and durable ownership checks remain authoritative.
- Refreshes coalesce with a 30-second minimum spacing. Saved work is
never discarded because a call returned without progress.
- No schema migration, new table, workflow or lockfile change is
introduced by this slice. Landed parent repairs are retained. The
receiver child must receive this integration before landing.

## Model Used

OpenAI Codex, GPT-6 family, with repository tools, code execution, and
reasoning. The exact serving version and context-window size are not
exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 23:32:24 -05:00
DottaandPaperclip 94a780286f fix(server): schedule tool health from committed changes and deadlines (#17554)
## Thinking Path

> - Paperclip manages AI-agent work and its connected tools.
> - Idle hosted instances need their database and network activity to
stop.
> - The maintenance tick queries tool connections even when no health
check is due.
> - Existing connection rows already contain eligibility and the last
health observation.
> - This pull request reconstructs health deadlines and refreshes them
after committed changes.
> - The shared coordinator preserves retries, drain, and shutdown
without another private timer.

## Linked Issues or Issue Description

**What happened?**

The aggregate maintenance tick scans connection health every 30 seconds.
Empty instances and connections with fresh health observations still
cause SQL activity.

**Expected behavior**

No eligible connection means no recurring health SQL. Eligible
connections retain the existing 15-minute proactive check. Configuration
changes and health observations update the schedule after commit.

**Steps to reproduce**

Start a server with heartbeat scheduling enabled and no tool
connections. Let startup finish and observe two maintenance ticks. The
old code repeats the health inventory query. The new startup regression
verifies that those ticks do not invoke the health inventory.

**Paperclip version or commit**

This branch includes merged parent #17518 and master
`96727b3cfefb61f85ffe1fbc29a9b6dd6837efe8`. The 47 changed paths belong
to the single tool-connection health duty. No database file differs from
master.

Related: #14638 covers runtime-auth exclusions. #15448, #15325, and
#11910 concern MCP failure classification. This PR preserves those
provider policies and does not replace their work.

## What Changed

- Keep the GitHub error-projection unit fixture at the health-write
boundary and verify the real transaction path in the PostgreSQL
health-worker suite.

- Add a health schedule owned by tool access. Read lean eligibility
fields and saved observation timestamps.
- Register health work with the existing coordinator. Refresh only dirty
connection/application/company scopes using bounded inventory pages,
check due connections in fair company batches, continue concrete due
backlog after one second, and retain failures with backoff.
- Notify before supported eligibility and observation writes in their
owning transactions. Cover API/gallery setup, OAuth, catalog/gateway
observations, email, voice, access removal, deletion, and settings.
- Commit connection creation with grant, binding, and runtime-slot SQL
before its wake. Keep provider calls outside the new transactions.
- Keep provider-to-transport mapping in the chat catalog. SDK-only chat
changes do not wake health work.
- Replace aggregate health scans, retain the public manual sweep, and
document the producer audit and remaining sleep limits.
- Keep metadata-only example and Smoke Lab installs scoped. Lock and
re-read application type before publishing a real eligibility change.
- Keep failed inventory reads on their own retry deadline while healthy
due batches continue.
- Apply fixture migrations before using external disposable databases in
all six producer suites.

## Verification

Published head: `8c1d293d1ae2b7db753ab20f5a2a2edec1fb0a62`. Fresh CI and
reviews are required for this exact head.

- **623 distinct targeted cases pass.** The final four complete health,
fair-batching, GitHub health recovery, and startup suites pass 80 cases
after the retry fix. Five complete producer suites pass 543 cases: tool
access 469, access 18, email 45, GitHub events four, and Smoke Lab
seven. The earlier 26 health cases are part of this total, not
additional cases.
- The six producer suites first passed against separate, initially empty
PostgreSQL 17 databases at `acbf262843`. They apply their own
migrations. The subsequent repair changes only the health worker and its
regression; its complete final consumer suites pass on that integrated
parent. Server typecheck and build pass with the final repair.
- **Installer amplification:** five real installs with 205 unrelated
connections reproduced 1,035 example rows and 1,045 Smoke Lab rows.
Repeated metadata installs now load only changed fixture connections.
The same cases restore an excluded application through each installer
and require all 205 unrelated IDs to re-enter the schedule.
- **Concurrent eligibility:** a real PostgreSQL lock-wait case requires
the installer to notify after a concurrent type change. A mutation that
retains the lock but uses the old lookup fails the settled-hint
assertion; original source was restored byte for byte.
- **Retry isolation:** the failing baseline read one unavailable company
three times while another company's 60 due checks drained. Final tests
require one initial read, at least 30 seconds between failed reads,
prompt healthy progress, eventual recovery, and SQL quiet after
settlement.
- Real-service producer coverage includes AgentMail activation/pause,
GitHub installation changes, and member access removal. Lifecycle
coverage includes outer commit/rollback, startup reconstruction,
drain/resume, failure, and shutdown.
- Failure history and exact evidence scope: [health
acceptance](https://github.com/paperclipai/paperclip/blob/8c1d293d1ae2b7db753ab20f5a2a2edec1fb0a62/doc/idle-tool-connection-health.md#acceptance-follow-up-after-the-plugin-parent-merged-october-27),
[producer
audit](https://github.com/paperclipai/paperclip/blob/8c1d293d1ae2b7db753ab20f5a2a2edec1fb0a62/doc/plans/2026-10-24-tool-connection-health-sleep-audit.md).
Prior remote failures and earlier 706-case evidence remain historical.
Startup tests emitted listener-count warnings; all assertions passed. No
full local repository-suite, deployed sleep, fleet savings, or live
provider qualification claim is made.

## Risks

- Supported live writers must use the transaction signals. Independent
SQL writers and other replicas need their own wake integration.
- Configured eligible connections still have a real proactive health
obligation. This does not prove Cloud alarm coverage or host/database
suspension.
- Existing manual probes and catalog operations can overlap. This
migration does not introduce a credential-version CAS or change provider
failure policy.
- Voice remains eligible under the previous health policy. Its generic
probe can still report an unsupported transport; changing that behavior
is separate work.
- No database migration, new table, workflow, or lockfile change. This
PR includes its merged parent and current inspected master; later stack
PRs and all current-head acceptance gates remain separate.

## Model Used

OpenAI Codex, GPT-6 family, with repository tools, code execution, and
reasoning. The exact serving version and context-window size are not
exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 21:37:50 -05:00
DottaandPaperclip 13709b4c7a feat(connections): let agents configure connections within delegated authority (#17737)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connections provide governed tools, chat channels, model accounts,
and gateways.
> - Several management routes require a human board actor even when an
agent has the required grant.
> - Default agents must configure these resources within the responsible
user's authority.
> - This pull request adds a shared authorization path to the existing
REST and native API surface.
> - Human authentication, execution approvals, and local host boundaries
remain enforced.
> - The benefit is that a standard agent can complete authorized setup
with a bounded human handoff.

## Linked Issues or Issue Description

**Subsystem affected**

Server authorization, connection services, shared contracts, native API
discovery, database schema.

**Problem or motivation**

Connection administration is available in the web app but often
unavailable to agents. Agent grants, responsible-user authority,
credential ownership, and actor attribution need separate checks.
Opening gateway-token creation also requires preserving the issuing
agent's delegated authority during token use.

**Proposed solution**

Use the existing authorization evaluator for every connection family.
Enforce current responsible-user authority, effective trust, grant
scope, resource visibility, and target-agent access. Keep existing agent
grants unchanged. Expose authorized configuration through default
`search_api` and `call_api`. Save human authentication steps and let
agents continue after completion.

**Roadmap alignment**

This change completes the API access path for the existing Connected
Apps, Personal & Shared AI Accounts, and governed MCP Gateway
capabilities in `ROADMAP.md`. It follows the maintainer's requested
design. Related work: #11899 enforces connection execution access and
creator/manager rules; this PR extends agent management across
connection families. It does not replace that execution-policy work.

## What Changed

- Add shared connection management context and mandatory
responsible-user, trust, scope, and target checks.
- Allow authorized agents to configure tool, chat/email, GitHub/Slack,
AI, profile, and gateway resources through existing routes.
- Preserve human credential ownership and record the actual agent,
responsible user, and run or key in audit data.
- Preserve saved browser authentication handoffs and callback session
checks.
- Bind agent-issued durable gateway tokens to their responsible user and
recheck delegated authority at use.
- Add explicit REST transport and management capability metadata,
built-in guidance, and sensitive-response handling.
- Intersect caller and endpoint-agent Slack test/invitation policies,
including independent and shared rates. Require the addressed human’s
current endpoint identity link before completing identity handoffs.
- Add production-authenticated integration scenarios. Companion #17739
contains the saved setup UI (including the required human
import/rotation step), product and permission documentation,
catalog/Vercel credential and callback ownership, and operation maps to
keep each review below 100 files. Both PRs must ship together; merge
this implementation first, then its companion.

## Verification

- Current implementation head:
`2ecd6451d0d0c8d82121a4e3fa4ce94c5befbbd6`, including master
`ea727dc3c2`, 99 files. The latest follow-up fixes the two valid
findings from the preceding f9 review. Exact-head Greptile has completed
at5/5 with no findings and Superagent passed. Full exact-head Linux CI
workflow40446606056 completed SUCCESS; only the queued external
Paperclip Review remains pending; earlier Linux passes do not qualify
this successor.
- Latest preserved-stack verification passed **2,165 tests** in fresh
PostgreSQL: **70 actual-auth scenarios**, 27 OpenAPI contracts, 2,022
native API tests and 46 saved GitHub wizard cases. **141 existing
gateway/policy acceptance tests** also passed. Workspace
typecheck/build, maps and token gates passed. The first workspace
typecheck was blocked by sandbox tsx IPC permissions; its authorized
rerun passed. This is focused local evidence; the full Linux CI matrix
is still required.
- Issuer/target gateway policy regressions were red before the fix. Both
decisions now intersect, including Block/Ask first/rates, same
credential identity and current token/user/agent authority after
approval. Invocations retain their token and actual requesting agent;
deleted tokens fail closed. Thirteen actual-auth cases cover revocation,
narrowed scope, approvals, shared rates and board compatibility.
Intermediate missing-token attribution, review-context and
implicit-session actor failures remain in the qualification record; all
final cases pass.
- Activity pagination now retains a bounded cursor across private-only
windows. The actual-JWT regression reaches three older readable events
after 27 private ones without exposing private details. A native
device-login regression was red for plaintext receipts; local check and
test-call results now use existing protected-response handling. The
passing actual-auth case proves encrypted persistence, exact replay,
redacted history and no response asset.

- Previous-head `5b55195593` Linux CI initially failed e2e shard 4/8 in
the existing connection-intent continuation test: periodic recovery
queued a repair at 01:21:47, the scripted journey completed the task at
01:21:48, and the extra queued run was cancelled at 01:21:49 because the
task was terminal. The assertion selected that latest cancelled run.
GitHub refused the first attempt while the workflow was nonterminal.
After completion, the single evidence-supported failed-job rerun was
accepted as **attempt 2** on the same head (workflow 40431202466). The
failed shard and final E2E aggregate passed on attempt 2, and the
complete Linux workflow for that head is successful. The original
failure remains part of qualification. No additional unchanged-code
rerun will be used for this failure.

- Companion CI also has an unchanged login-cleanup idleness timeout,
retained in its qualification record. That same 16-case suite passed in
this parent Linux run and a fresh local database. Both preceding
workflows passed after their single failed-job reruns as attempt 2; the
original failures remain recorded. No additional unchanged-code rerun
was used.

- Migration `0380_broken_aqueduct.sql` was regenerated through the
repository workflow after master took 0379 for project Git
authorization. It adds the responsible-user column with `IF NOT EXISTS`,
preserves upstream migrations, and satisfies snapshot retention and
migration safety checks.
- Upstream published Copilot v62 and v63 identities remain byte-for-byte
unchanged. The combined guidance is now v64, digest
`sha256:22e31f95ef972bcead98a4a707c9f33433558fd111e390e027a2bbb4346e112a`.
The normal shared TypeScript/Rust identity check and **61 Copilot
installation tests passed**. The old source-identity assertion first
failed against unchanged published v63; regenerating a new v64 preserves
the published release.
- Workspace `pnpm -r typecheck` and `pnpm build`, map validation, and UI
token gates passed on the final combined stack after the upstream merge.
Node 24.22.1 / pnpm 9.15.4 were used.
- **Earlier 82 API/OpenAPI tests passed** in fresh PostgreSQL 18: 55
assembled-server scenarios and 27 contracts. They use real persistent
agent keys, run JWTs, human sessions, production defaults, and
deterministic provider fixtures. No actor injection establishes access.
- The new email regression was red before per-account scope filtering.
The Arcade regression was red before human ownership and inventory-key
fixes; it also verifies actual-agent audit identity and a human-session
inventory read. The activity regression measured **200 authorization
checks before the fix and one afterward** for the same one-item page.
- **82 GitHub UI tests passed**, including all three new
failed-replacement regressions that were red before their fix. The UI
preserves an earlier copy only after confirming its committed
generation. Changed or unreadable results block copying and reconnecting
until reconciled. Human-only secret responses now include their
nonsecret committed generation.
- Private test status now rechecks the originating principal and linked
task, including mandatory agent/responsible-user privacy. Cross-agent
tests require the full caller tool access decision and the same
credential identity, regardless of auth label; caller and target
policies/approvals and rate limits apply before execution and after
human approval. A profile-only precondition was found to reject valid
allow-policy and scoped-grant access and has been removed. Both
permitted-access cases and a no-auth-label identity regression were red
before the correction; caller-specific Block still prevents provider
execution. The private-status regression was also red before its fix.
- The tool-activity regression measured 100 capability decisions and 102
run captures on a 100-event page before the fix. It now uses two task
decisions and at most two captures while retaining the same 50 visible
events, private-event filtering, and 403 after audit-grant revocation.
The regression was red before request-context reuse and task-decision
sharing; final server typecheck/build also pass.
- Generic chat configure/reconnect now hands agent-supplied verification
credentials to the addressed human before provider work or vault
changes. Actual key/JWT regressions were red for Slack signing-key
replacement and generic channel secret-reference rebinding. They now
prove unchanged refs and vaulted signing value, human setup, permitted
agent bot-token repair, and governed test messages. All 82 API/OpenAPI
cases pass in fresh PostgreSQL. Eight native receipt protections and
final server typecheck/build also pass.
- The preceding review found that old healthy state could retire a
credential-entry card before a human changed anything. The actual-JWT
regression was red. Saved field generations now change only with
protected values and commit with refs plus a verification fence; retries
retain the baseline. Old health, bot-token repair and unchanged entry
stay pending. New signing verification and current authority permit
continuation. A separate red race proved that user revocation during
provider authentication could return 403 after refs changed; authority
is now checked before persistence and inside the credential transaction.
The final 82 API/OpenAPI cases, four neighboring real-database
Slack/GitHub lifecycle cases, and final server typecheck/build pass.
- A preceding full run crossed a rate-window boundary. Database rows
prove one consumed slot at 23:35 and another at 23:36 for the same
policy/bucket. Only Date is frozen in the rate test cases; transport and
asynchronous timers remain real. Production rate behavior is unchanged,
and the final full run passes. An intermediate fixture failure that
overwrote hidden generation metadata with an API projection is retained
in the qualification record.
- Linux CI on an earlier head found two rate-admission assertions that
omitted the newly persisted bucket key. The failures were reproduced
locally; both assertions now verify the exact actor/tool bucket and all
49 policy-service tests pass. The companion qualification record retains
the initial and intermediate failures. Catalog creator attribution is
preserved in the companion to keep this implementation review at 99
files.
- The latest review reproduced three regressions before repair: complete
human replacements failed on unavailable old signing secrets, fresh
GitHub links incorrectly selected reconnect, and different
credential-entry requests shared an idempotency key. Each old protected
ref now has a narrow known-unavailable fallback; unexpected resolver
failures and company/scope violations still abort. Fresh imports keep
their credential form, configured endpoints keep reconnect, and
canonical field sets/completion modes distinguish handoffs while
matching retries retain their baseline. All 55 actual-auth scenarios and
27 separately run OpenAPI contracts pass, as do server typecheck/build.
Companion #17739 also passes all 41 wizard tests including actual
fresh-form submission, UI typecheck, maps and token gates. Earlier red
results and a mistyped OpenAPI filename are retained in qualification.
- The configured GitHub handoff regression was red in the
browser-component tests and actual-auth link/persistence tests. Saved
links now name requested fields and all/any completion mode; the
companion form submits those supplied fields through reconnect and
retains other saved credentials. Webhook/client-secret reconnect remains
human-only; first-setup secret restrictions remain. All 46 wizard tests
pass, including combined modes and legacy links. A duplicate review
referenced the older companion bf760912; the current form is already
fixed, linked in the reply, and its thread is resolved.
- Linux CI on bf760912 failed automatic Slack provisioning because vault
persistence cleared an already verified manifest-update challenge. The
same regression was reproduced locally. The provider-owned helper now
preserves proof only for the current signing fingerprint and callback
URL. Eight existing compatibility cases pass, including this case and
initial GitHub secret rejection. The first uncommitted GitHub-field
variant also failed that initial boundary and was narrowed to reconnect;
both failures remain in qualification.
- The upstream merge conflicted only in generated migration metadata.
Upstream 0379 is preserved, normal generation/pruning produced 0380, and
two repeated applications of the idempotent additive SQL passed. The
final combined stack passed **128 tests** (55 actual-auth, 27 OpenAPI
and 46 wizard cases) in fresh PostgreSQL. Eight Google UI cases also
pass; the two protocol cases could not initialize embedded PostgreSQL in
this fresh local attempt. Their earlier passing evidence remains
historical; fresh Linux CI must execute them. Vercel personal credential
attribution is preserved in companion #17739 with its other
ownership/consent follow-ups, keeping this PR at 99 files.
- The suite covers fresh defaults, restricted users/agents, scopes,
personal isolation, token revocation, human handoffs, callback replay,
execution approvals, authorized self-targeted policy changes,
self-approval denial, and current authority before commit. Reproduce API
checks with `pnpm exec vitest run
server/src/__tests__/connection-management.integration.test.ts
server/src/__tests__/openapi-routes.test.ts`, using a fresh database
through `PAPERCLIP_CONNECTION_MANAGEMENT_TEST_DATABASE_URL` or the
default embedded test database.
- Companion #17739 also records consent separately from token refresh so
saved Google choices survive refresh. Its eight service-picker and two
local-HTTP OAuth tests pass; both new UI cases were red before the fix.
Normal migration generation confirms no SQL change is needed for the
additive JSON metadata.
- The integration module shares one assembled server, authentication
factory, and provider lifecycle to preserve the
HTTP-to-vault-to-task-continuation proof. A reused external database
caused a Slack fixture identity conflict; the fresh final run passed.
Earlier fixture/transport and contract-update failures remain in the
companion qualification record.
- The broad local `pnpm test:run` attempt remains blocked by macOS
embedded PostgreSQL's host semaphore limit. It is not a clean pass. The
fresh Linux CI matrix must complete. Provider fixtures do not prove live
setup or an empirical LLM success rate.
- A current-head completed Paperclip assessment is not yet recorded. Its
earlier external recovery boundary has not been bypassed, and no
incomplete assessment is reported as passing. The user authorized both
merges when checks pass; merge this implementation first, then replay,
retarget, and requalify companion #17739 against the squash-merged
master.

- After the master refresh, local workspace typecheck/build, **97
actual-auth/OpenAPI cases** and **141 gateway/policy cases** pass. The
original fixed database port was occupied; Docker assigned a free
localhost port. The first neighbor setup command could not resolve root
`tsx`, leaving its schema uninitialized; the built database package
migrated the separate fixture and all unchanged cases passed. Both setup
failures are retained in qualification. Fresh Linux CI remains required;
no full local test-sweep pass is claimed.

- The f9 Greptile review scored **2/5** for two reproduced findings:
Slack test sends skipped the caller’s tool policy, and healthy App
credentials completed an unconfirmed identity handoff. Both are fixed in
this head and have resolved evidence threads
([Slack](https://github.com/paperclipai/paperclip/pull/17737#discussion_r4384927765),
[identity](https://github.com/paperclipai/paperclip/pull/17737#discussion_r4384927895)).
Actual key/JWT cases cover twelve Slack caller/target/recipient
combinations; the human-session GitHub OAuth callback alone remains
pending until explicit confirmation. All **99 API/OpenAPI tests** (72
actual-auth + 27 contracts), workspace typecheck and build pass. On the
combined companion, all four focused cases (including the twelve Slack
combinations), typecheck/build and maps also pass. The continuation
suite’s 50 embedded-PG cases were skipped because its database could not
start locally; fresh Linux CI must run them. Initial fixture
credential-collision and audit-projection assertion failures are
retained with the red reproductions in the companion qualification
record. No full local sweep or live consent is claimed.

## Risks

- The maintainer explicitly confirmed authorized policy administration,
including self-targeted changes that loosen controls. These writes
require management grants and the responsible user’s current authority.
Agents cannot approve their own governed action requests or edit their
own principal permission grants. The actual-auth regression exercises
both permitted administration and those denials.
- This is a broad authorization change. Incorrect scope or owner
resolution could deny permitted setup or expose another user's
resources. Integration cases cover both permitted and denied requests
with actual authentication.
- The additive nullable gateway-token column does not infer identities
for legacy clients or backfill agent grants. Legacy agent tokens without
a responsible user fail closed.
- Provider fixtures test supported setup and callback contracts. They do
not prove live provider availability.

## Model Used

- OpenAI Codex, GPT-6 family, with reasoning, repository tools, and code
execution. The runtime does not expose a more specific deployment ID or
context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass — focused suites above;
full local sweep remains blocked as documented
- [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 — exact `2ecd6451d0` Linux CI
completed SUCCESS; external Paperclip Review is still queued
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups —
exact `2ecd6451d0` review completed; both f9 findings have resolved
evidence replies
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 08:20:24 -05:00
DottaandPaperclip f0877a9c7c fix: recover native work and requalify saved computers (#17724)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/32/changes/paperclip/32
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip manages AI agents and preserves their work after an
interruption.
> - Native Stop must confirm termination and save the workspace.
> - Task and run views must show the current recovery receipt.
> - A new external reply can arrive while that cleanup is pending.
> - The reply must return to its original chat owner after cleanup.
> - A successful fresh retry also becomes the task’s bound workspace for
its next ordinary turn.
> - Managed computer updates can invalidate a saved snapshot
qualification.
> - This pull request fixes those instructions, acknowledgements,
handoffs and the existing native-agent Test path.
> - The operator can continue with new input while the stopped turn
remains preserved.

## Linked Issues or Issue Description

**What happened?**

Stopped native runs could keep the initial workspace-repair instruction
after files were recovered. Native Stop could also leave the shared
cancellation state at requested after remote termination was confirmed.
A new GitHub reply saved during cleanup could then remain queued because
cleanup did not ask its original inbound owner to reconsider the
receipt. After a managed snapshot update, an existing native agent could
also need qualification while the generic environment Test required
instance-admin access.

**Expected behavior**

Show the current saved-work state. Acknowledge Stop only after exact
termination proof. Let an authorized operator use the existing
saved-agent Run test to qualify its current computer. After cleanup,
recheck the saved reply's current authority and admit it once as new
input. Preserve the stopped run and uncertain external effects.

**Steps to reproduce**

1. Stop an active native turn before it returns a semantic result.
2. Send a new authorized external reply while cleanup is pending.
3. Let workspace recovery and provider cleanup finish. Inspect the run
instruction, Stop acknowledgement and queued reply.

Related work: #17594 preserves native processes through controller
outages. #17401 addresses a separate bootstrap failure. This pull
request does not replace those fixes.

## What Changed

- Use the exact run's workspace recovery receipt for task and run
guidance, including the Activity ledger.
- Retire an obsolete exact-session notice through the existing bounded
reconciler. Preserve the separate no-replay hold.
- Write the shared native Stop acknowledgement only after the audited
Stop intent and every exact remote lease receipt match.
- Delegate saved external input to the live inbound owner. Recheck its
source, actor, endpoint, principal and conversation generation. Promote
the same receipt in the transaction that creates its new run.
- Use that owner from the cleanup callback and existing stranded-queue
catch-up after a lost callback or restart. A denied source cannot abort
other items.
- Reuse the current private task directory after a successful fresh
retry. Re-read the company/task/workspace binding and validate the
canonical stable or attempt namespace without recreating missing files;
keep a later fresh retry separate.
- Extend the existing agent-scoped qualification owner to native agents.
The clean saved-agent Test qualifies its exact computer before runtime
testing. Reuse a current proof; require a real probe and verified
cleanup for a stale proof. Preserve draft tests and metadata-only
external/pool previews.
- Update execution semantics, capability maps and the recovery
verification recipe. Add a production-page Storybook interaction for the
normal native Test.

## Verification

- **Red:** persisted recovery states returned stale instructions; an
exact terminated native lease left shared Stop requested; the real
GitHub subscribed-message fixture left zero successors after cleanup.
The controlled baseline restored the previous production source,
reproduced the failure, then restored the fixed bytes with matching
SHA-256 hashes.
- **Green:** 382 durable-chat, native-continuation, Stop and recovery
tests pass. The real GitHub/PostgreSQL handoff matrix passes 12/12. It
covers callback, application restart, callback/sweep race, valid input
behind a deleted source, and denial for unknown stop, wrong allocation,
paused endpoint, revoked principal, deleted or changed source, changed
conversation generation and foreign scope. Repeated callbacks preserve
one receipt, its actor, one successor and the unchanged stopped
predecessor.
- **Workspace continuation red/green:** the real PostgreSQL preparation
flow created a fresh attempt and saved a marker, then rejected the next
ordinary turn with the same binding mismatch observed in deployed use.
The repaired preparation and filesystem suites pass 86/86: stable and
attempt-root reuse, saved-marker preservation, a later clean sibling,
changed current bindings, foreign company/task, closed workspace,
traversal, missing path and symlink refusal. No task row reset or
old-turn replay is used.
- **Qualification red/green:** a native saved-agent qualification
returned 422, and its normal Test skipped qualification. The repaired
path passes 224 qualification/immutable-snapshot/environment tests and
176 UI/upgrade tests. It covers revoked authority, foreign or changed
computer, current-proof reuse, failed/missing proof, draft settings,
settings changed during the probe, and external/pool previews. On exact
current source, the real local Harness / Runtime UI also qualified a
newly saved disposable Computer with missing proof through actual
Daytona, then completed the actual OpenCode/OpenRouter hello probe using
`openrouter/deepseek/deepseek-v4.1-flash-1017`. Supported availability
changed from Legacy-only to Paperclip Runner after proof persistence.
Qualification and runtime leases both completed normal release/cleanup.
The five prior task run IDs were unchanged; no task wake was created.
This is macOS source-server/UI with real Linux Daytona and provider
services, not a hosted UI claim. Test probes are archived by the
existing inspection contract; release does not claim physical deletion.
- Full workspace `pnpm -r typecheck`, `pnpm build`, token, map and diff
checks pass at `f6450f4739fc8141815b8b7c35fde22a655c5f90`. The broad
local `pnpm test:run` passed 24,899 tests and reported one existing
nested-clone test timeout at 15 seconds. The complete failing file then
passed 21/21 with the normal timeout; the exact case also passed on the
pinned earlier baseline. The broad runner stopped before its later
groups. No timeout or production workaround was added. Prior head
`f6450f4` has 53 successful checks, two conditional Storybook skips and
Greptile 5/5 with no inline threads. New workspace-reuse head
`fcb13399ec70f92f71bd8250081251dca3f48962` passes workspace typecheck,
full build, 86 scoped tests, maps and diff checks; Current-head CI has
53 successful checks and two conditional Storybook skips; Greptile is
5/5 with no inline findings. Deployed ordinary-turn reuse acceptance
passed as described below.

- **Hosted Stop proof:** the real GitHub issue-mention path used native
OpenCode, `openrouter/deepseek/deepseek-v4.1-flash-1017`, Daytona and an
exact low-trust task boundary. Normal UI Stop interrupted an active Bash
call. Native and shared acknowledgements matched the exact lease.
Automatic recovery saved exactly `STARTED\n` (8 bytes), with no finish
marker. Reload showed Stopped and saved work recovered. Only the
original cancelled run remained. Normal five-minute cleanup completed
its exact provider-destruction transition.
- **Limits:** the provider buffered command output, so the marker was
read after recovery. The approved local provider credential could not
inspect the hosted sandbox; its 404 is not deletion proof. Cleanup
success comes from the exact lease's platform destruction transition. An
earlier hosted stale instruction disappeared after rollout with
unchanged raw run/action data; that historical cause remains
unexplained. Original incident holds and publication receipts were
untouched.
- **Hosted handoff proof:** after QA deployed the combined candidate
containing `46b2e99`, startup admitted the previously saved GitHub
author reply without another comment, Retry or manual action. The new
native run used the exact original wake receipt and saved comment. It
completed once, committed an external-response wait, preserved the
stopped predecessor, emptied the queue and left the task In review. The
answer appeared in the original GitHub conversation. Workspace
finalization and the exact lease's normal destruction transition
succeeded.
- **Hosted workspace proof:** on the combined candidate containing
`fcb13399`, normal Retry preserved the original authenticated GitHub
request and completed a fresh native attempt. One later ordinary
same-head author reply then completed in the exact same workspace ID and
attempt directory, with no Retry/fresh directive. Its input tree digest
matched the Retry's finalized digest; final copyback preserved that
digest. The persisted assessment row and all five prior run records were
unchanged, exactly one new reply run completed, and the task returned to
In review with an empty queue and no live run. Both exact leases
completed normal verified destruction. This used real native OpenCode,
the exact DeepSeek/OpenRouter model and Daytona, without workspace-row
repair or a new remote marker.
- **Publication limit:** the workspace audit compares the persisted
assessment and run history. The ordinary reply exposed a separate
destination-summary fallback that changed the visible GitHub summary
despite the preserved assessment row. The publication track is repairing
that behavior; this proof does not claim the visible summary was
preserved.
- **Deployment boundary:** current-head CI/review and hosted same-source
Retry/ordinary-workspace reuse acceptance passed. The separate
visible-summary publication failure remains owned by the publication
track. Combined hosted UI confirmation of the native-agent Test path is
coordinated separately. Actual missing-proof UI/provider qualification
has passed in the isolated local instance above; prior hosted Stop and
same-input handoff proof remains separate. No merge or deployment is
performed by this pull request.

## Risks

Recovery state and termination receipts must match the exact source run
and allocation. Missing or foreign proof keeps the hold. The chat owner
must retain the original receipt and actor and recheck current
authority. Cleanup cannot grant authority or replay the stopped turn.
Existing native ownership, Stop, budget, permission and uncertain-effect
guards remain in place.

## Model Used

OpenAI GPT-6.1 Sol (`gpt-6.1-sol`) through Codex, with reasoning,
repository tools, source editing and test execution. The context-window
size is not exposed in this session.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#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 (affected suites and
isolated failing file pass; broad timeout retained 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 (current fcb has 53 successful
checks/two conditional Storybook skips)
- [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-26 22:21:58 -05:00
DottaandPaperclip 338bf75761 fix(chat): admit task Retry after GitHub reconnect (#17733)
## Thinking Path

> - Paperclip manages agents and their tasks.
> - Task Retry must preserve saved input and enforce current access.
> - A GitHub reconnect invalidates old runtime callbacks.
> - Retry reused that old callback authority and rejected valid new
intent.
> - Retry also replayed an older failed request when a follow-up was
already saved.
> - This change admits a deliberate Retry under current authority and
transfers saved input once.

## Linked Issues or Issue Description

Refs #16965, #17053 and #17317. These repairs preserve work and contain
old executors. This change fixes the subsequent chat admission boundary.
A search found no overlapping open reconnect/admission fix.

**What happened?**

Ordinary task Retry returned `chat_failed_run_retry_not_authorized`
after the same GitHub App reconnected. The endpoint was healthy, but the
saved request still carried its old runtime generation. A newer queued
follow-up also made Retry reject the older failed request instead of
continuing the follow-up. No successor was admitted.

HTTP qualification found two related defects. Concurrent clicks could
omit the canonical chat action from a response. Signed-in board dispatch
also passed an incomplete task resource to the permission resolver,
which rejected a permitted mutation.

**Expected behavior**

A deliberate Retry checks current authority for the same App, sender,
repository, conversation and task. It continues saved input once. A
later reconnect, changed App, revoked access or changed source prevents
dispatch. Old runtime callbacks remain invalid.

**Steps to reproduce**

1. Admit a GitHub request and record a failed native run.
2. Save a follow-up while execution is blocked.
3. Reconnect the same GitHub App.
4. Click ordinary task Retry.
5. Before this change, admission returns 409. Without reconnect, the
newer input alone also causes 409.

**Paperclip version or commit**

Baseline source: `41c42895fa862c586ff841f8c50200d93ffc83a4`.

**Deployment mode**

Source checkout on macOS. Regressions use real PostgreSQL transactions
and the assembled chat, HTTP route and heartbeat admission services.
Provider boundaries are simulated. No hosted recovery is claimed.

## What Changed

- Record the admitting App identity for new GitHub deliveries.
Historical deliveries can use their original working-comment binding.
Reauthorize deliberate Retry under a pinned current generation and
credential-reference fingerprint.
- Select the complete saved-input queue from the failed run's actual
conversation before replaying the older failed batch. Keep exact-run
Retry bounded while ordinary task Retry supports larger queues. Transfer
its receipts with the dispatch transaction. Recover the same ownership
after restart or a lost response. Release unadmitted input after a
definitive rejection.
- Preserve canonical chat action IDs across concurrent clicks. Supply
current task status and assignment fields to board mutation checks.
- Keep exact-run Retry, stale webhook, containment, source integrity,
publication, pause and budget checks. Update recovery contracts and
verification recipes.

## Verification

- Red: all three new PostgreSQL regressions failed on unchanged
production code. Reconnect failed at chat authorization. Newer input
failed at the obsolete-source guard. The combined case also failed.
- Green: 61 selected chat integration cases passed. These include 27 new
cases and 34 existing cases for containment, retained-source recovery,
exact batches and source revocation.
- A further red/green PostgreSQL regression reproduces the 51-message
overflow identified during review. All 51 messages reach one successor,
including a later Retry of that successor. A separate 52-message
consumed-batch regression also passes.
- A competing conversation retains its own deferred message. Distinct
automatic policy contexts are checked independently; revoking only the
later policy blocks the whole unadmitted batch. Batch validation still
rejects a later message with a changed App binding or deleted source. A
real PostgreSQL query capture reduced the 51-message preparation from
1,103 calls to fewer than 180.
- All 16 durable task Retry tests passed.
- The real HTTP route returns 202 and admits one queued successor for
concurrent deliveries. Fault injection covers rollback during input
handoff, response loss after dispatch commit, and permission loss when
resuming an existing durable wait. A wait only adopts input after
current admission succeeds; a one-shot settlement marker keeps status
projection read-only. A new deliberate Retry works after another
reconnect or a failed successor.
- Current-App, repository, sender, source edit/delete, reassignment,
endpoint pause and board-permission controls passed. Historical
deliveries remain unchanged.
- Final-head CI: 55 checks passed, three expected skips. The unchanged
minute-bucket rate-limit assertion passed locally against PostgreSQL and
on its one CI rerun. Greptile reviewed the final commit at 5/5 with no
unresolved threads.
- Workspace typecheck and full build passed. Map alignment, module
boundaries, UI token gates and `git diff --check` passed.
- Hosted task recovery and a live provider turn remain unverified. The
local tests hold agent capacity to inspect admission without starting a
model or publishing a GitHub response.

## Risks

- A deliberate GitHub Retry can admit old saved input under current
connection authority. It requires the same App binding and current
access. It pins that admission; it does not rewrite the historical
delivery or make stale callbacks valid.
- The durable chat queue has an optional admission callback. It
transfers input only when the transaction contains a valid queued
execution or saved wait. Other chat consumers have no callback and
retain their behavior.
- No migration, Cloud dependency, deployment, configuration change or
workspace cleanup is included.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, source inspection, code
execution and GitHub tools. The exact serving variant and context-window
size are not exposed in this session.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-26 10:26:45 -05:00
DottaandPaperclip 7ae81c9fa7 fix(slack): support rich questions and complete review delivery (#17255)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Questions and review decisions must work in the conversation where a
task started.
> - Slack omitted question context and did not publish several review
kinds.
> - Some answers saved in Paperclip also lost their authorized
continuation or their final Slack reply.
> - A settled card and a successful run did not prove that the user
received the result.
> - This pull request preserves complete questions and follows the
existing answer and delivery receipts through continuation.
> - Users can read the request, submit an authorized decision, and
receive the resumed task's result in the same conversation.

## Linked Issues or Issue Description

Refs #17045 and #17218.

**What happened?**

Slack question cards could omit instructions and editable starting text.
Checkbox reviews, item verdicts, task suggestions, and connection
requests had no publication path. Complex question answers submitted in
Paperclip could fail continuation authorization. Several review
continuations completed without delivering their result to Slack.

**Expected behavior**

Show the actual question and context. Use native Slack controls when
they preserve the form contract. Otherwise provide an explicit Paperclip
review link. Persist one authorized response, resume through the
existing delivery path, settle the card, and deliver the useful result
to its originating conversation.

**Steps to reproduce**

1. Start a task in Slack and ask a text or choice question with
instructions and help text.
2. Submit native text and choice responses, then submit a complex form
through Paperclip.
3. Accept a checklist, submit item decisions, select suggested tasks, or
decline a connection request.
4. Inspect the saved answer, continuation run, original Slack card, and
final Slack reply independently.

## What Changed

- Preserve full prompts, context, descriptions, recommendations, help,
and editable starting text. Use direct buttons for short choices, inline
searchable selects for longer lists, and native checkboxes with explicit
submission for multiple choices.
- Add native custom-answer and validated-text modals, ordinary
confirmation buttons, checklist decisions, per-item verdicts with
reasons, suggested-task creation/dismissal, and connection decline. Keep
governed approvals, permission grants, and forms that cannot be
represented faithfully in the full Paperclip review surface.
- Keep Slack-specific canonical-validation feedback in its owning
platform module. Shared callbacks delegate without interpreting provider
presentation.
- Reuse the existing canonical interaction transactions, callback
receipts, publication queue, and continuation delivery. Share ordinary
confirmation handling across Telegram and Slack. Recheck current
authorization and commit response receipts atomically.
- Settle cards with the saved answer and remove stale controls. Ignore
passive Slack link callbacks so opening a task does not display a false
answer error.
- Validate exact multi-select receipt mappings during native
continuation. Recover automation-origin connection replies from their
published prompt after validating the durable connection receipt.
- Keep oversized multi-select handoffs free of unused native tokens, and
retain the complete Paperclip form for 101–128 choices plus Other. Make
the original-conversation audience explicit before submitting a Slack
modal.
- Add rollback, provider serialization, callback, continuation, and
negative authorization regressions. Update the connector playbook and
feature/access maps. No React or application UI changes are included.
- Add a durable Q01–Q11 qualification index and provider coverage
matrix. Require distinct functional, good-experience, and
best-available-control assessments; real unanswered/answering/settled
evidence; saved results, continuation and navigation proof; and retained
failures. Mark other providers unaudited rather than assuming Slack
parity.

## Verification

Candidate: `e0017d446b1016a38d65382366cd1408cce33039`. The
eleven-core-format live Slack gallery is pinned to
`c3d458b2a06b660448940fd8cf33c5906f0058d5`; subsequent boundary fixes
and the sharing notice have automated verification, not new live
screenshots.

- Real Slack UI testing covered all 11 formats: text, closed choice,
long single select, multiple choices, choices with a custom answer,
pattern-validated text, confirmation, checklist, item verdicts,
suggested tasks, and connection requests. Each has
unanswered/answering/answered screenshots as applicable, an inspected
saved result, one continuation, and an individual experience review in
the local HTML gallery.
- The dedicated private QA app/channel used signed callbacks to the
local candidate. A separately approved password-protected, read-only
preview proved connection-review, suggested-task review, and
created-task navigation. Anonymous access, writes, and credential routes
were denied. No OAuth grant was attempted.
- Real testing exposed and repaired a multi-select continuation failure
and a misleading error on link-button clicks. Failed attempts remain in
the evidence. The final navigation replay opened the exact pending
connection request and declined it in Slack without granting access.
Suggested-task creation produced the selected child with the correct
parent and description.
- Final review-fix verification: **32 form tests**, **28
provider/form-rendering tests**, **30 publication tests**, and **171
native continuation/authorization tests** passed. Earlier **3
atomic-resolution rollback**, **9 targeted
callback/publication/Telegram**, and **28 review-continuation** cases
passed. The final Slack/Teams modal subset also passed. The
automation-origin connection cases, 101/128 custom-choice cases, and
oversized multi-select continuation reproduced before their fixes and
passed afterward; failing logs remain retained. These counts describe
relevant runs, not a reliability percentage.
- CI on `b5885b85fd` exposed a test fixture that assumed every Slack
modal block was an input; the new sharing notice correctly renders a
non-input block. The fixture now selects input blocks safely. The exact
signed-modal correction/one-continuation test passed locally, together
with 14 Slack form/modal tests. The failing CI log and its specific
cause remain recorded.
- `pnpm -r typecheck` and `pnpm build` passed. Server typechecking was
repeated after the final source changes. Map and module-boundary checks
and `git diff --check` passed.
- The full `pnpm test:run` was attempted and stopped after repeated
embedded PostgreSQL semaphore exhaustion on this host. Its 1,395-test
chat suite found two stale native-control assertions; both were
corrected and re-tested in a focused run. Focused database suites used
separate disposable databases on existing local PostgreSQL. The full
suite is not claimed green; new-head CI must complete before merge.
- Final-head CI passed on `e0017d446b1016a38d65382366cd1408cce33039`:
all test/build jobs and required `ci / verify` and `ci / e2e` gates are
green
([run](https://github.com/paperclipai/paperclip/actions/runs/40115430194)).
Greptile and Ponytail both reviewed this exact head at 5/5, the security
scan passed, and all review threads are resolved.
- All three QA app callbacks were restored to staging. Both temporary
tunnels and local proxies were closed. The local endpoint was archived
and its local credential copies removed. The candidate app was stopped.

Limits: provider execution used a deterministic Claude protocol fixture,
not an LLM. This is local real-provider UX proof, not deployed staging
or broader Codie/Claude qualification. The public preview intentionally
blocked ancillary artifact routes, so its destination pages could show a
partial-history warning. The complete permission-grant flow and every
oversized/mixed-form branch were not driven manually. Earlier fixture,
test, and provider failures remain recorded.

## Risks

- New reply routes require durable origin proof. Incorrect receipt
matching could lose a reply or route it incorrectly. Tests cover
missing, forged, mismatched, and revoked authority.
- Governed forms keep their Paperclip resolution checks. This change
does not grant new approval authority to Slack.
- Existing completed review results can become deliverable through the
repaired publication path without another provider run.
- No schema, lockfile, workflow, public task-status model, or
runtime-instruction change is included. This branch is not deployed.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either linked existing issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
Paperclip ticket id
- [x] I have run focused 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 on the new head
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
on the new head
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-24 10:29:15 -07:00
Devin FoleyandPaperclip a2d26a83fe fix(inbox): keep automatic work out of Mine by default
Keep channel and routine attribution out of Mine unless the person participates directly, is assigned the task, or receives a current addressed request. Apply the same source rules to unread state, archives, and task notifications. Preserve direct comments and current human action requests.

Restore the two expressions damaged by redaction during the earlier master merge.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-20 13:46:10 -05:00
DottaandPaperclip 9966f31bee fix(chat): keep permission failures scoped to the rejected operation (#16847)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - External channels deliver agent replies through a durable
publication queue.
> - A provider can reject one operation while other operations remain
allowed.
> - The shared error classifier treated generic 403 and permission
errors as failures of the whole connection.
> - Failure handlers then changed the user's enabled setting and removed
all assigned channel tools.
> - This pull request limits permission failures to the rejected
operation and preserves connection intent during authentication
failures.
> - Unrelated work can continue, while confirmed authentication failures
still stop endpoint traffic.

## Linked Issues or Issue Description

Refs #16137. Follows #16138, which distinguishes local authorization
errors from provider errors. This change also narrows provider
permission failures. Related #16806 handles a separate task-continuation
tool-binding defect.

A provider 403 or missing-scope response currently disables a connection
that may still support other operations. The expected behavior is a
visible operation failure with unrelated work preserved. Confirmed
authentication failures must stop sends without changing the user's
enabled setting.

## What Changed

- Classify generic 403, adapter permission errors, and Slack
missing-scope/no-permission responses as failed operations.
- Preserve rate-limit retries, known destination quarantine, and
confirmed authentication failures.
- Preserve connection status and enabled intent when publication,
provider-reply, or form-open authentication fails. The endpoint still
enters attention and its runtime stops.
- Add GitHub regressions for retained discovery and successful later
publication after 403, and no further sends after 401.
- Mark authentication health failed and fence persistent receiver
startup, background reconciliation, and receiver callbacks. Keep signed
GitHub lifecycle events available during an authentication stop. Verify
Discord reconciliation and Photon restart preserve the stop, while
transient Discord disconnects still recover.
- Update provider, publication, and modal regression expectations and
the execution contract and verification maps.

## Verification

- Red: five new classifier cases returned endpoint attention before the
repair. The signed-installation-removal regression also reproduced a
blocked lifecycle event after a 401 before narrowing the receiver guard.
- Green: all 35 classifier tests pass.
- Green: 19 PostgreSQL-backed cases pass through the production channel
services, including GitHub discovery/publication, Slack provider replies
and question modals, Telegram credential/destination failures, rate
limiting, and Discord/Photon authentication-stop persistence.
- Map structural checks and `git diff --check` pass.
- `pnpm -r typecheck` and `pnpm build` pass. All CI gates are green on
`7e379bcd98aa8363e42efe7f8a4b2589b7111ae6`; Greptile is 5/5 on that
exact commit with no unresolved findings.
- The monolithic local `pnpm test:run` was started, then stopped after
its revision passed the full CI matrix and was superseded by the
authentication-stop repair. Final full-suite verification passed in CI
shards; all 19 final local provider regressions pass.
- The tests run from this source checkout on macOS arm64 with isolated
PostgreSQL and controlled provider failures. They do not prove live
GitHub recovery or deployment. No live connection settings were changed.

## Risks

- Permission failures now leave unrelated work available. The rejected
operation remains failed and is not automatically replayed. Provider
authorization still applies to every request.
- Keeping a connection enabled must not bypass an authentication stop.
GitHub verifies blocked tool discovery and later sends; Discord and
Photon verify background reconciliation and restart cannot clear the
stop. Failed connection health is an execution gate while the endpoint
requires attention.
- Explicit disable, disconnect, signed installation revocation, and
existing destination-specific denial handling remain unchanged. No
migration or API schema change is required.
- Previously disabled connections are not automatically re-enabled
because an upgrade cannot safely infer the user's intent.

## Model Used

- OpenAI Codex, GPT-6 family. The runtime does not expose the exact
deployment model ID or context-window size. Used reasoning, shell tools,
repository edits, and 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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 09:54:22 -05:00
DottaandPaperclip becdc3b08e perf(slack): remove delays before mention acknowledgements (#16491)
Slack mentions now start eyes reactions after the authorized task/comment commits, independently of attachments, subscription and scheduler acceptance. Omit unused optional URL-preview polling while retaining message text, links and files. Keep receipt failures and missing-file warnings independent, including terminal cleanup of older multi-line diagnostics.

Verified with full current-head CI and E2E, Superagent and legacy security checks, Apex 5/5 with no unresolved findings, 19 selected real-PostgreSQL receipt/authorization/cleanup cases, and full frozen-source typecheck/build. The first CI attempt's unchanged Cursor probe timeout is retained in the PR; the one failed-only retry passed under unchanged deadlines. Live Slack latency still requires deployed acceptance.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-15 17:36:50 -05:00
DottaandPaperclip 09a2f0b7b0 refactor(server): isolate provider message admission and runtime policies (#16289)
## Thinking Path

> - Paperclip helps people manage AI agents for work.
> - Chat channels turn external messages into shared task workflows.
> - The main service still contains some provider decisions.
> - These decisions belong with the existing channel modules.
> - This pull request isolates provider message-admission and runtime
policies.
> - Shared authorization, persistence, and runtime ownership keep their
current order.

## Linked Issues or Issue Description

Refs: #16235. Stack part 3/3. Base: `master`. #16276 and #16283 are
merged.

**What existing behavior does this improve?**

Provider ownership and readability in the chat channel service.

**Current behavior**

The entry point combines shared workflows with provider decisions.

**Proposed behavior**

Provider modules own their decisions. Shared modules own product state
and authorization.

**Reason and benefit**

Maintainers can find provider behavior in its channel folder.

**Breaking changes**

None intended. Public service methods and durable data shapes stay
compatible.

## What Changed

- Move Discord SDK admission and its barrier to the Discord message
module.
- Move Photon live-message eviction and startup recovery policy to its
runtime callbacks module.
- Move Slack mention eligibility and Teams setup-channel eligibility to
their message modules.
- Keep Photon deferred ingress and Speko conversation policy with their
provider modules.
- Keep ordered SDK message batching in a shared runtime module with a
live per-message ingress callback.
- Keep receiver leases, cache lifetime, startup failure cleanup,
authorization locks, and transaction ownership shared.
- Reduce `chat-channels.ts` from 3,570 to 3,548 lines.

## Verification

- The same 46 runtime/admission integration cases and all 18 Photon
channel cases passed before and after in the owned Linux container.
- The existing first-channel Teams orphan-admission case passed before
and after moving its eligibility predicate.
- The same 94 SDK adapter and lifecycle-normalization tests passed
locally.
- Server typecheck and module-boundary checks passed.
- Token comparison confirms ordered SDK batching and every processor
argument, plus Photon invalidation and its live runtime lookup.
- The shared factory creates no cache or worker. It reads the ingress
policy for each message and awaits processing in order.
- The extraction rebased without conflicts onto master after #16276 and
#16283 merged. Git range-diff reports the same patch. Final head
`7b63b569e2a0dbcc959310f565f77f367fa64aa0` has the same patch by
range-diff. The 94 SDK/lifecycle tests, server typecheck, and boundary
check passed on the final head. All CI gates pass on that exact head.
Greptile reviewed it at 5/5 with no inline findings or unresolved review
threads.
- One Runner CI test failed its original short timing window. The
unchanged test passed earlier-head CI and local reproduction. The single
failed-job retry passed.
- Cumulative `pnpm -r typecheck` and `pnpm build` passed. All 1,321
channel integration cases passed. The normal UI, CLI, database, adapter,
plugin, and serialized API test selections ran.
- The first Linux `pnpm test:run` returned 1. Original-source runs
reproduced the local failures. Container-only repairs supplied missing
tools, process reaping, and sufficient Node heap. The existing
mocked-fetch CLI telemetry fixture passed with the image opt-out flag
overridden only for that fixture.
- One local venue limitation remains: adapter-utils T24 fails unchanged
on both original and final source in the Linux container. Its entire
56-case suite passes before and after on the host. All other failed or
aborted suites passed in repaired reruns. No test assertion or timeout
changed.
- These fixtures prove application integration. They do not prove live
provider execution.

## Risks

- A captured option value or changed callback order could affect
deferred ingress or stale-runtime handling.
- The ingress callback and runtime getter remain live. Core maps and
receiver lease operations keep one owner.
- No schema migration or public API change is included.

## Model Used

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

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-14 10:50:34 -05:00
DottaandPaperclip 7df55f3dcc refactor(server): isolate provider webhook lifecycle decisions (#16283)
## Thinking Path

> - Paperclip helps people manage AI agents for work.
> - Chat channels turn external messages into shared task workflows.
> - The main service still contains some provider decisions.
> - These decisions belong with the existing channel modules.
> - This pull request moves webhook recovery and payload-scope decisions
to their provider modules.
> - Shared authorization, persistence, and runtime ownership keep their
current order.

## Linked Issues or Issue Description

Refs: #16235. Stack part 2/3. Base: `master`. #16276 is merged.

**What existing behavior does this improve?**

Provider ownership and readability in the chat channel service.

**Current behavior**

The entry point combines shared workflows with provider decisions.

**Proposed behavior**

Provider modules own their decisions. Shared modules own product state
and authorization.

**Reason and benefit**

Maintainers can find provider behavior in its channel folder.

**Breaking changes**

None intended. Public service methods and durable data shapes stay
compatible.

## What Changed

- Move GitHub revoked-installation recovery classification to
`github/webhook-scope.ts`.
- Move Teams payload-scope validation to its message module.
- Record normalized GitHub, Telegram, and Teams lifecycle events through
one shared durable call.
- Keep Slack callback ordering and persistence failures outside parser
catches.
- Reduce `chat-channels.ts` from 3,598 to 3,570 lines.

## Verification

- The same 86 selected webhook/lifecycle integration cases passed before
and after in an owned Linux container.
- The same 17 selected Telegram edit and Teams edit/delete/restore cases
passed before and after in that container.
- The same 94 SDK adapter and lifecycle-normalization tests passed
locally before and after.
- Server typecheck and module-boundary checks passed.
- Token comparison confirms the shared recording payload and runtime
fence, plus the Teams scope and parser inputs.
- The host database baseline failed before assertions because System V
shared-memory IDs were exhausted. No other PostgreSQL server or host
setting was changed. Database verification used an isolated container
under its unprivileged user.
- The extraction rebased without conflicts after #16276 merged. Git
range-diff reports the same patch. The 94 SDK/lifecycle tests and server
typecheck passed on this base. All CI gates pass on rebased head
`d835d7c3815c168226fa646aec6370b6a8ac94c1`. Greptile reviewed that exact
head at 5/5, with no inline findings or unresolved review threads.
- Cumulative `pnpm -r typecheck` and `pnpm build` passed. All 1,321
channel integration cases passed. The normal UI, CLI, database, adapter,
plugin, and serialized API test selections ran.
- The first Linux `pnpm test:run` returned 1. Original-source runs
reproduced the local failures. Container-only repairs supplied missing
tools, process reaping, and sufficient Node heap. The existing
mocked-fetch CLI telemetry fixture passed with the image opt-out flag
overridden only for that fixture.
- One local venue limitation remains: adapter-utils T24 fails unchanged
on both original and final source in the Linux container. Its entire
56-case suite passes before and after on the host. All other failed or
aborted suites passed in repaired reruns. No test assertion or timeout
changed.
- These fixtures exercise application state and the service entry point.
They do not prove live provider execution.

## Risks

- A scope or ordering error could record an event for the wrong provider
context.
- The selected parser returns normalized data. The shared service keeps
durable recording and runtime fencing.
- No database migration or API change is included.

## Model Used

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

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-14 10:38:12 -05:00
DottaandPaperclip f16c0ad5c8 refactor(server): isolate chat conversation and control policies (#16276)
## Thinking Path

> - Paperclip helps people manage AI agents for work.
> - Chat channels turn external messages into shared task workflows.
> - The main service still contains some provider decisions.
> - These decisions belong with the existing channel modules.
> - This pull request separates conversation binding and Telegram
control policy.
> - Shared authorization, persistence, and runtime ownership keep their
current order.

## Linked Issues or Issue Description

Refs: #16235. Stack part 1/3. Base: `master`.

**What existing behavior does this improve?**

Provider ownership and readability in the chat channel service.

**Current behavior**

The entry point combines shared workflows with provider decisions.

**Proposed behavior**

Provider modules own their decisions. Shared modules own product state
and authorization.

**Reason and benefit**

Maintainers can find provider behavior in its channel folder.

**Breaking changes**

None intended. Public service methods and durable data shapes stay
compatible.

## What Changed

- Keep shared conversation lookup and completion in
`inbound/conversation-binding.ts`.
- Move Photon binding-completion policy to its messages module.
- Move Telegram command classification, forum behavior, and chronology
exemptions to its commands module.
- Keep the original conversation generation separate from the retained
task binding.
- Reduce `chat-channels.ts` from 3,649 to 3,598 lines.

## Verification

- The same 62 selected Telegram/Teams integration cases passed before
and after extraction.
- All 18 Photon channel integration cases passed before and after
extraction in separate test processes.
- The initial combined baseline command had a Photon database-startup
hook timeout. No Photon assertion ran in that invocation. The unchanged
Photon suite then passed in isolation with its existing timeouts.
- Server typecheck and the module-boundary check passed.
- A token comparison confirms the moved lookup, completion, and
generation logic, after normalizing the explicit policy callbacks.
- All current-head CI checks passed. Greptile reviewed this exact head
at 5/5 with no findings.
- Cumulative `pnpm -r typecheck` and `pnpm build` passed. All 1,321
channel integration cases passed. The normal UI, CLI, database, adapter,
plugin, and serialized API test selections ran.
- The first Linux `pnpm test:run` returned 1. Original-source runs
reproduced the local failures. Container-only repairs supplied missing
tools, process reaping, and sufficient Node heap. The existing
mocked-fetch CLI telemetry fixture passed with the image opt-out flag
overridden only for that fixture.
- One local venue limitation remains: adapter-utils T24 fails unchanged
on both original and final source in the Linux container. Its entire
56-case suite passes before and after on the host. All other failed or
aborted suites passed in repaired reruns. No test assertion or timeout
changed.
- These fixtures exercise the assembled service and persisted state.
They do not prove live third-party execution.

## Risks

- Changing query order or losing the original generation could bind a
message to the wrong task.
- The workflow retains the original lookup result and all existing query
and write conditions.
- No schema migration or API change is included.

## Model Used

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

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-14 10:21:48 -05:00
DottaandPaperclip f69c6a8a35 fix(github): retry and recover review publication (#16284)
## Thinking Path

> - Paperclip manages agent work and its published results.
> - GitHub review bots publish task-bound assessments through governed
tools.
> - A review can survive a caller timeout because its publication intent
is durable.
> - A transient provider failure still returned a failed receipt before
recovery.
> - Gateway replay could return an empty cached result, and publication
retries had no dedicated scheduler deadline.
> - This pull request adds bounded retries, receipt recovery, and an
independent durable worker.
> - A temporary GitHub failure can recover without another review or
duplicate publication.

## Linked Issues or Issue Description

Refs #16275. That change increased the GitHub tool deadline. This change
repairs retry and recovery behavior.

**What happened?**

A one-off GitHub HTTP 503 or 429 left the caller with a failed
publication receipt. The saved retry did not have its own scheduler
worker. An identical gateway call after a timeout could return an empty
cached result instead of the saved publication receipt.

**Expected behavior**

Temporary failures should retry under current authority. Pending work
should resume at its saved deadline after restart. Exact retries should
return the current receipt. Lost responses must not create duplicate
comments, findings, or checks.

**Steps to reproduce**

1. Admit an advisory PR review request and begin its assessment.
2. Return HTTP 503 or 429 for the first summary-comment PATCH, then let
GitHub succeed.
3. Submit the assessment through the run-scoped tool gateway.
4. On master, the result says publication failed. With this change, the
same call returns the processed receipt and neutral check.
5. For receipt recovery, use a shorter caller deadline and repeat the
exact call after publication finishes.

**Paperclip version or commit**

Reproduced on master at `6cb6ac3b8e40cb90d734ba115a2f22f850ff9477`.

## What Changed

- Classify transient transport, server, and rate-limit failures. Honor
Retry-After and primary reset deadlines. Stop retries for permanent
permission and validation errors.
- Retry safe reads and installation-token issuance within a bounded call
window. Retry publication writes through the existing outbox and
provider receipt checks.
- Wait for up to three publication attempts within a 45-second retry
window. Keep the durable eight-failure cap and enforce saved deadlines
on explicit retries.
- Register an independent GitHub publication worker with
transaction-owned wake notifications, startup recovery, and per-PR lease
deadlines.
- Recover exact comment, progress, and assessment gateway calls from
their stored publication. Require the same company, agent, task, run,
connection, tool, arguments, and current policy. Clear stale timeout
errors after recovery. Approved exact retries read the current receipt
through the existing signed replay path; the worker retains the verified
approval for deferred writes and still rejects revocation.
- Add regression coverage and update the connector guide and
feature/access maps.

## Verification

- Red: both one-off HTTP 503 and 429 regressions failed on master with a
failed publication receipt.
- Green: the same tests passed after the change.
- GitHub review workflows: 133 covered against isolated PostgreSQL 18.
The final combined run passed 132 and hit one fifteen-second timeout
under concurrent build load. All three variants of that workflow passed
in isolation. The earlier combined run passed all 131 workflows before
the two approval regressions were added.
- Retry policy and delivery coordinator tests: 35 passed.
- Additional focused checks passed for the actual eight-failure cap,
exact-argument conflicts, policy revocation, and timeout receipt
recovery. The approved deferred-publication and revocation regressions
failed before the review repair and passed after it, with one approval
request preserved.
- `pnpm -r typecheck`: passed. `pnpm build`: passed. `node
scripts/check-maps.mjs`: passed.
- The broad local `pnpm test:run` path remains blocked by the host's
exhausted PostgreSQL shared-memory slots. The changed database-backed
workflows use an isolated Docker database instead. All Paperclip CI jobs
passed at a6d81b67cb, including the required verify and E2E gates.
Greptile is 5/5 at the same head, with the approval-recovery finding
resolved. The external Superagent Security Scan also passed.
- Live acceptance passed on a dedicated single-repository local test App
and native Paperclip Runner. A test-only preload returned one HTTP 503
before the final summary PATCH. One submit_review call completed in
17.305 seconds; the bot published its 3/5 advisory review and neutral
check, then automatically finished the task. [Published
review](https://github.com/paperclipai/paperclip-permissions-smoke-20260926-pap57-fee7428e/pull/9#issuecomment-6168809007),
[neutral
check](https://github.com/paperclipai/paperclip-permissions-smoke-20260926-pap57-fee7428e/runs/115863564014).
This live test ran at de6862072c; approval-specific recovery is covered
by the later regressions. The preload is excluded from the repository
and removed from the running local instance.

## Risks

Retries make additional bounded provider requests. A provider write with
a lost response is recovered through its existing App-owned identity
before another write is permitted. The worker rechecks authority and the
PR head; revocation and superseded work stop publication. Calls can
still exceed their deadline, and repeated failures eventually exhaust
the retry cap. A pending publication is not a completed task. The agent
still owns task completion after receiving a confirmed receipt. No
schema migration is needed.

## Model Used

OpenAI Codex (GPT-6 family), with code inspection, editing, and test
execution. The exact deployment model ID and context window are not
exposed in this session.

## Checklist

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

> - Paperclip helps people manage AI agents for work.
> - Chat channels turn provider messages into shared task workflows.
> - The main service still implements provider details beside common
authorization and persistence.
> - These details belong in the existing channel folders.
> - This pull request moves Discord runtime command capture and root
receipts, Speko runtime and authority, and GitHub maintenance scheduling
behind explicit typed functions.
> - The service keeps its shared workflow and selects the provider
implementation directly.

## Linked Issues or Issue Description

Refs: #16192. Stack part 5/5. Depends on #16233. Base: `master` (parent
PR merged).

**What existing behavior does this improve?**

The ownership and readability of provider behavior in the chat channel
service.

**Current behavior**

The service implements Discord runtime command capture and root
receipts, Speko runtime and authority, and GitHub maintenance scheduling
inline.

**Proposed behavior**

Channel modules own these details. The core calls their typed functions.
Runtime and database effects retain their current order.

**Reason and benefit**

Maintainers can find channel behavior in its channel folder without
following a generic provider framework.

**Breaking changes**

None intended. Public service entry points and durable data shapes stay
compatible.

## What Changed

- Extract Discord runtime command capture and root receipts, Speko
runtime and authority, and GitHub maintenance scheduling into the
existing channel folders.
- Keep shared company scope, authorization, and transaction ownership in
their current workflow.
- Reduce `chat-channels.ts` from 3715 to 3649 lines.

## Verification

- The same 167 selected chat-runtime cases and 87 voice ownership cases
passed before and after extraction. Full workspace typecheck and build
passed. Token parity checks passed for six moved control-flow blocks.
- Server typecheck passed.
- `node scripts/check-module-boundaries.mjs` passed.
- Full workspace typecheck and build passed on the cumulative stack. All
current-head CI gates passed. Greptile completed at 5/5 with no
findings.
- The full local `pnpm test:run` command exited with three database
fixture-startup hook timeouts. It reported 19,529 passing tests and 250
skipped tests. No assertion failed. Its later test groups did not run
because the driver stops on the first failing group.
- The timed-out files were `environment-custom-images-service.test.ts`,
`generic-mcp-connection.test.ts`, and
`modules/wake-queue/adapters/postgres.test.ts`. All 166 tests in these
files passed in isolation on both baseline `edcfcaf3f6` and stack head
`faaca26d46`, with existing timeouts and assertions. The tests and
database-startup helper are unchanged.
- Provider fixtures prove application integration. They do not prove
live third-party execution.

## Risks

- Incorrect inputs or changed await order could affect provider handling
and recovery.
- Existing integration tests exercise the assembled service before and
after extraction.
- No database migration or API change is included.

## Model Used

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

## Checklist


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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-13 21:39:08 -05:00
DottaandPaperclip c1994056f9 refactor(server): isolate channel registration and setup services (#16233)
## Thinking Path

> - Paperclip helps people manage AI agents for work.
> - Chat channels turn provider messages into shared task workflows.
> - The main service still implements provider details beside common
authorization and persistence.
> - These details belong in the existing channel folders.
> - This pull request moves Slack registration, account linking,
test-message setup, GitHub setup progress, and Telegram webhook URL
restrictions behind explicit typed functions.
> - The service keeps its shared workflow and selects the provider
implementation directly.

## Linked Issues or Issue Description

Refs: #16192. Stack part 4/5. Depends on #16232. Base: `master` (parent
PR merged).

**What existing behavior does this improve?**

The ownership and readability of provider behavior in the chat channel
service.

**Current behavior**

The service implements Slack registration, account linking, test-message
setup, GitHub setup progress, and Telegram webhook URL restrictions
inline.

**Proposed behavior**

Channel modules own these details. The core calls their typed functions.
Runtime and database effects retain their current order.

**Reason and benefit**

Maintainers can find channel behavior in its channel folder without
following a generic provider framework.

**Breaking changes**

None intended. Public service entry points and durable data shapes stay
compatible.

## What Changed

- Extract Slack registration, account linking, test-message setup,
GitHub setup progress, and Telegram webhook URL restrictions into the
existing channel folders.
- Keep shared company scope, authorization, and transaction ownership in
their current workflow.
- Reduce `chat-channels.ts` from 3813 to 3715 lines.

## Verification

- The same 97 selected setup integration cases passed before and after
extraction. The cases cover Slack installer linking and welcome
eligibility, GitHub registration, and Telegram webhook restrictions.
- Server typecheck passed.
- `node scripts/check-module-boundaries.mjs` passed.
- Full workspace typecheck and build passed on the cumulative stack. All
current-head CI gates passed. Greptile completed at 5/5 with no
findings.
- The full local `pnpm test:run` command exited with three database
fixture-startup hook timeouts. It reported 19,529 passing tests and 250
skipped tests. No assertion failed. Its later test groups did not run
because the driver stops on the first failing group.
- The timed-out files were `environment-custom-images-service.test.ts`,
`generic-mcp-connection.test.ts`, and
`modules/wake-queue/adapters/postgres.test.ts`. All 166 tests in these
files passed in isolation on both baseline `edcfcaf3f6` and stack head
`faaca26d46`, with existing timeouts and assertions. The tests and
database-startup helper are unchanged.
- Provider fixtures prove application integration. They do not prove
live third-party execution.

## Risks

- Incorrect inputs or changed await order could affect provider handling
and recovery.
- Existing integration tests exercise the assembled service before and
after extraction.
- No database migration or API change is included.

## Model Used

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

## Checklist


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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-13 21:28:16 -05:00
DottaandPaperclip 875943ac83 refactor(server): isolate provider webhook lifecycle processing (#16232)
## Thinking Path

> - Paperclip helps people manage AI agents for work.
> - Chat channels turn provider messages into shared task workflows.
> - The main service still implements provider details beside common
authorization and persistence.
> - These details belong in the existing channel folders.
> - This pull request moves GitHub webhook runtime deadlines and Slack
lifecycle processing behind explicit typed functions.
> - The service keeps its shared workflow and selects the provider
implementation directly.

## Linked Issues or Issue Description

Refs: #16192. Stack part 3/5. Depends on #16231. Base: `master` (parent
PR merged).

**What existing behavior does this improve?**

The ownership and readability of provider behavior in the chat channel
service.

**Current behavior**

The service implements GitHub webhook runtime deadlines and Slack
lifecycle processing inline.

**Proposed behavior**

Channel modules own these details. The core calls their typed functions.
Runtime and database effects retain their current order.

**Reason and benefit**

Maintainers can find channel behavior in its channel folder without
following a generic provider framework.

**Breaking changes**

None intended. Public service entry points and durable data shapes stay
compatible.

## What Changed

- Extract GitHub webhook runtime deadlines and Slack lifecycle
processing into the existing channel folders.
- Keep shared company scope, authorization, and transaction ownership in
their current workflow.
- Reduce `chat-channels.ts` from 3906 to 3813 lines.

## Verification

- The same 61 selected webhook/lifecycle integration cases passed before
and after extraction. They cover cold GitHub runtime startup, signed
ingress, installation recovery, Slack lifecycle effects, and
Telegram/Teams edits.
- Server typecheck passed.
- `node scripts/check-module-boundaries.mjs` passed.
- Full workspace typecheck and build passed on the cumulative stack. All
current-head CI gates passed. Greptile completed at 5/5 with no
findings.
- The full local `pnpm test:run` command exited with three database
fixture-startup hook timeouts. It reported 19,529 passing tests and 250
skipped tests. No assertion failed. Its later test groups did not run
because the driver stops on the first failing group.
- The timed-out files were `environment-custom-images-service.test.ts`,
`generic-mcp-connection.test.ts`, and
`modules/wake-queue/adapters/postgres.test.ts`. All 166 tests in these
files passed in isolation on both baseline `edcfcaf3f6` and stack head
`faaca26d46`, with existing timeouts and assertions. The tests and
database-startup helper are unchanged.
- Provider fixtures prove application integration. They do not prove
live third-party execution.

## Risks

- Incorrect inputs or changed await order could affect provider handling
and recovery.
- Existing integration tests exercise the assembled service before and
after extraction.
- No database migration or API change is included.

## Model Used

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

## Checklist


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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-13 21:03:46 -05:00
DottaandPaperclip f6608f382f refactor(server): isolate GitHub task preparation and review containment (#16231)
## Thinking Path

> - Paperclip helps people manage AI agents for work.
> - Chat channels turn provider messages into shared task workflows.
> - The main service still implements provider details beside common
authorization and persistence.
> - These details belong in the existing channel folders.
> - This pull request moves GitHub task prompts, review provenance, and
shared guest containment behind explicit typed functions.
> - The service keeps its shared workflow and selects the provider
implementation directly.

## Linked Issues or Issue Description

Refs: #16192. Stack part 2/5. Depends on #16230. Base:
`codex/chat-channel-inbound-policies`.

**What existing behavior does this improve?**

The ownership and readability of provider behavior in the chat channel
service.

**Current behavior**

The service implements GitHub task prompts, review provenance, and
shared guest containment inline.

**Proposed behavior**

Channel modules own these details. The core calls their typed functions.
Runtime and database effects retain their current order.

**Reason and benefit**

Maintainers can find channel behavior in its channel folder without
following a generic provider framework.

**Breaking changes**

None intended. Public service entry points and durable data shapes stay
compatible.

## What Changed

- Extract GitHub task prompts, review provenance, and shared guest
containment into the existing channel folders.
- Keep shared company scope, authorization, and transaction ownership in
their current workflow.
- Reduce `chat-channels.ts` from 3970 to 3906 lines.

## Verification

- The same 130 selected GitHub and low-trust integration cases passed
before and after extraction. Existing transactions still own
containment, authority receipts, and review rows.
- Server typecheck passed.
- `node scripts/check-module-boundaries.mjs` passed.
- Full workspace typecheck and build passed on the cumulative stack. All
current-head CI gates passed. Greptile completed at 5/5 with no
findings.
- The full local `pnpm test:run` command exited with three database
fixture-startup hook timeouts. It reported 19,529 passing tests and 250
skipped tests. No assertion failed. Its later test groups did not run
because the driver stops on the first failing group.
- The timed-out files were `environment-custom-images-service.test.ts`,
`generic-mcp-connection.test.ts`, and
`modules/wake-queue/adapters/postgres.test.ts`. All 166 tests in these
files passed in isolation on both baseline `edcfcaf3f6` and stack head
`faaca26d46`, with existing timeouts and assertions. The tests and
database-startup helper are unchanged.
- Provider fixtures prove application integration. They do not prove
live third-party execution.

## Risks

- Incorrect inputs or changed await order could affect provider handling
and recovery.
- Existing integration tests exercise the assembled service before and
after extraction.
- No database migration or API change is included.

## Model Used

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

## Checklist


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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-13 20:54:18 -05:00
DottaandPaperclip 3e8e1efb84 refactor(server): isolate inbound channel message policies (#16230)
## Thinking Path

> - Paperclip helps people manage AI agents for work.
> - Chat channels turn provider messages into shared task workflows.
> - The main service still implements provider details beside common
authorization and persistence.
> - These details belong in the existing channel folders.
> - This pull request moves inbound message filtering, command
rendering, reply metadata, and setup-reply settlement behind explicit
typed functions.
> - The service keeps its shared workflow and selects the provider
implementation directly.

## Linked Issues or Issue Description

Refs: #16192. Stack part 1/5. Base: `master`.

**What existing behavior does this improve?**

The ownership and readability of provider behavior in the chat channel
service.

**Current behavior**

The service implements inbound message filtering, command rendering,
reply metadata, and setup-reply settlement inline.

**Proposed behavior**

Channel modules own these details. The core calls their typed functions.
Runtime and database effects retain their current order.

**Reason and benefit**

Maintainers can find channel behavior in its channel folder without
following a generic provider framework.

**Breaking changes**

None intended. Public service entry points and durable data shapes stay
compatible.

## What Changed

- Extract inbound message filtering, command rendering, reply metadata,
and setup-reply settlement into the existing channel folders.
- Keep shared company scope, authorization, and transaction ownership in
their current workflow.
- Reduce `chat-channels.ts` from 4082 to 3970 lines.

## Verification

- The same 14 selected chat/Photon integration cases passed before and
after extraction, including Telegram forum controls, guidance retries,
Teams setup replies, and Photon conversation reuse.
- Server typecheck passed.
- `node scripts/check-module-boundaries.mjs` passed.
- Full workspace typecheck and build passed on the cumulative stack. All
current-head CI gates passed. Greptile completed at 5/5 with no
findings.
- The full local `pnpm test:run` command exited with three database
fixture-startup hook timeouts. It reported 19,529 passing tests and 250
skipped tests. No assertion failed. Its later test groups did not run
because the driver stops on the first failing group.
- The timed-out files were `environment-custom-images-service.test.ts`,
`generic-mcp-connection.test.ts`, and
`modules/wake-queue/adapters/postgres.test.ts`. All 166 tests in these
files passed in isolation on both baseline `edcfcaf3f6` and stack head
`faaca26d46`, with existing timeouts and assertions. The tests and
database-startup helper are unchanged.
- Provider fixtures prove application integration. They do not prove
live third-party execution.

## Risks

- Incorrect inputs or changed await order could affect provider handling
and recovery.
- Existing integration tests exercise the assembled service before and
after extraction.
- No database migration or API change is included.

## Model Used

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

## Checklist


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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-13 20:44:29 -05:00
DottaandPaperclip e43af9770a refactor(server): isolate publication recovery and Board sends (#16192)
## Thinking Path

> - Paperclip publishes task messages through several chat providers.
> - Operator recovery must keep durable receipts and task authority
consistent.
> - The service combines shared publication transactions with provider
recovery details.
> - Provider-specific recovery belongs beside its transport
implementation.
> - This pull request extracts publication requests and resolution
workflows.
> - Shared workflows keep transaction ownership and delegate provider
operations.

## Linked Issues or Issue Description

Depends on #16187. Refs #16185, #16183, and #16180. Review against the
parent branch.

**What existing behavior does this improve?**
The structure of publication requests, Board sends, and operator
recovery.

**Current behavior**
Six public publication methods live in the main service and include
provider-specific transfer and receipt operations.

**Proposed behavior**
Move shared requests and resolution to publications modules. Move Teams
file resolution and Board preparation, Slack file receipts and Board
staging, and Photon retry records to their provider folders.

**Reason and benefit**
Provider recovery is easier to locate without moving transaction and
idempotency ownership into providers.

## What Changed

- Extract six public publication methods into two shared workflow
factories (629 and 467 lines).
- Reduce chat-channels.ts from 5,337 to 4,078 lines. The full stack
reduces it from 7,919 lines.
- Extract Teams transfer resolution and cold-runtime Board preparation.
- Extract Slack upload receipt resolution and Board send staging.
- Extract Photon operator retry records.
- Preserve the same public service API and keep provider operations in
the original transactions.

## Verification

- Merge preparation: replayed this stack onto current master after
#16180 landed. Preserve master's new Telegram scheduling methods and
connection-scoped Photon notifications. Server typecheck, callback
syntax audit, and module-boundary check passed. Fresh local integration
and wiring checks passed (1,318 tests). The dedicated Photon suite
passed 18 before and 18 after the conflict resolution. This final slice
was replayed onto merged #16187 with all chat-channel source unchanged.
Current-head CI and review are running. Earlier verification below
describes previous stack commits.

- Publication, attachment, Board send, and operator recovery baseline:
261 passed before and 261 passed after; 1,034 other cases excluded.
- Server typecheck, module-boundary check, and git diff --check passed.
- Syntax audit reconstructs all six public method bodies from the
provider helpers and matches the original AST. Unrelated service
functions and the public API match too.
- Final repository typecheck passed. Build passed. The broad local test
run encountered heartbeat fixture setup failures under the macOS
PostgreSQL shared-memory limit and was interrupted after 868 seconds
(exit 130). Four confirmed abandoned guard slots were reclaimed without
stopping active databases. The complete chat integration suite and
source-wiring checks passed separately (1,309 tests).
- Greptile rates current head 55417debfe 5/5 with zero inline findings.
All 55 CI checks pass on that head. Tests use local PostgreSQL and
fixture transports, not live provider execution.

- Previous stack validation on #16192 (55417debfe): repository typecheck
and build passed; all 1,295 chat integration cases plus 14 source-wiring
checks passed locally (1,309 total). All five PRs have current-head 5/5
reviews and 55 passing CI checks. The broad local pnpm test:run hit
PostgreSQL shared-memory fixture failures and was interrupted after 868
seconds (exit 130); it is not a local full-suite pass.

## Risks

Operator recovery can duplicate a send if receipt updates move out of
their transaction. The extracted helpers use the caller transaction.
Teams preparation remains outside Board locks, and repeated send
identities retain their existing receipt. Public method names and return
values stay the same.

## Model Used

OpenAI GPT-6 via Codex, with code execution and repository tools. The
precise serving variant and context-window size are not exposed in this
session.

## Checklist

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

> - Paperclip accepts chat messages as durable task input.
> - Wakeups must preserve current company, identity, and task
permissions.
> - The main service mixes those shared checks with provider message
rules.
> - Shared wakeup workflows should own persistence and queue ordering.
> - This pull request extracts wakeup authorization, processing, and
notices.
> - Slack and GitHub rules move into their provider folders.

## Linked Issues or Issue Description

Depends on #16185. Refs #16183 and #16180. Review against the parent
branch. Related open #13620 covers durable chat wakeup feature work;
this PR only moves existing behavior.

**What existing behavior does this improve?**
The structure of durable inbound wakeup processing.

**Current behavior**
The service contains authorization, durable wake receipts, queue
notices, and provider authority details.

**Proposed behavior**
Use three cohesive inbound modules and provider-owned authority
functions.

**Reason and benefit**
The shared transaction and company checks stay together while provider
rules have a clear home.

## What Changed

- Move wakeup authorization, processing, and notices into inbound
modules (245, 418, and 377 lines).
- Move Slack mention checks and GitHub automatic-event admission and
acknowledgements into provider folders.
- Preserve lock order, durable receipt ordering, notice cursor lifetime,
and the live heartbeat dependency.
- Reduce chat-channels.ts from 6,340 to 5,337 lines, including blank-gap
cleanup.

## Verification

- Merge preparation: replayed this stack onto current master after
#16180 landed. Preserve master's new Telegram scheduling methods and
connection-scoped Photon notifications. Server typecheck, callback
syntax audit, and module-boundary check passed. Fresh local integration
and wiring checks passed (1,318 tests). The dedicated Photon suite
passed 18 before and 18 after the conflict resolution. This slice was
replayed onto merged #16185 with its chat-channel source unchanged.
Current-head CI and review are running. Earlier verification below
describes previous stack commits.

- Existing wakeup, queue, retry, and authorization integration cases:
212 passed before and 212 passed after; 1,083 other cases excluded.
- Server typecheck, module-boundary check, and git diff --check passed.
- Syntax-tree audit compares all 12 moved functions, cursor state,
retained service functions, and public API after explicit provider
delegations.
- The first three stack PRs have 55 passing CI checks and current-head
5/5 reviews.
- Final stack checks are recorded below. The first broad local run
encountered a PostgreSQL shared-memory fixture limit and was interrupted
after that failure.
- Greptile rates current head 1462819f53 5/5 with zero inline findings.
All 55 CI checks now pass. Initial CI failures: the first workspace job
hit EADDRINUSE in sandbox-callback-bridge.test.ts, and
cloud-auth.spec.ts hit a disposed Playwright response. Both jobs passed
on retry without source changes. Integration uses local PostgreSQL and
fixture provider transports, not live providers.

- Previous stack validation on #16192 (55417debfe): repository typecheck
and build passed; all 1,295 chat integration cases plus 14 source-wiring
checks passed locally (1,309 total). All five PRs have current-head 5/5
reviews and 55 passing CI checks. The broad local pnpm test:run hit
PostgreSQL shared-memory fixture failures and was interrupted after 868
seconds (exit 130); it is not a local full-suite pass.

## Risks

Authorization and wakeups must retain the same locks and transaction
scope. Factories receive narrow dependencies and initialize before their
consumers. The notice cursor stays per service. Shutdown and heartbeat
reads remain live. Provider helpers do not own transactions.

## Model Used

OpenAI GPT-6 via Codex, with code execution and repository tools. The
precise serving variant and context-window size are not exposed in this
session.

## Checklist

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

> - Paperclip accepts provider callbacks as durable task input.
> - Runtime ownership prevents two servers from accepting the same
receiver stream.
> - Discord and Photon share the lease machinery but have different
callback details.
> - Moving that shared machinery into Discord would create the wrong
platform dependency.
> - This pull request extracts common receiver ownership and puts
provider callbacks in their own folders.
> - The service keeps startup and shutdown coordination.

## Linked Issues or Issue Description

Depends on #16183; review against the parent branch. Refs #16180 and
#16080. Related open work: #15532 changes Discord command reconciliation
scheduling. This extraction preserves existing scheduling.

**What existing behavior does this improve?**
The structure of shared receiver ownership and Discord/Photon runtime
callbacks.

**Current behavior**
The shared entry point mixes lease acquisition, renewal, provider
capability checks, and Photon checkpoint transactions.

**Proposed behavior**
Put the common lease operations in runtime/ownership.ts and the protocol
details in the provider folders.

**Reason and benefit**
The ownership lifetime stays explicit without making Photon depend on
Discord implementation code.

## What Changed

- Extract 11 receiver-ownership helpers into runtime/ownership.ts (397
lines). Expose only the operations used by the service.
- Extract Photon ownership checks and checkpoint callbacks (44 lines).
Retain the same runtime context object.
- Extract Discord command and capability reconciliation (112 lines).
- Keep the original service-owned lease map, runtime versions, stop
tasks, and shutdown sequence. Read shutdown and test overrides through
live accessors.
- Reduce chat-channels.ts from 6,880 to 6,340 lines, including removal
of blank gaps left by extractions.

## Verification

- Merge preparation: replayed this stack onto current master after
#16180 landed. Preserve master's new Telegram scheduling methods and
connection-scoped Photon notifications. Server typecheck, callback
syntax audit, and module-boundary check passed. Fresh local integration
and wiring checks passed (1,318 tests). The dedicated Photon suite
passed 18 before and 18 after the conflict resolution. Current head is
6d52aba35f; CI and review are running. Earlier verification below
describes the previous stack commits.

- Existing Discord, Photon, and runtime integration cases: 110 passed
before and 110 passed after; 1,185 other cases excluded.
- Server typecheck, module-boundary check, and git diff --check passed.
- Syntax-tree comparison: 11 ownership helpers, two Photon callback
bodies, Discord reconciliation, unrelated service functions, and the
full public API/shutdown return expression preserve structure.
Intentional binding changes are audited.
- Both preceding PRs have 55 passing CI checks and current-head 5/5
reviews.
- Repository typecheck and build passed earlier in this stack. Final
stack checks are recorded below. The first broad local run hit a macOS
PostgreSQL shared-memory fixture limit and was interrupted after that
failure.
- All 55 CI checks pass on df15f9dd9c. Greptile rates that head 5/5 with
no inline findings. Tests use real local persistence with fixture
runtimes; they do not prove live Discord or Photon execution.

- Previous stack validation on #16192 (55417debfe): repository typecheck
and build passed; all 1,295 chat integration cases plus 14 source-wiring
checks passed locally (1,309 total). All five PRs have current-head 5/5
reviews and 55 passing CI checks. The broad local pnpm test:run hit
PostgreSQL shared-memory fixture failures and was interrupted after 868
seconds (exit 130); it is not a local full-suite pass.

## Risks

Lease loss and partial startup can create overlapping receivers if
cleanup order changes. The service retains the same map objects and
shutdown ordering. The ownership module reads current shutdown state,
and Photon callbacks retain the exact mutable runtime context reference.
No new worker or timer starts during module initialization.

## Model Used

OpenAI GPT-6 via Codex, with code execution and repository tools. The
precise serving variant and context-window size are not exposed in this
session.

## Checklist

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

> - Paperclip connects provider messages to governed agent work.
> - Webhooks must authenticate and persist messages before acknowledging
them.
> - The shared service still contains GitHub and Slack protocol details.
> - The platform-boundary rule places those details in provider folders.
> - This pull request extracts provider webhook handling behind typed
methods.
> - The service retains dispatch, runtime selection, and durable
lifecycle recording.

## Linked Issues or Issue Description

Depends on #16180; review this PR against its parent branch. Refs
#16080. Related open work: #16163 changes GitHub automatic-author
policy. This extraction preserves that policy implementation.

**What existing behavior does this improve?**
The ownership and readability of GitHub and Slack webhook handling.

**Current behavior**
The shared service implements GitHub signatures, replay fences,
automatic event messages, and Slack callback verification.

**Proposed behavior**
Place those details in the respective provider folders and keep the
common dispatcher small.

**Reason and benefit**
Provider code can be reviewed without reading the shared task service.

## What Changed

- Extract GitHub request-local deadline and replay scope (60 lines).
- Extract GitHub authentication and durable-ingress coordination (280
lines).
- Extract GitHub event admission, message construction, and policy-skip
receipts (140 lines).
- Extract Slack workspace validation and authenticated callback
observation (131 lines).
- Keep the same service-owned background task set and GitHub provenance
maps. Forward late-initialized callbacks without reading them during
construction.
- Reduce chat-channels.ts from 7,383 to 6,880 lines: 503 net lines
removed.

## Verification

- Merge preparation: replayed this stack onto current master after
#16180 landed. Preserve master's new Telegram scheduling methods and
connection-scoped Photon notifications. Server typecheck, callback
syntax audit, and module-boundary check passed. Fresh integration, CI,
and current-head review are running. Earlier verification below
describes the previous stack commits.

- Parent baseline: 544 selected GitHub, Slack, and webhook integration
cases passed; 751 other cases excluded.
- Initial extracted run: 543 passed and one idle-queue scan assertion
failed. The idle-queue case passed separately on both the parent and
extracted code. Its publication implementation is unchanged. The full
selected-suite retry passed all 544 cases; the initial failure remains
documented and its cause is not established.
- Server typecheck, module-boundary check, and git diff --check passed.
- Syntax-tree comparison verifies unchanged request-scope logic, durable
ingress, leased authentication, event handling, workspace validation,
and callback recording. All unrelated service functions remain
unchanged.
- Repository typecheck and production build passed for the parent
extraction. Full-stack verification will run at the final handoff. The
first broad local run hit a macOS PostgreSQL shared-memory fixture limit
and was interrupted after that failure.
- All 55 current-head CI checks passed. Greptile: 5/5 on f74ecb5094,
with zero inline findings. No live third-party execution is claimed.

- Previous stack validation on #16192 (55417debfe): repository typecheck
and build passed; all 1,295 chat integration cases plus 14 source-wiring
checks passed locally (1,309 total). All five PRs have current-head 5/5
reviews and 55 passing CI checks. The broad local pnpm test:run hit
PostgreSQL shared-memory fixture failures and was interrupted after 868
seconds (exit 130); it is not a local full-suite pass.

## Risks

Moving callback code can change initialization timing or lose
request-scoped state. The new factories retain live option getters, the
exact runtime context and provenance maps, and typed forwarding for late
initialization. Authentication stays inside the existing credential
lease. The common lifecycle write still completes before returning
provider success.

## Model Used

OpenAI GPT-6 via Codex, with code execution and repository tools. The
precise serving variant and context-window size are not exposed in this
session.

## Checklist

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

> - Paperclip manages AI agents and their work.
> - Chat channels connect provider messages to governed tasks.
> - Slack task recovery still lives in the shared channel service.
> - Its provider sends and recovery state belong in the Slack folder.
> - This pull request moves Slack task-start resolution and
Board-message recovery into two modules.
> - The service keeps the public dispatcher and the existing shared
authorization owners.

## Linked Issues or Issue Description

Refs #16080. Related open work: #15421 changes linked-user task trust;
#15532 changes Discord reconciliation. This extraction changes neither
behavior.

**What existing behavior does this improve?**
The ownership and readability of Slack task-start and Board-message
recovery.

**Current behavior**
The 7,919-line shared service implements Slack retry and cancellation
details.

**Proposed behavior**
Keep those implementations in the Slack folder. Preserve public methods
and all state transitions.

**Reason and benefit**
The channel boundary follows rules/chat-channel-platform-boundaries.mdc
and makes Slack recovery easier to review.

## What Changed

- Move Slack task-start operator resolution into
slack/task-start-resolution.ts (488 lines).
- Move the durable Slack Board-message worker into
slack/board-messages.ts (104 lines).
- Keep initial endpoint/action lookup and provider-effect dispatch in
the service. Pass the original endpoint record to avoid a new read or
race.
- Preserve live reads of heartbeat and deferred-processing options.
- Reduce chat-channels.ts from 7,919 to 7,383 lines: 536 net lines
removed.

## Verification

- Existing Slack integration cases: 282 passed before and 282 passed
after; 1,013 non-Slack cases excluded by the filter.
- pnpm -r typecheck: passed. The first sandboxed attempt could not
create a local tsx IPC socket; the permitted rerun passed.
- pnpm build: passed.
- Module-boundary check and git diff --check: passed.
- Normalized TypeScript AST comparison: moved Board worker and Slack
resolution tail unchanged; all other service function declarations
unchanged.
- All 55 current-head CI checks passed; two optional Storybook checks
skipped. Greptile: 5/5 on 1c1bf5d019, with zero inline findings.
- The broad local pnpm test:run encountered PostgreSQL fixture startup
failure because the macOS shared-memory ID limit was exhausted (the chat
integration file did not execute in that run). The focused 282-case
before/after runs passed. Two verified abandoned, unattached 56-byte
guard segments were reclaimed; no active database was stopped. The broad
run remains unverified and its output is retained.
- Existing public-service integration tests use real local database
fixtures and injected provider transports; no live Slack execution is
claimed.

- Final stack validation on #16192 (55417debfe): repository typecheck
and build passed; all 1,295 chat integration cases plus 14 source-wiring
checks passed locally (1,309 total). All five PRs have current-head 5/5
reviews and 55 passing CI checks. The broad local pnpm test:run hit
PostgreSQL shared-memory fixture failures and was interrupted after 868
seconds (exit 130); it is not a local full-suite pass.

## Risks

Credential lease loss, ambiguous sends, and scheduler failure can cause
duplicate work if ordering changes. The extraction keeps the lease,
transaction, provider-confirmed receipt, and resume marker sequence
intact. No schema, API, dependency, or workflow change.

## Model Used

OpenAI GPT-6 via Codex, with code execution and repository tools. The
precise serving variant and context-window size are not exposed in this
session.

## Checklist

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

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-13 10:50:23 -05:00
Devin FoleyandPaperclip 833769ab55 perf(chat): schedule Telegram maintenance from commits and deadlines (#16094)
Replace periodic Telegram discovery and maintenance scans with bounded startup recovery, connection-specific commit notifications, and durable action deadlines. Preserve ownership, inactive subscription parking, retry and cleanup recovery, and atomic credential binding updates.

Verified full typecheck/build, 30 focused scheduler tests, 12 database-backed recovery cases, all current-head CI checks, and Greptile 5/5 with no unresolved threads.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-13 07:55:27 -07:00
DottaandPaperclip df06df2306 fix(slack): allow direct messages without at-mentions (#16151)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Slack connections let people start and continue agent tasks.
> - The Require at-mention setting currently applies to channels and
direct messages.
> - A person who sends a direct message has already selected the agent.
> - This pull request exempts direct messages from mention checks,
including queued work.
> - People can talk normally in DMs while channel messages keep the
configured mention rule.

## Linked Issues or Issue Description

Refs #15612, which introduced the Require at-mention setting. Searches
found no duplicate PR for the DM exemption.

**What happened?**

With Require at-mention enabled, a plain Slack DM does not start or
continue agent work. New Slack connections enable the setting by
default.

**Expected behavior**

Direct messages do not need an at-mention. Top-level DM replies remain
top-level. Channel messages and channel thread replies still follow the
saved mention setting.

**Steps to reproduce**

1. Enable Allow direct messages and Require at-mention on a Slack
connection.
2. Send a plain DM from an authorized sender.
3. Confirm the agent responds without an at-mention. Send a plain
follow-up and confirm it also works.
4. Confirm unmentioned channel messages remain filtered when Require
at-mention is enabled.
5. Disable Allow direct messages and confirm new DMs remain blocked.

**Paperclip version or commit**

Source baseline: `eb06c9fedd`.

**Deployment mode**

Built from source. Automated tests use disposable local Postgres and
provider fixtures. This change has not been deployed or retested in live
Slack.

## What Changed

- Exempt DMs at inbound admission, task mutation, work authorization,
and heartbeat queue claim.
- Keep channel mention checks and all existing sender, endpoint, and
destination checks.
- Update regressions for new connections, follow-ups, deferred delivery,
and coalesced queued messages.
- Clarify the Slack settings copy, connection documentation, and
verification maps.
- Refresh the affected Storybook review references after source
inspection.

## Verification

- Passed 55 Slack and durable scheduler tests with Vitest on the current
rebased commit, including admission through the extracted inbound
module.
- Passed `pnpm -r typecheck` and `pnpm build` on the rebased PR commit.
- Passed token gates and map checks.
- Passed Storybook catalog validation after rebase: 223 files and 2,210
stories.
- Full local `pnpm test:run` was stopped before completion after three
failures in the unchanged tool-access suite. All 418 tests in that suite
passed in a standalone rerun. The focused regressions passed; full
GitHub CI remains the merge gate.
- Greptile reviewed commit `b0293fa6571403c5e01c30bb7b5fcc5e91b88c97`:
5/5, with no findings or unresolved review threads. All 55 GitHub checks
passed on this commit; two optional Storybook jobs were skipped.
- No live Slack messages were sent during implementation verification.

## Risks

Existing Slack connections now accept authorized plain DMs even when
Require at-mention is enabled. Allow direct messages and sender
authorization still apply. Queued DM work follows the same exemption.
Channel behavior and DM reply routing are unchanged. No schema or
migration change is required.

## Model Used

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

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [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-13 07:40:46 -05:00
DottaandPaperclip eb06c9fedd refactor(server): split chat channel workflows into provider and shared modules (#16080)
Move provider operations into channel folders and shared chat work into named interaction, setup, admission, delivery and publication workflows. Consolidate reviewed PRs #16085, #16089, #16096 and #16105. Preserve upstream execution-default and recovery behavior. The main service is 7,917 lines.

All 55 current-head CI checks pass, with two optional Storybook skips. Greptile is 5/5 with no findings. All 1,294 current chat integration cases, repository-wide typecheck and build pass locally. Broad local tool-route timing/socket failures are recorded in the PR.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-13 07:26:32 -05:00
DottaandPaperclip d837b65be8 refactor(server): move provider setup, inventory and delivery into channel folders (#16058)
Consolidate the ten reviewed provider-folder extractions. Preserve the verified source tree and current master changes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-13 00:26:33 -05:00
DottaandPaperclip e168512f7b perf(chat): stop polling failed run retries (#15871)
Stop one-second scans of failed chat-run retries. Wake the existing retry queue after transaction commits and at saved retry or stale-claim deadlines. Preserve claim fences, authorization, recovery, and idempotent agent admission.

Resolve conflicts with the current chat-service extraction by applying the retry signals and shared deadline predicate in the failed-run retry module.

Verified with pnpm typecheck, pnpm build, all 1,328 chat and coordinator regression tests, and current-head CI. Greptile reviewed the final head at 5/5 with no unresolved threads.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-12 19:49:47 -07:00
DottaandPaperclip f329b24ee1 feat: give tasks durable project-optional workspaces (#15749)
Give tasks durable company-scoped workspace bindings independent of project assignment, channel defaults and authorized repository preparation. Reuse verified input seeds and sparse output recovery while preserving trust, privacy and controller provisioning boundaries.

Full CI and E2E, Superagent, legacy checks and Greptile Apex 5/5 passed on reviewed head 753680b61c. All review findings are resolved; the PR records focused verification and historical acceptance limits.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-12 20:45:18 -05:00
DottaandPaperclip 64bd6e9e07 refactor(chat): extract delivery, reaction, and setup boundaries (#16024)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Chat channels connect that work to provider conversations.
> - One shared service contains callback, delivery, reaction, and setup
logic.
> - These responsibilities have distinct contracts and existing
public-path tests.
> - This PR moves ten cohesive responsibilities into focused modules.
> - The service retains shared runtime ownership and scheduling.
> - Provider behavior is easier to locate and review.

## Linked Issues or Issue Description

Refs #15995, #16026, #16027, #16030, #16031, #16035, #16037, #16038,
#16041, #16043.

This PR consolidates the reviewed extraction stack. The plan is
`doc/plans/2026-10-12-chat-channel-delivery-boundaries-refactor.md`.

## What Changed

- Move Slack callback verification into the Slack folder.
- Move Discord Gateway events and root-thread admission/recovery into
the Discord folder.
- Extract durable receipt reactions and inbound reaction
admission/replay.
- Extract inbound attachment ingestion and outbound integrity-checked
hydration. Preserve the public hydration export.
- Extract durable provider effects. Keep Telegram callback notices in
the Telegram folder.
- Extract conversation/activity reads and setup qualification. Keep
Slack and Teams projections in their channel folders.
- Preserve the merged managed Slack setup behavior, shared workers,
credential leases, and transaction boundaries.
- Reduce `chat-channels.ts` from 26,493 lines / 1,048,769 bytes to
21,460 lines / 862,284 bytes. This removes 5,033 lines from the service.

## Verification

- Each extraction passed its selected existing tests before and after
through public service paths.
- On updated master, all 55 selected Slack cases passed before
extraction. All 194 selected chat/managed-Slack cases passed on the
final stack tip.
- `pnpm -r typecheck`, `pnpm build`, module-boundary checks, and
whitespace checks passed on that tip.
- The normalized syntax audit verifies 69 moved declarations and all
retained statements, including their relative order, against updated
master.
- The eight earlier stack merges retain the exact validated repository
tree. The combined root equals the validated tip merged with current
master. All chat-channel files remain byte-identical to the validated
tip. Current combined-root CI and review are pending.
- Full local verification remains unverified. The unchanged
`workspace-git-snapshot-streaming.test.ts:56` stress test timed out at
300,000 ms in a clean run and again in isolation. The full run was
stopped after the reproduced failure. No timeout or assertion was
weakened.
- These checks use assembled services, real local databases, and
provider fixtures. They do not prove live third-party execution.

Reviewers can run the public-path suites:

```sh
pnpm exec vitest run server/src/__tests__/chat-channels.integration.test.ts server/src/services/chat-outbound-attachment-hydration.test.ts server/src/__tests__/slack-development-manager.test.ts
```

## Risks

- Factory wiring must preserve live values, shared state, and
initialization order. Identity-link construction retains deferred access
to the provider-effects callback.
- Credential fences, authorization transactions, and delivery settlement
must keep their original ordering. Syntax parity and public-path
integration cases cover these boundaries.
- Full local verification has the recorded Git-streaming timeout. The
combined PR must pass master’s required CI before merging into master.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and repository tools. The
exact runtime model ID and context-window size are not exposed in this
session. No separate agent was used.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-12 22:46:25 +00:00
DottaandPaperclip f0e12c8519 Add managed Slack setup with an independent own-app path (#15679)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Slack connects a person to an agent through an installed app and a
verified identity.
> - Independent installations must remain usable without Paperclip Cloud
or manager credentials.
> - Approved Cloud deployments can use Slack manager grants to create
and install each agent's app.
> - Both paths should share credential storage, identity checks,
recovery, and the existing runtime.
> - This pull request adds gated managed setup and keeps independent app
setup under Advanced.
> - It also makes ongoing connection settings and personal test messages
easier to use.

## Linked Issues or Issue Description

**Subsystem affected**

Slack setup, connection settings, tenant credential storage, and the
Cloud connector handoff.

**Problem or motivation**

Approved deployments need an installation flow without pasted
configuration tokens. Open-source users must retain their independent
Slack app flow. A connection manager also needs a simple way to check a
bot from Settings.

**Proposed solution**

Use the managed path when the instance is configured to support it.
Choose agent and Connect are the two visible stops. Continue starts
authorization or installation. Use your own app remains under Advanced
before creation. Save personal manager grants by company, Paperclip
user, Slack user, workspace, and manager app. Reuse only verified
identities for test messages. Unknown identities must complete a private
Slack connection challenge before linking and receiving the test DM.

**Alternatives considered**

A shared bot would change each agent's Slack identity. Requiring Slack
CLI or a hosted service for self-hosted users would remove independent
installation.

**Roadmap alignment**

This maintainer-requested change improves Connected Apps and
experimental Agent Chat. It adds provisioning and management controls to
the existing Slack runtime.

**Additional context**

The companion Cloud broker profile is a separate deployment
prerequisite. Managed setup remains gated. Existing-app adoption is
deferred.

## What Changed

- Extract Slack registration, provider requests, completion,
customer-owned setup, managed setup, and personal manager grants into
focused services. Preserve the compatibility facade and independent
removal cleanup.
- Add company-scoped manager grants and a registration reference through
an additive, idempotent migration after current master. Keep runtime
credentials separate from app-registration secrets.
- Add authenticated manager authorization, sealed handoff, serialized
refresh and revocation, app creation, managed installation, and
installer-bound OAuth fallback.
- Preserve creation intent, block automatic uncertain recreation, save
credentials before downstream checks, and validate app, workspace, bot,
scopes, and installer identity.
- Add the two-stop production wizard and ordered stories. Keep the
own-app, manual, existing-app, and legacy-draft paths.
- Simplify Settings. Open Slack configuration targets the saved app. The
test-message action has its own row. Remove the old manual-avatar
section, channel-message section, and broken permissions link.
- Add paginated account discovery and a private connection challenge for
unknown accounts. Expired invitations stop waiting and offer a new
private invitation. Save send receipts before provider dispatch and
preserve confirmed delivery when activity logging fails.
- Reinstall the saved managed app on explicit reconnect, replace revoked
credentials, and resume completion. Persist reconnect intent and
duplicate-request receipts without creating another app.
- Update provider browser tests, recovery tests, secret redaction, setup
documentation, and the agent prompt. Preserve current master's durable
verification scheduling.

## Verification

- Full workspace typecheck and repository build passed on `56d389d47a`.
The subsequent reconnect retry fix in `288364eada` also passed UI
typecheck and UI build.
- 114 focused Slack registration cases and 13 production managed-wizard
cases passed, including fresh-token reconnect, retry after installation
failure, and duplicate reconnect requests.
- All nine affected Slack browser cases passed against the production UI
and a disposable fixture server. They cover managed setup, automatic
setup, own-app selection, refresh, recovery, mobile behavior, and
connection settings.
- Eight focused real-database test-message cases passed. They cover a
private ownership challenge, saved grant reuse, account pagination,
revoked and conflicting links, workspace mismatch, disabled DMs, revoked
membership, audit failure, ambiguous dispatch, and secret canaries.
- UI token gates and the production Storybook build passed.
- Greptile reviewed exact head
`288364eada5d9c114fad991ff634612639d06672` at 5/5 with no actionable
findings or unresolved review threads.
- The full repository test suite and current-head CI are running. Their
final results will replace this line before merge.
- Earlier live feature previews created two bots in the authorized
Paperclip Slack workspace and reused one personal manager grant. Local
managed Continue created and installed a bot without a configuration
token or a separate Add to Slack action. Avatars, welcome DMs, signed
callbacks, and direct replies were observed. A Settings test DM also
arrived in the signed-in user's Slack account.
- Earlier staging thread qualification required manual publication
recovery for one bot. Current-head live qualification remains required
before enabling the production default. Fixture results do not establish
Slack approval behavior in other workspaces.

## Risks

- Personal manager tokens can create apps. They stay in scoped vault
entries. The manager client secret stays at the broker. Company,
actor/session, origin, and app identity checks apply throughout setup.
- The additive migration must also work on qualification instances that
applied earlier branch migrations. Table, column, index, and constraint
creation is idempotent.
- Creation and message timeouts can leave uncertain outcomes. Saved
request IDs prevent automatic duplicate dispatch.
- Unknown Slack identities must receive and complete their private
challenge while signed in. Account selection alone does not grant
Paperclip permissions. Existing revoked or conflicting links are not
overwritten.
- A development-only manager transport uses an explicitly configured
private credential file for local qualification. Production ignores this
transport; no manager credentials are bundled with open source.
- Managed rollout requires Slack approval, the companion broker
deployment, configured secrets, and final live qualification. Removing a
connection does not delete its Slack app.

## Model Used

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

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-12 15:34:02 -05:00
DottaandPaperclip 0d0e138dad refactor(chat): extract channel status, receipts, drafts and authority workflows (#15995)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Chat channels connect that work to provider conversations.
> - Provider workflows still fill the shared service.
> - Their authority and recovery rules need clear homes.
> - This PR lands five reviewed extractions into channel folders.
> - Shared authorization, state and worker lifetime stay explicit.

## Linked Issues or Issue Description

Refs #15976, #15996, #15999, #16001 and #16002. This root PR now
contains all five extractions from batch three. The four upper PRs were
merged into their parents. The combined tree matches reviewed stack head
`789e918b5af49ec1958076ce4d22d31006205302` exactly.

## What Changed

- Extract Slack session status and accepted-file receipt recovery.
- Extract Telegram publication drafts and Stop handling.
- Extract Photon events and native responses.
- Extract Teams file-transfer authority.
- Reduce `chat-channels.ts` from 29,897 to 26,461 lines (3,436 lines,
11.5%).
- Preserve function bodies, runtime-map identity, leases and transaction
boundaries.

## Verification

- All 117 selected public-service cases passed before and after their
respective extractions.
- All 30 moved declarations and remaining service statements preserve
normalized syntax across the five slices.
- Server typecheck, module boundaries and whitespace checks passed.
- Cumulative `pnpm -r typecheck` and `pnpm build` passed. Combined-head
CI and review are pending on `5de1b0b99d71049a72440e8c131bf4bb30bdf3f3`.
- Fixtures exercise assembled services and disposable databases, not
live third-party providers.
- Cumulative local `pnpm test:run` on
`789e918b5af49ec1958076ce4d22d31006205302` exited 1: 32,414 passed, 125
skipped, one failure. `company-skills-routes.test.ts:1691` (`stars,
forks, and comments on skills through company-scoped endpoints`) failed
with `socket hang up`; that test and its route are unchanged by this
stack. The same 58-case suite then passed in isolation without code
changes. The original command did not reach 111 later serialized suites;
its failure is retained, so the full-local-test checklist remains
unchecked.

```sh
pnpm exec vitest run server/src/__tests__/chat-channels.integration.test.ts -t 'Slack session|Slack turns to Idle|signed Slack session stop|denies guest Slack stops'
```

- Combined-head CI attempt 1: five runners received a shutdown signal at
19:13:08 UTC (server shard 10/12, serialized shards 2/9 and 7/9, E2E
shards 3/8 and 7/8). These jobs stopped during execution without a
failing test assertion. [Original
workflow](https://github.com/paperclipai/paperclip/actions/runs/38293566028).
The affected jobs will receive one unchanged retry after the other jobs
finish.

## Risks

- Changes cross durable provider recovery and authority boundaries. The
moved bodies preserve syntax, and 117 focused public-service cases
passed before and after their extractions.
- Shared workers, timers, runtime maps and generic authorization remain
in the service.
- The full local test run failed in an unchanged company-skills route
test; its result and the unrun suites are recorded above.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and repository tools. The
exact runtime model ID and context-window size are not exposed in this
session. No separate agent was used.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-12 19:26:54 +00:00
DottaandPaperclip a2ac5c2715 refactor(chat): isolate Telegram, Slack, GitHub and Discord workflows (#15976)
## Thinking Path

> - Paperclip manages AI agents and their work.
> - Chat channels connect that work to external conversations.
> - The shared chat service still contains provider-specific workflows.
> - Those workflows are hard to inspect in a 34,000-line file.
> - This stack extracts Telegram, Slack, GitHub and Discord workflows
into their channel folders.
> - Shared authorization and service lifetime remain explicit.

## Linked Issues or Issue Description

Refs #15823, #15834, #15836, #15844 and #15845. Root of the second
behavior-preserving channel-folder refactor stack. The dependent PRs
#15979, #15981, #15985 and #15987 have merged into this branch; this PR
lands all five extractions on master.

## What Changed

- Move Telegram maintenance and subscription repair into
`chat-channels/telegram/maintenance.ts`.
- Move Slack session stopping and task starts into
`chat-channels/slack/session-stop.ts` and `task-start.ts`.
- Move GitHub webhook intake and recovery into
`chat-channels/github/webhook-ingress.ts`.
- Move Discord command registration and handling into
`chat-channels/discord/commands.ts`.
- Share type-only runtime records while preserving shared authorization,
transactions, live lease checks and worker ownership.
- Reduce the original service from 34,603 to 29,897 lines, removing
4,706 lines (13.6%).

## Verification

- All 205 selected integration cases passed before and after their
respective extractions: Telegram 41, Slack session stop 2 multi-step
scenarios, GitHub 84, Slack task start 25 and Discord 53. Each dependent
PR records its focused reproduction command.
- Server typecheck, module boundaries and whitespace checks passed.
- Per-slice syntax comparisons passed for moved declarations and
remaining service statements, allowing only the documented live callback
substitutions.
- Tests exercise the public service with disposable databases and
fixture provider transports. They do not claim live third-party
execution.
- Cumulative workspace typecheck and build passed on the final stack.
- Current-head CI passed on the combined stack commit
`d5b37dbe512e3e199932b6608cdc17639eda555a`; Greptile is 5/5 with no
unresolved threads.
- The [original serialized
shard](https://github.com/paperclipai/paperclip/actions/runs/38266518817/job/114870022249)
timed out in unchanged `adapter-auth-signal-routes.test.ts`. The exact
case passed locally without changes, and the [single job
retry](https://github.com/paperclipai/paperclip/actions/runs/38266518817/job/114874019933)
passed. The original timeout remains recorded.

Reproduce the original Telegram slice’s focused suite:

```sh
pnpm exec vitest run server/src/__tests__/chat-channels.integration.test.ts -t 'Telegram durable private draft Stop|Telegram maintenance|Telegram webhook|Telegram.*(pause|remove)|Telegram.*commands'
```

- Cumulative local `pnpm test:run` exited 1: the first server group had
**18,770 passed, 105 skipped, and one timeout** in unchanged
`server/src/services/workspace-git-snapshot-streaming.test.ts:56`
(300,000 ms on macOS). The fail-fast runner did not reach its later
workspace and serialized groups. An unchanged isolated rerun passed
using the existing timeout; this does not turn the original full run
green. The test and its Git utility code are outside this refactor; all
current-head CI jobs passed.
- Reproduce that diagnostic alone: `pnpm exec vitest run
server/src/services/workspace-git-snapshot-streaming.test.ts`.

## Risks

- Credential lease ownership and provider-confirmation ordering must
remain unchanged. Existing rotation, lease-loss, recovery and durable
Stop cases pass.
- The channel factories create no workers or timers and preserve live
runtime, shutdown and gateway-ownership reads.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and repository tools. The
exact runtime model ID and context-window size are not exposed in this
session. No separate agent was used.

## Checklist

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

> - Paperclip manages agent work and sends results back to chat.
> - A failed chat run can be retried only while its original source
remains authorized.
> - That decision includes persisted source evidence and native runtime
state.
> - Retry claims also share in-flight promises and depend on service
shutdown.
> - This PR groups retry authorization, execution and notices in one
module.
> - The service retains the live admission, runtime and shutdown
boundaries.

## Linked Issues or Issue Description

Refs #15844, #15836, #15834 and #15823. Stack slice 5 of 5, based on
`codex/chat-publication-replacement`.
Merge each predecessor first, then retarget this PR. Do not merge the
stack out of order.

Stack order: #15823 (provider messages) → #15834 (resource
reconciliation) → #15836 (identity links) → #15844 (publication
replacement) → #15845 (failed-run retries). GitHub native stack merging
preserves this order and automatically restacks the remaining branches.

## What Changed

- Extract failed-run retry admission and coordination while keeping the
in-flight map, cursor, error class and authority registrations scoped to
one chat service.
- Move the exact Teams uncertain-file continuation proof into
`microsoft-teams/file-transfer-source.ts`.
- Pass the existing transaction, explicit source identifiers and denial
factory. Return only the proven publication ID.
- Keep committed-result, complete source-batch, ancestor and
other-uncertain-effect checks in shared `failed-run-retry.ts`.
- Keep native execution recovery together; its provider references
describe runner backends, not chat channels.
- The retry coordinator is 1,825 lines and the Teams proof is 149 lines.
Restack on revised #15844 and record the reassessment.

## Verification

- Baseline: 59 retry cases and six negative Teams authority cases
passed. The combined 65 cases passed after the move.
- Cases cover retry ownership, service restart/lifetime, ambiguous Teams
receipts, sibling unknown effects, changed source authority and active
attempts.
- Teams guard, joins, locks, attempt checks and selected ID match after
explicit input substitutions. The shared coordinator retains its state
and cleanup ownership.
- Server typecheck, module-boundary and whitespace checks passed.
- Integration uses disposable databases and fixture provider transports;
no live third-party execution is claimed.

- Fresh Greptile review is 5/5 on
`4f7151409717458717633aa270441a8faf33664e`, with a successful check and
no open review threads.
- Final-stack `pnpm -r typecheck` and `pnpm build` passed at
`57ec5ba94aecd860471f9b14db46f99120c7c790`.
- All CI checks passed on `57ec5ba94aecd860471f9b14db46f99120c7c790`.
- Full local `pnpm test:run` stopped in the general-server group: 18,763
passed, 105 skipped, and one test timed out after 20 seconds in
unchanged `workspace-runtime.test.ts` ("does not accept an occupied
allocated port when listener ownership is unavailable"). The same case
passed in an isolated rerun without code, assertion or timeout changes
(1 passed, 175 excluded). The original timeout is retained as a failed
full run; later workspace and serialized groups were not reached. The
full local gate remains unverified.

- Merge verification on the restacked tree: 118 focused identity,
publication, Photon and retry integration tests passed; server typecheck
and module-boundary checks passed. GitHub’s rebased trees exactly match
the previously reviewed file contents.

- All current-head required checks passed on
`4f7151409717458717633aa270441a8faf33664e`: full CI; Greptile 5/5 with
no unresolved threads.

## Risks

- Authorization must remain fail-closed across committed output and
retry admission. The helper proves only the Teams transfer; the caller
still checks the complete source and result in the same transaction.
- In-flight promises, error-class identity, registration cleanup, cursor
state and the live shutdown getter must remain per-service. Their code
is unchanged by this channel-folder move.
- This PR depends on #15844. Merge and retarget in stack order.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and repository tools. The
exact runtime model ID and context-window size are not exposed in this
session. No separate agent was used.

## Checklist

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

> - Paperclip publishes agent progress and results back to chat.
> - Some updates replace an earlier message while others need a new
message.
> - The current outbound link and task generation determine that
authority.
> - These decisions are spread through the large chat service.
> - This PR groups publication replacement and supersession decisions in
one module.
> - Reviewers can follow those decisions without reading provider
transport code.

## Linked Issues or Issue Description

Refs #15836, #15834 and #15823. Stack slice 4 of 5, based on
`codex/chat-identity-links`.
Merge the predecessor first, then retarget this PR. Do not merge the
stack out of order.

Stack order: #15823 (provider messages) → #15834 (resource
reconciliation) → #15836 (identity links) → #15844 (publication
replacement) → #15845 (failed-run retries). GitHub native stack merging
preserves this order and automatically restacks the remaining branches.

## What Changed

- Extract shared publication replacement and supersession queries from
the large service.
- Keep exact outbound ownership, run/wake scope, consumed progress,
interaction replacement and retained-source authorization together.
- Put the iMessage typing-versus-progress policy in
`imessage-photon/publications.ts`.
- Preserve endpoint lookup timing and all ownership query bodies. The
multi-provider close allowlist remains shared dispatch metadata.
- Restack onto the revised #15836 and record why this boundary remains
mostly shared.

## Verification

- The same 49 existing publication and Photon integration cases passed
before and after the provider-policy move. Other cases were excluded by
the filter.
- Cases cover close-owned progress, ambiguous delivery, interleaved
Slack control, Telegram confirmation, FIFO replacement and Photon
channel behavior.
- Server typecheck, module-boundary and whitespace checks passed. Only
the iMessage predicate/reason moved; ownership queries are unchanged.
- Historical server shard 2 hit a cleanup deadlock; its unchanged
[isolated rerun
passed](https://github.com/paperclipai/paperclip/actions/runs/38134431077/job/114457999409).
[Original
failure](https://github.com/paperclipai/paperclip/actions/runs/38134431077/job/114455332022).
- Tests use disposable databases and fixture provider transports, not
live third-party execution.

- Fresh Greptile review is 5/5 on
`8e2da97b6dc11eb446128b61c789edb529c50d5a`, with a successful check and
no open review threads.
- Final-stack `pnpm -r typecheck` and `pnpm build` passed at
`57ec5ba94aecd860471f9b14db46f99120c7c790`.
- Historical pre-restack CI failed on `ci / General tests (server
(11/12))` and its aggregate `ci / verify`. All 1,255 tests passed, but
worker-exit cleanup in unchanged
`server/src/__tests__/setup-supertest.ts:32` failed with EACCES removing
a temporary `paperclip-vitest-home-*` directory. The [original
job](https://github.com/paperclipai/paperclip/actions/runs/38256549828/job/114836065382)
and the [single unchanged
rerun](https://github.com/paperclipai/paperclip/actions/runs/38256549828/job/114839735273)
failed the same way. No further reruns were requested. After GitHub
automatically restacked the branches, the full cumulative run on #15845
passed this server shard. This middle PR uses the repository’s
policy-only stack CI scope; the top PR runs all suites.
- The final full-local-suite outcome for this cumulative stack is
recorded in #15845; do not infer that gate from the focused tests above.

- Merge verification on the restacked tree: 118 focused identity,
publication, Photon and retry integration tests passed; server typecheck
and module-boundary checks passed. GitHub’s rebased trees exactly match
the previously reviewed file contents.

- All current-head required checks passed on
`8e2da97b6dc11eb446128b61c789edb529c50d5a`: policy CI (middle-stack
scope; full cumulative suites passed on #15845); Greptile 5/5 with no
unresolved threads.

## Risks

- Splitting shared ownership queries per channel would duplicate
authorization rules. They remain in the shared module.
- Preserve the issue-to-run lock order and retained-source callback. The
factory creates no worker or mutable state.
- This PR depends on #15836. Merge and retarget in stack order.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and repository tools. The
exact runtime model ID and context-window size are not exposed in this
session. No separate agent was used.

## Checklist

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

> - Paperclip connects provider identities to company members.
> - A confirmed identity determines whose permissions apply to chat
messages.
> - Token consumption and membership checks must remain atomic.
> - These operations currently share the large chat channel service.
> - This PR moves identity linking into one module with explicit runtime
callbacks.
> - Reviewers can inspect the complete identity-link flow together.

## Linked Issues or Issue Description

Refs #15834 and #15823. Stack slice 3 of 5, based on
`codex/chat-resource-reconciliation`.
Merge the predecessor first, then retarget this PR. Do not merge the
stack out of order.

Stack order: #15823 (provider messages) → #15834 (resource
reconciliation) → #15836 (identity links) → #15844 (publication
replacement) → #15845 (failed-run retries). GitHub native stack merging
preserves this order and automatically restacks the remaining branches.

## What Changed

- Extract company-scoped identity linking into shared
`identity-links.ts`.
- Move Slack connect receipt queries, access requests and
confirmation-notice staging into `slack/identity-links.ts`.
- Move GitHub identity fields into `github/identity-links.ts`.
- Preserve shared token consumption, link locks, membership checks and
revocation.
- Stage the Slack notice inside the original confirmation transaction.
Schedule delivery after commit. Keep runtime and public URL callbacks
live.
- Restack on the revised resource PR #15834 and record the architectural
reassessment in the plan.

## Verification

- Four existing service integration cases passed before and after. The
Slack connect case covers discovery, preview, access requests, duplicate
requests, member confirmation, provider notice, consumed tokens and
endpoint isolation.
- Receipt queries, the access-request transaction and notice payload
match the previous implementation with explicit parameter substitutions.
- Server typecheck, module-boundary and whitespace checks passed.
- These are local database and fixture transport tests, not live Slack
execution.

- Fresh Greptile review is 5/5 on
`7b44962f09fe8043c77ed40e05f761f31c64b33c`, with a successful check and
no open review threads.
- Final-stack `pnpm -r typecheck` and `pnpm build` passed at
`57ec5ba94aecd860471f9b14db46f99120c7c790`.
- All CI checks passed on `62ee045a4728da2d756be3d2e40d13e592a0b5a9`.
- The [original workspace
shard](https://github.com/paperclipai/paperclip/actions/runs/38256203686/job/114834873234)
timed out waiting for the CLI import/export test server health endpoint.
Its [single unchanged rerun
passed](https://github.com/paperclipai/paperclip/actions/runs/38256203686/job/114838954081).
The original timeout remains part of the evidence.
- The final full-local-suite outcome for this cumulative stack is
recorded in #15845; do not infer that gate from the focused tests above.

- Merge verification on the restacked tree: 118 focused identity,
publication, Photon and retry integration tests passed; server typecheck
and module-boundary checks passed. GitHub’s rebased trees exactly match
the previously reviewed file contents.

- All current-head required checks passed on
`7b44962f09fe8043c77ed40e05f761f31c64b33c`: full CI; Greptile 5/5 with
no unresolved threads.

## Risks

- Confirmation must retain transaction and token ownership. The Slack
helper receives the existing transaction and stages the same effect;
scheduling remains after commit in the shared coordinator.
- This PR depends on #15834. Merge predecessors and retarget before
merging this PR.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning and repository tools. The
exact runtime model ID and context-window size are not exposed in this
session. No separate agent was used.

## Checklist

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