Files
PaperClipAI/server
1bceae0c91 Make import spool cleanup wake on changes and saved deadlines (#17835)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/38/changes/paperclip/38
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip manages agent work and the files that support it.
> - Resumable company imports keep uploaded parts until apply or expiry.
> - An hourly cleanup loop reads the database for every retained upload
directory.
> - Failed and applying imports can retain files without owing periodic
cleanup.
> - Existing transfer rows and file timestamps already identify real
deadlines.
> - This change schedules those deadlines and wakes cleanup after
relevant changes.

## Linked Issues or Issue Description

Refs: #17801.

**What problem does this solve?**

The hourly import sweep keeps querying retained uploads when no cleanup
is due. It also treats a failed database read as a missing transfer row.
That can cause deletion of a live upload whose directory is old.

**What is the proposed solution?**

Use the existing delivery coordinator with per-transfer deadlines. Keep
commit-aware notifications in the transfer ledger service. Keep
filesystem change notifications in the spool owner. Recover pending
cleanup from existing files and rows at startup.

**What alternatives have you considered?**

A slower periodic sweep would still query idle history. A new job table
would duplicate the existing ledger and directory timestamps. Retrying
only after successful uploads would miss partial file writes that leave
cleanup work.

This is slice 59. Parent #17801 has merged. This publication targets
master and preserves that landed prerequisite. Fresh current-head CI and
review remain required.

## What Changed

- Repair an inherited CI concurrency test. Observe exact PostgreSQL
blockers instead of assuming lock order from two 50 ms sleeps. Keep
production authorization and all fail-closed assertions unchanged.

- Refresh verified-upload activity before writing bytes. Preserve the
guarded cleanup claim without recording a part receipt before the file
exists.

- Isolate unreadable child directories so healthy cleanup continues. Use
unique, self-cleaning route fixtures for external database reruns.

- Replace the hourly timer with the existing scoped deadline worker. No
new table or independent scheduler.
- Schedule open uploads at saved activity time plus 24 hours, preserving
the strict cutoff and guarded cancellation before deletion.
- Keep failed and applying imports quiet while retaining their files.
Clean completed/cancelled leftovers immediately.
- Register run-scoped write intent before every supported ledger
mutation, including nested transactions. The helper stays inside the
existing ledger owner.
- Wake from filesystem changes, including failed writes and removals.
Reconstruct orphan deadlines from directory timestamps after restart.
- Propagate database and permission errors. Only a missing directory
proves absence. Read only the four ledger fields needed for cleanup.
- Preserve startup-only stranded-apply recovery. The cleanup worker
cannot fail live applies. Remove its filesystem subscription and join
active cleanup on shutdown.
- Record producer coverage and limits in
`doc/plans/2026-10-26-import-spool-cleanup-sleep.md`.

## Verification

Current repair source: `5d974e5eb28fc3e28b5e75e36fb18c61582348d5`. The
publication adds a test-fixture repair and audit text to the previously
tested import-spool source; runtime code is unchanged. **765 distinct
cases pass across nine complete files:** the original 293 consumer cases
remain hash-identical, and the full tool-access file passes all 472 in
20.86 seconds.

Controlled evidence: a 500 ms cleanup-query delay fails all three old
timing cases; observed lock barriers pass all three with the same delay
and unchanged policy assertions. The artificial delay is not committed.
Current-head CI's original audience-race failure is preserved. The first
local full-file run also retains one separate 15-second stdio HTTP
timeout; one fresh diagnostic full run passes all 472, without
establishing that timeout's cause or changing its limit. Fresh CI and
reviews are required on this new publication head.

Accepted production source: `87549234b125464dc7fa216227fc9bfa1d93f3d7`.
Publication head: `016b3af51a734ad0ddf574de701679a7bdc33d06`. Adopting
the actual parent squash preserves the complete accepted child tree. The
subsequent changes are the CI test fixture and its audit text.

- **293 cases pass across eight complete server files, with zero
skips:** spool worker 18; HTTP import transfers 25; transfer ledger 9;
cloud floor 8; portability 114; startup 92; coordinator 26; scoped
deadlines 1. Runtime: 12.28 seconds.
- Real filesystem and PostgreSQL cases cover zero idle SQL/directory
scans, actual deadlines, first/concurrent writes, nested
commit/rollback, restart, failure, drain/resume, root and symlink
boundaries, and joined shutdown. Three fresh PostgreSQL 17 fixtures and
isolated PAPERCLIP_HOME keep the run separate. All eight source hashes
remain exact; no assertion, timeout, or source adaptation.
- **Static gates pass:** database build; server typecheck/build; module
boundaries; migration order; profile identity. All 412 migration journal
entries are present through index/tag 0413_tired_kronos.
- **Composition:** 1,237 parent-only and eight owned-only paths remain
exact; 11,521 identical paths and two automatic shared production
results are preserved. The only manual conflict is the status ledger.
Packages and other native worker services equal the parent. Its 4,192
selected cases are prior source-scoped evidence, not added to this
count.
- **Historical failures remain recorded:** earlier trusted-runner and
Greptile service errors are not current passes. The older Ponytail Ship
verdict names another head. Fresh CI, security, and exact-head Greptile
5/5 must pass before merge.
- [Master integration and spool acceptance
audit](https://github.com/paperclipai/paperclip/blob/016b3af51a734ad0ddf574de701679a7bdc33d06/doc/plans/2026-10-26-import-spool-cleanup-sleep.md#current-master-integration-and-spool-acceptance-2026-10-29).
No full local repository, live provider, or deployed sleep claim is
made.

<details><summary>Earlier revision verification and failure
history</summary>

Receiver failure fairness: a controlled 1,100 ms batch reproduced a
30-second delay for healthy due receivers. The worker now supplies its
existing per-item deadline through `nextRunAtOnError`. All 20 receiver
lifecycle tests pass on the owner and combined tip
`31c12f1d68ff4a51e06fc2be2abf2c2aee9f9d3a`; server production
typechecking passes on the owner. The failed receiver retains its own
backoff, and settled receivers return to zero recurring SQL. The
five-second assertion budget is unchanged. See [the owning
audit](https://github.com/paperclipai/paperclip/blob/7435a19f6d18f14466175d72b3b7d893ed39acd0/doc/plans/2026-10-25-chat-receiver-discovery-sleep-audit.md#healthy-receiver-progress-after-a-slow-failed-batch).
Current-head CI and review remain required.

Approved delegated Test-tab calls now evaluate caller and target
policies in the existing claim transaction. Real HTTP regressions first
showed a missing caller charge and shared-limit self-rejection. All 78
connection-management cases and 92 gateway cases now pass on the owning
branch, along with server production typechecking. All 78
connection-management cases also pass at combined tip
`d25f830db89c1623bff3547bfc68015c1c66e0cf`. The three new cases cover
shared charges, separate charges, rollback on denial, duplicate
approval, and rejection of a later authorized call. Intermediate
counter/identity fixture failures and a reused-database Slack collision
are recorded in [the owning
audit](https://github.com/paperclipai/paperclip/blob/1509a56a97f2ffb2ab59a9a27f6d7be16ab46569/doc/idle-approved-tool-recovery.md#delegated-test-tab-admission-after-policy-changes).
The earlier combined checks below remain evidence for their stated
revisions. Current-head CI and review remain required.

Inherited voice-cleanup verification: the controlled slow-provider
regression and all 13 lifecycle tests passed on its owner and combined
tip `ab22d8ed0c09028315607414b83b375e5cc0a60a`. That repair changed only
the fixture clock advancement and its audit note.

Current head: `7435a19f6d18f14466175d72b3b7d893ed39acd0`. This remains a
single-duty PR stacked on #17801.

- Integrated pinned master `8548173fc9efdc0fa07644fb92dcc0b6851a95e5`
with normal merges. Every branch passed generated-schema checks and its
target-branch migration-order gate. Existing SQL is unchanged; the 25
stack migrations follow master’s new migration.
- Duty-specific producer coverage, lifecycle tests, and earlier failure
records:
[2026-10-24-recurring-server-sleep-stack.md](https://github.com/paperclipai/paperclip/blob/47ba0a93c4b01484ad58d16bbeb5a372c76b5a0d/doc/plans/2026-10-24-recurring-server-sleep-stack.md),
[2026-10-26-import-spool-cleanup-sleep.md](https://github.com/paperclipai/paperclip/blob/47ba0a93c4b01484ad58d16bbeb5a372c76b5a0d/doc/plans/2026-10-26-import-spool-cleanup-sleep.md).
- Combined tip `51e6cbe67979b55b340ea9f0f434c5b5c682ccd6`: **355
startup/cancellation/recovery/dispatch/preservation tests**, **75
connection-management tests**, and production server typechecking pass.
These combined checks do not mean every intermediate PR independently
ran the full repository suite.
- Real master-to-stack database upgrade passes: **379 unchanged prior
migration receipts plus 25 new migrations**, with the gateway
responsibility fixture preserved.
- Owning-branch checks: 84 runner installation/settlement cases plus
runner typechecking and generated TypeScript/Rust profile agreement; 253
GitHub review workflow cases. Stop-attribution and held-worker readiness
regressions failed before their fixes.
- Failure accounting: the initial combined run passed 349 cases and
failed six idle assertions in a reused preservation database containing
old cancelled runs. Repeating the combined command with a fresh
preservation database passed. Earlier invalid project selection, merge
import/type errors, and the interrupted full local suite are not counted
as passing checks.
- **Latest-head CI and review remain required.** Prior CI findings
include GitHub idle observation, route teardown, attention cleanup,
touch-picker E2E, workspace health, and voice-cleanup timing; local
passes do not erase those failures. No full local repository-suite,
deployed sleep, fleet cost, or live Copilot qualification claim is made.


</details>

## Risks

- Expiry and active apply must keep their guarded ledger claims. A stale
read must never authorize file deletion after a concurrent resume.
- Database and permission failures remain unresolved work. They cannot
be interpreted as missing rows or empty directories.
- Only supported ledger and spool owner writers emit these local
notifications. Independent processes or SQL writers need ingress;
startup recovery alone cannot wake stopped compute.
- Cloud sleep blockers remain. No deployed suspension, external alarm
coverage, live provider qualification, or cost savings is claimed.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, code execution, real
PostgreSQL and filesystem tests, and GitHub tools. 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 URLs)
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Codex <noreply@openai.com>
2026-10-29 07:42:14 -05:00
..