Paperclip Weekly Highlights — July 13–19, 2026: Spend Telemetry Fixes, UI Performance, and CI Shard Balancing
- Commits summarized
- 105
- Period
- Jul 13 - Jul 19, 2026
- Published
- Jul 20, 2026
Paperclip Weekly Highlights — July 13–19, 2026
Repository: paperclipai/paperclip
Period: 2026-07-13 – 2026-07-19
Total Commits: 105
This issue covers highlights from 105 commits in the period. If you run Paperclip adapters, manage a self-hosted instance, or work on the UI, several of the changes below directly affect accuracy, cost, and responsiveness.
Adapters & Execution
ACP-Lane Spend and Usage Now Propagates to Telemetry (#9471)
Paid claude_local and codex_local runs using the default ACP engine could complete with zero recorded cost and missing tokens. This commit:
- Captures ACP usage from runtime status and
usage_updateevents, reporting it asusageBasis: per_run. - Converts agent-reported cumulative ACP cost into a per-turn delta with counter-reset and no-report safeguards.
- Adds a shared billing-identity resolver and maps Claude/Codex authentication modes to control-plane billing types.
- Prefers Claude result-event
modelUsagetotals so subagent and sidechain tokens are included. - Skips the server's session-cumulative usage delta when an adapter explicitly reports per-run usage.
Who should care: Anyone running paid Claude or Codex adapters through the ACP engine will now see accurate token and cost records.
Execution Contract Injected Once Per Fresh Heartbeat (#9469)
Fresh heartbeats were emitting the execution-contract paragraph twice — once from the default heartbeat template and once from the scoped wake payload. This wasted roughly 300 tokens per fresh heartbeat. The fix:
- Stops emitting the execution-contract paragraph from fresh scoped wake payloads (the default template already includes it).
- Keeps the contract in resume deltas and adds
includeExecutionContractfor adapters that don't render the default template. - Opts
openclaw-gatewayinto wake-payload contract rendering. - Suppresses empty comment-batch guidance and metadata when no comments are pending.
Who should care: Any adapter using the default heartbeat template saves ~300 tokens per fresh heartbeat.
Forward onSpawn to Hermes and Process Adapters for PID Persistence (#8722)
The orphan reaper could false-positive reap active runs because hermes-local and process adapters weren't forwarding ctx.onSpawn to runChildProcess(). All other adapters already forwarded this callback — these two were the only ones missing it. This 3-line additive change eliminates false-positive reaps and the associated 5-minute timeout errors.
Who should care: Operators using hermes-local or process adapters who see spurious orphan-reap errors.
Heartbeat & Reliability
Throttle Redundant Issue Re-Wakes After Process Loss (#9470)
After a process died, external wake drivers could re-wake the same agent for the same in_progress issue every few seconds — each producing a full adapter session with no new issue-visible progress. Observed recovery storms consumed 25 sessions and 2.4× the direct-run cost. This commit:
- Adds an issue-scoped admission throttle for consecutive no-progress re-wakes with a 120-second exponential cooldown capped at 30 minutes.
- Gates event-free
enqueueWakeuprequests and returns the explicit skip reasonissue_rewake_throttled. - Always bypasses throttling for comment wakes, new activity, explicit resumes,
forceFreshSession, event-shaped reasons, and post-failure recovery.
Who should care: Anyone who has seen runaway re-wake storms after process recovery. Recovery cost is now bounded without delaying meaningful events.
UI Improvements
Decisions Scrolling Performance (#9468)
Large attention feeds on the Decisions page eagerly mounted every row and re-rendered the full queue on interactions. The fix:
- Renders 50 rows initially and adds 100 more when nearing the scroll boundary.
- Memoizes
AttentionQueueRow, stabilizes parent callbacks, and passes row items through a shared expand callback. - Adds
content-visibility: autoand intrinsic containment so off-screen rows skip layout and paint work.
Who should care: Operators with large attention histories will see a noticeably faster Decisions page.
Mobile Decision Rows Now Readable (#9472)
Decision rows used a fixed two-column layout that squeezed headlines into a truncated sliver on narrow screens. This rework:
- Makes each row respond to its own container width, stacking metadata, content, evidence, and actions on narrow surfaces.
- Preserves the compact desktop layout at wide row widths.
- Wraps decision titles to two lines and promotes actions to full-width mobile tap targets.
Who should care: Anyone using Paperclip on a phone or narrow side panel.
Consolidated Live/Running Blues and Fixed Inbox Row Alignment (#9383)
Three different blues were used to signal "live/running" agent state across the sidebar, task header, and chat thread. Additionally, the unread mark-read dot in the Inbox was pushing row content one column right of read rows. This change:
- Adds a shared
liveBlueBadgerecipe and points all three affordances at it. - Skips the per-row leading spacer when the unread dot is present, so read and unread rows align.
Who should care: Anyone who noticed the visual inconsistency in "live" indicators or misaligned Inbox rows.
Experiments Auto-Recovery Dialog No Longer Locks the UI (#9513)
Enabling the "Task graph liveness auto-recovery" experiment left the Radix overlay and pointer-events: none body lock behind after confirming — dimming the page and blocking all interaction until a refresh. The fix:
- Closes the dialog before firing the mutation in both confirm flows.
- Mounts the dialog conditionally so its overlay fully unmounts.
- Surfaces mutation errors in the page-level error banner instead of a dead UI.
Who should care: Anyone who has toggled the liveness auto-recovery experiment and hit a dead UI.
CI & Build
Runtime Asset Build-Gap Guard
The server package ships runtime asset trees (server/src/built-ins/** and server/src/onboarding-assets/**) that must be copied to dist/ during build. A prior build silently shipped an incomplete dist when the copy step was missing. This commit:
- Extends the existing build-gap gate to verify every non-TypeScript source asset file exists at the matching
distpath. - Adds a
--runtime-assets-onlymode for focused pass/fail verification. - Wires
pnpm run typecheck:build-gapsto prepare plugin SDK deps, build the server, then run the full gate.
Who should care: Contributors and CI — missing runtime assets now fail loudly at build time instead of shipping silently.
Balanced General-Server Test Shards (#9516)
The general-server vitest lane runs maxWorkers=1 across 3 shards. Round-robin assignment by file index produced unbalanced runtimes — with one shard regularly finishing much later than the others, adding minutes to PR CI. This commit records historical suite durations and redistributes tests to balance wall-clock time across shards.
(Full details cut off in available summaries — watch for the PR merge for precise numbers.)
Who should care: Anyone waiting on PR CI for the general-server test lane.
Summary
| Area | Highlight |
|---|---|
| Adapters | ACP spend telemetry now accurate; execution contract dedup saves tokens; orphan-reap fix for hermes/process adapters |
| Heartbeat | Issue re-wake throttle prevents runaway recovery cost |
| UI | Decisions scrolling perf; mobile readability; consistent live badges; Inbox alignment; experiments dialog fix |
| CI/Build | Runtime asset build-gap guard; test shard balancing |
105 commits, 10 highlighted changes — see the full commit log for the complete picture.