mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 10:48:12 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Every master push publishes a canary through release-verify; the staging fleet and the nightly/beta/stable chain start from those canaries > - The server suite grew substantially on 2026-09-10 and now runs under real contention in CI, where three tests assert timing properties that only hold on an idle machine > - Each of the three failed a release-verify canary run that day (runs 34497348802 and 34517515849), and together with the shard timeouts (#13185) they kept any canary from publishing after 18:50 UTC > - This pull request makes the three assertions contention-tolerant without weakening the invariants they prove > - The benefit is a canary lane whose verdicts reflect the code, not the load on the runner ## Linked Issues or Issue Description **What happened?** Three server tests failed release-verify canary runs on 2026-09-10 under CI load: 1. `chat-channels.integration.test.ts › returns a retryable webhook failure when the delivery insert fails before durable receipt` — the duplicate-redelivery request drew the retryable 503 instead of an immediate 200 (run 34517515849). 2. `chat-channels.integration.test.ts › returns ephemeral guidance for exact Slack controls in channels without creating tasks or actions` — a `provider_effect` row was read before its async settlement reached `processed` (run 34497348802). 3. `runner-connection-eval-fixtures.test.ts › resets paired attempts…` — the fixture's `TRUNCATE companies CASCADE` was chosen as a deadlock victim (40P01) against the helper app's own background sweeps (run 34497348802). **Expected behavior** Verify runs fail only for real regressions. A momentary-contention 503 on a duplicate redelivery, an in-flight settlement row, and a deadlock-victim reset are all recoverable states the code handles by design. **Steps to reproduce** Run the three tests under a loaded 3-shard release-verify split; the timing assertions flake. Under `pr-trusted`'s lighter shards they usually pass, which is why the PRs that introduced them were green. **Paperclip version or commit** `master` at `d1ba17eec`. ## What Changed - The duplicate-redelivery assertion retries on 503 the way Slack itself would (bounded, 250 ms apart), then asserts the 200 and the unchanged dedup invariants: duplicate count increments, still exactly one issue. - The channel-controls settlement read is wrapped in a bounded `vi.waitFor`, the same pattern the file's durable-receipt paths already use. - The runner eval fixture retries its TRUNCATE on Postgres error 40P01, bounded at five attempts, and rethrows anything else. ## Verification - All three run green locally: the two chat tests via `-t` filters, the eval fixtures file in full (6 tests). - Each change is assertion-shape only; no product code is touched. - Observation for a follow-up, not this PR: the chat integration file costs ~15 s transform + ~28 s import per vitest worker before any test executes — splitting it would give back real shard time. ## Risks - Low risk: the retries and waits are bounded, so a genuine regression (permanent 503, settlement that never lands, persistent deadlock) still fails within the same timeouts as before. ## Model Used - Claude (Anthropic), model ID `claude-fable-5` (Claude Fable 5), extended thinking, tool use via Claude Code CLI. ## 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