Commit Graph
3 Commits
Author SHA1 Message Date
DottaandPaperclip aa58fa1073 perf(ui): restore fast Coordinator task and inbox loading (#18323)
## Thinking Path

> - Paperclip lets people manage work done by agents.
> - Tasks, Inbox, and Needs You must stay usable as work history grows.
> - The Coordinator views bypassed some existing collection
optimizations.
> - Navigation fetched complete decision cards for a count, and Tasks
mounted every loaded row.
> - This PR uses the canonical attention rules for small count and
task-ID responses. It also restores bounded rendering and the optimized
Inbox selection.
> - The benefit is less data and less initial rendering work without a
second definition of pending work.

## Linked Issues or Issue Description

**What happened?**

Coordinator navigation fetched the full attention feed on every cold
collection visit. Tasks rendered the entire loaded collection.
Coordinator could also select the old Inbox loader when Streamlined UI
was off.

**Expected behavior**

Fetch only the projection needed by each surface. Start with a bounded
set of rows. Keep complete task membership, accurate counts, current
permissions, and stable loaded rows.

**Steps to reproduce**

1. Enable Coordinator and open Tasks or Inbox with an empty browser
query cache.
2. Observe a complete attention-card download for the navigation badge.
3. Open a large task list and observe that every loaded row mounts at
once.
4. Disable Streamlined UI while keeping Coordinator enabled, then open
Mine and observe three overlapping compact task reads.

Related work: #17756, #3744, #17983, and #18312.

## What Changed

- Add board-only attention count and complete task-ID projections. Reuse
canonical company, privacy, addressee, deduplication, dismissal, snooze,
and archive rules. Skip card bodies, plan/image reads, and presentation
roster lookup.
- Share the small count read across desktop and mobile navigation. Reuse
the page-owned response on Needs You and Needs attention. Keep the
newest known count through navigation, including zero.
- Use the task-ID index for Needs attention and keep task row hydration
in batches of at most 100.
- Render 100 task rows initially, across the whole expanded tree. Reveal
150 more at a time through scrolling or a button. Keep existing rows
through refresh and append. Defer offscreen leaf layout with shared
tokens.
- Keep Coordinator on the optimized Inbox when Streamlined UI is off.
Use index reads for expanded project recents.
- Add real-database, component, and production-build browser regression
checks. Update the access and feature maps.

## Verification

- All required CI checks pass on
`1c68ac8957490a6c8585ba0939355f536c8120bf`: typecheck, build,
server/workspace tests, serialized database suites, and eight E2E
shards. Greptile is **5/5**, with its row-retention finding fixed and
the review thread resolved. Storybook checks were intentionally skipped;
Paperclip Review completed neutral.
- Workspace typecheck and production build passed locally. The final
rebased source also passed UI typecheck and production build. Token
gates and map checks passed.
- The attention service suite passed all 34 tests on disposable
PostgreSQL. Final targeted checks cover compact projections,
complete-set counts, quality approvals, snoozes, private tasks, and
board/company access. Database response capture confirms compact
projections do not read plans or images. All 31 OpenAPI tests passed
after registering both endpoint contracts.
- Six production-build browser journeys passed: desktop, mobile,
Coordinator Inbox with Streamlined UI off, Needs You, Needs attention,
and an older server page followed by task open/Back. They verify the
initial 100-row budget, scrolling, retained DOM identity/height, one
owner per attention read, complete task membership, 220 retained rows on
Back, and less than 2 px of return-position difference.
- The row-budget and Inbox regressions fail against original source and
pass with this change. The final three affected UI suites passed 40
tests, and the broader Inbox/IssuesList suites passed 101 tests
serially.

### Controlled production-build comparison

Baseline `b31ec0a2dc079e32272a8f618425fe92b68bbaec` versus PR head
`1c68ac8957490a6c8585ba0939355f536c8120bf`. Isolated baseline asset
`index-CS9uPxMx.js`; candidate asset `index-BxJeTQ30.js`. Both UI builds
used the same warm disposable API server and database, with 220 tasks
and 110 pending board approvals. Chromium **151.0.7922.34**, 1440 × 900
viewport, **4× CPU throttle**, loopback with no added network latency,
alternating baseline/candidate order. Cold cases use a new browser
context with network cache disabled; warm cases navigate within the same
context. Other host workloads are uncontrolled.

Readiness requires the destination collection's first visible task row,
then two animation frames. Inbox readiness waits for its canonical Mine
route so previous-page rows cannot satisfy the measurement. Five paired
samples per case; cold Inbox has a second five-pair confirmation wave
because the first result was slower. Times below are **milliseconds**;
parentheses show min–max. Paired savings are the median of individual
before-minus-after pairs, not the difference between medians.

| Journey | Pairs | Baseline median (range) | Candidate median (range) |
Median paired saving | Faster pairs |
| --- | ---: | ---: | ---: | ---: | ---: |
| Cold Tasks | 5 | 2752 (2542–3025) | 2300 (2275–2524) | 328 | 5/5 |
| Cold Inbox | 10 | 2536 (2283–2927) | 2582 (2117–2856) | 37 | 5/10 |
| Warm Tasks navigation | 5 | 2054 (1826–2479) | 1448 (1419–1548) | 635
| 5/5 |
| Warm Inbox navigation | 5 | 2020 (1485–2254) | 1568 (1289–1848) | 350
| 5/5 |
| Task → Back to Tasks | 5 | 1747 (1609–1948) | 1327 (1238–1355) | 472 |
5/5 |

Cold Tasks, warm Tasks, warm Inbox, and Back improved in every measured
pair. **Cold Inbox latency is inconclusive:** the two waves pointed in
opposite directions, with the candidate faster in 5/10 pairs. This PR
claims less badge work there, not a proven cold Inbox latency
improvement.

The canonical badge response shrank from **200,039 to 359 decoded
bytes** (encoded HTTP transfer: **8,125 to 598 bytes**). The compact
response also skips card payloads, plans, images, and presentation-only
roster work. These are measured mechanism reductions, separate from
end-to-end latency. Needs You still owns its full card feed; Needs
attention owns its complete task-ID projection. Reproduction setup and
assertions are in `tests/perf/collections/README.md`.

<details>
<summary>Individual paired readiness measurements (ms)</summary>

| Journey | Pair | Baseline | Candidate |
| --- | ---: | ---: | ---: |
| Cold Tasks | 1 | 3025 | 2283 |
| Cold Tasks | 2 | 2542 | 2275 |
| Cold Tasks | 3 | 2752 | 2424 |
| Cold Tasks | 4 | 2783 | 2300 |
| Cold Tasks | 5 | 2641 | 2524 |
| Cold Inbox | 1 | 2927 | 2702 |
| Cold Inbox | 2 | 2422 | 2629 |
| Cold Inbox | 3 | 2409 | 2606 |
| Cold Inbox | 4 | 2621 | 2769 |
| Cold Inbox | 5 | 2539 | 2856 |
| Cold Inbox | 6 | 2283 | 2117 |
| Cold Inbox | 7 | 2466 | 2558 |
| Cold Inbox | 8 | 2674 | 2286 |
| Cold Inbox | 9 | 2696 | 2389 |
| Cold Inbox | 10 | 2533 | 2183 |
| Warm Tasks navigation | 1 | 2479 | 1423 |
| Warm Tasks navigation | 2 | 2228 | 1548 |
| Warm Tasks navigation | 3 | 2054 | 1419 |
| Warm Tasks navigation | 4 | 1826 | 1448 |
| Warm Tasks navigation | 5 | 1954 | 1518 |
| Warm Inbox navigation | 1 | 2020 | 1661 |
| Warm Inbox navigation | 2 | 2198 | 1848 |
| Warm Inbox navigation | 3 | 1733 | 1497 |
| Warm Inbox navigation | 4 | 2254 | 1568 |
| Warm Inbox navigation | 5 | 1485 | 1289 |
| Task → Back to Tasks | 1 | 1721 | 1330 |
| Task → Back to Tasks | 2 | 1747 | 1275 |
| Task → Back to Tasks | 3 | 1948 | 1355 |
| Task → Back to Tasks | 4 | 1609 | 1327 |
| Task → Back to Tasks | 5 | 1790 | 1238 |

</details>

### Failed attempts and limits

- The local full repository command hit embedded PostgreSQL startup
failures and 16 failures in the untouched native session executor suite;
it was stopped. The full local suite is not claimed green. CI on the
final revision provides the broad test result.
- A concurrent local UI run hit timing failures under host contention.
Inbox/IssuesList subsequently passed all 101 tests serially. No tests
were weakened to address these timeouts.
- CI caught two integration gaps introduced during this work: missing
OpenAPI entries for the new endpoints, and an attention fixture
incompatible with the routine filters added on master. Both were fixed;
the affected 31 OpenAPI and 40 UI tests pass.
- The final revision's first CI attempt failed two untouched tests:
scheduled-retry batch cancellation and the tool-access audience/archive
race. Both failed jobs passed when rerun without changing the revision.
Their original failed attempts remain visible in [the workflow
history](https://github.com/paperclipai/paperclip/actions/runs/41083379875).
- Browser evidence uses synthetic disposable data. This PR is not
deployed staging or production verification.

## Risks

- New attention sources must preserve canonical eligibility. Both
projections call the existing collector, so they share its permissions
and complete-set behavior.
- The count and task-ID caches must not stand in for full decision
cards. Each projection has its own key under the existing attention
invalidation prefix.
- A row budget can omit descendants if applied per parent. The tests
cover one global budget across a large expanded tree, refresh, append,
reset, and incremental loading.
- Local browser evidence uses synthetic data and is not staging
deployment proof.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The exact backend model deployment ID and context window were
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; broad-run
limitations are listed 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
- [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-30 11:58:53 -05:00
0a09e4d975 feat(decisions): add desk workflow and retention (#10672)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The Decisions desk shows work that needs a human decision
> - The queue foundation can group and rank decision work
> - Operators also need a focused daily view and a safe way to handle
old work
> - This pull request adds the desk controls, the aging shelf, and
reversible retention
> - It also binds bulk archive decisions to the exact reviewed item set
> - The benefit is a smaller daily queue without lost or orphaned work

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting: server, UI, database, and shared contracts.

**Problem or motivation**

Decision work can grow into one large company list. Operators need quick
queue and date controls. Old items also need a safe retention path that
does not delete work.

**Proposed solution**

Add queue and date controls to the Decisions desk. Compute the aging
shelf on the server. Archive idle items after 90 days unless an operator
keeps them. Keep archived items searchable and revivable. Notify origin
agents in one batch per sweep. Bind bulk archive proposals to a signed,
exact item manifest.

**Alternatives considered**

Client-only aging can drift across browsers and source kinds. Deleting
old rows removes audit and recovery paths. An unsigned dynamic bulk
query can archive items that the reviewer did not inspect.

**Roadmap alignment**

This work supports the Work Queues and decision-memory directions in
`ROADMAP.md`. It extends the Decisions and attention-feed foundation
from #10651. Related earlier work includes #9380, #10010, and #10474.

## What Changed

- Added the queue rail, date chips, decide split, triage strip, queue
page, and aging shelf UI.
- Added server-owned shelf state with per-queue retention overrides.
- Added reversible retention state, archive history, and an idempotent
notification outbox.
- Added the 90-day archive sweeper, Keep exemption, archived feed query,
and revive actions.
- Added one origin-agent notification per agent and sweep.
- Added signed bulk archive proposals with exact-set and version checks.
- Persisted queue-exclusion reasons atomically and kept cross-domain
source resolution per-item until it has an exact-set transaction
contract.
- Added API contracts, OpenAPI entries, migration coverage, focused
tests, and Storybook screens.

## Verification

- `pnpm -r typecheck`
- `pnpm test:run` (server: 329 files and 3,453 tests passed; UI: 408
files and 3,362 tests passed)
- `env -u AWS_ACCESS_KEY_ID -u AWS_SECRET_ACCESS_KEY pnpm exec vitest
run cli/src/__tests__/secrets.test.ts`
- `pnpm build`
- `pnpm check:token-gates`
- Focused retention, attention, decisions, migration replay, startup,
and UI API tests.
- Complete queue snapshot regression with 51 items across the normal
50-item page boundary.

The unmodified CLI test reports one warning assertion in this runtime
because the harness injects static AWS credential variables. The
isolated test passes when those two variables are removed.

## Risks

- The migration adds retention and notification outbox tables. It uses
idempotent table, index, and foreign-key creation.
- Retention runs on the heartbeat scheduler interval. Compare-and-set
version checks prevent stale archive writes.
- Bulk archive acceptance fails closed when authority, activity,
version, or the reviewed set changes.
- Archive is reversible and does not delete source records.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

OpenAI Codex with `gpt-5.6-sol`. The model used tool calls, code
execution, database migration generation, and test execution. The
context-window size is not exposed in this runtime.

## 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: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-02 10:47:03 -05:00
DottaandPaperclip 30c49c8327 feat(decisions): add queues and prioritized attention feed (#10651)
<!-- Write all pull request text in Simplified Technical English
(ASD-STE100): short sentences, one instruction per sentence, simple
approved vocabulary, and the active voice. -->

## Thinking Path

> - Paperclip is the open source control plane for companies of AI
agents.
> - Operators use the attention feed to find decisions that need action.
> - The feed has eleven source kinds, but it has no durable queue or
triage state.
> - The feed also returns every item and lacks decision deadlines,
snooze state, and decision-focused ordering.
> - This pull request adds secure queue sidecars and enriches the
attention feed with triage data, filters, cursor pagination, and
decide-now ranking.
> - The benefit is a bounded feed that can show the most urgent
decisions first without weakening source visibility rules.

## Linked Issues or Issue Description

This pull request replaces the closed
[#10634](https://github.com/paperclipai/paperclip/pull/10634). It
combines that queue foundation with the dependent attention-feed change
as one review unit.

**Subsystem affected**

Database schema, shared contracts, server authorization and REST APIs,
and the UI attention client library.

**Problem or motivation**

The attention feed can contain hundreds of mixed decision items.
Operators cannot group them into durable queues, set a decision
deadline, snooze an item, or request a bounded page ordered by urgency.
The current client must download the full feed on each refresh.

**Proposed solution**

Store queue membership and triage state by stable attention identity.
Re-authorize each source during queue reads and writes. Enrich attention
items with queue, deadline, snooze, expiry, rule, and origin data. Add
activity and queue filters, opaque cursor pagination, decide-focused
ordering, and a decide-now count.

**Alternatives considered**

Adding queue fields to every source would duplicate schema and
authorization logic across eleven source kinds. Client-only filtering
and sorting would still transfer the full feed and would make pagination
unstable.

**Roadmap alignment**

This change improves the core decision-attention surface and operator
oversight. It does not implement the separate general-purpose work queue
milestone in `ROADMAP.md`.

## What Changed

- Added company-scoped queue, membership, triage, and append-only event
tables with actor and run provenance.
- Added queue CRUD, item membership, starter-rule discovery, and
decide-by and snooze endpoints.
- Kept source authorization on each queue mutation, read, and count.
- Added attention fields for expiry, rule, origin agent, queues,
decide-by attribution, and snooze state.
- Added activity date filters, queue filters, opaque cursor pagination,
and configurable page limits.
- Added decide-now ordering by deadline, expiry, severity, and activity.
- Added `decideNowCount` and excluded actively snoozed items from the
default feed.
- Updated the shared and UI client contracts.
- Added focused server, route, OpenAPI, and UI client tests.

## Verification

- `pnpm exec vitest run server/src/__tests__/attention-service.test.ts
server/src/__tests__/decision-queues-routes.test.ts
server/src/__tests__/openapi-routes.test.ts ui/src/api/attention.test.ts
ui/src/lib/attention.test.ts` (72 tests passed)
- `pnpm --filter @paperclipai/db check:migrations`
- `pnpm -r --filter @paperclipai/db --filter @paperclipai/shared
--filter @paperclipai/server --filter @paperclipai/ui typecheck`
- `git diff --check origin/master...HEAD`

## Risks

- The migration adds four company-scoped tables and provenance foreign
keys. Migration numbering and safety checks pass.
- Attention reads can lazily create starter queues and memberships.
Inserts are idempotent, audited, and transactional.
- Cursor validity depends on the filtered feed. The API returns a clear
validation error when the cursor item no longer exists in that feed.
- Queue reads re-check source visibility. This favors correct
authorization over fewer queries.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, model `gpt-5`. The runtime used agentic reasoning,
repository tools, code execution, and test execution. The runtime did
not expose the context-window size.

## Checklist

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

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-08-01 20:37:39 -05:00