paperclip/ui/src/components/IssueChatThread.test.tsx

2375 lines
72 KiB
TypeScript
Raw Normal View History

// @vitest-environment jsdom
import { act, createRef, forwardRef, useImperativeHandle } from "react";
import type { ReactNode } from "react";
import { createRoot } from "react-dom/client";
import { MemoryRouter } from "react-router-dom";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
[codex] Polish issue board workflows (#4224) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Human operators supervise that work through issue lists, issue detail, comments, inbox groups, markdown references, and profile/activity surfaces > - The branch had many small UI fixes that improve the operator loop but do not need to ship with backend runtime migrations > - These changes belong together as board workflow polish because they affect scanning, navigation, issue context, comment state, and markdown clarity > - This pull request groups the UI-only slice so it can merge independently from runtime/backend changes > - The benefit is a clearer board experience with better issue context, steadier optimistic updates, and more predictable keyboard navigation ## What Changed - Improves issue properties, sub-issue actions, blocker chips, and issue list/detail refresh behavior. - Adds blocker context above the issue composer and stabilizes queued/interrupted comment UI state. - Improves markdown issue/GitHub link rendering and opens external markdown links in a new tab. - Adds inbox group keyboard navigation and fold/unfold support. - Polishes activity/avatar/profile/settings/workspace presentation details. ## Verification - `pnpm exec vitest run ui/src/components/IssueProperties.test.tsx ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownBody.test.tsx ui/src/lib/inbox.test.ts ui/src/lib/optimistic-issue-comments.test.ts` ## Risks - Low to medium risk: changes are UI-focused but cover high-traffic issue and inbox surfaces. - This branch intentionally does not include the backend runtime changes from the companion PR; where UI calls newer API filters, unsupported servers should continue to fail visibly through existing API error handling. - Visual screenshots were not captured in this heartbeat; targeted component/helper tests cover the changed behavior. > 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, GPT-5-based coding agent runtime, shell/git tool use enabled. Exact hosted model build and context window are not exposed in this Paperclip heartbeat environment. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge
2026-04-21 12:25:34 -05:00
import type { Agent } from "@paperclipai/shared";
feat: implement multi-user access and invite flows (#3784) ## Thinking Path > - Paperclip is the control plane for autonomous AI companies. > - V1 needs to stay local-first while also supporting shared, authenticated deployments. > - Human operators need real identities, company membership, invite flows, profile surfaces, and company-scoped access controls. > - Agents and operators also need the existing issue, inbox, workspace, approval, and plugin flows to keep working under those authenticated boundaries. > - This branch accumulated the multi-user implementation, follow-up QA fixes, workspace/runtime refinements, invite UX improvements, release-branch conflict resolution, and review hardening. > - This pull request consolidates that branch onto the current `master` branch as a single reviewable PR. > - The benefit is a complete multi-user implementation path with tests and docs carried forward without dropping existing branch work. ## What Changed - Added authenticated human-user access surfaces: auth/session routes, company user directory, profile settings, company access/member management, join requests, and invite management. - Added invite creation, invite landing, onboarding, logo/branding, invite grants, deduped join requests, and authenticated multi-user E2E coverage. - Tightened company-scoped and instance-admin authorization across board, plugin, adapter, access, issue, and workspace routes. - Added profile-image URL validation hardening, avatar preservation on name-only profile updates, and join-request uniqueness migration cleanup for pending human requests. - Added an atomic member role/status/grants update path so Company Access saves no longer leave partially updated permissions. - Improved issue chat, inbox, assignee identity rendering, sidebar/account/company navigation, workspace routing, and execution workspace reuse behavior for multi-user operation. - Added and updated server/UI tests covering auth, invites, membership, issue workspace inheritance, plugin authz, inbox/chat behavior, and multi-user flows. - Merged current `public-gh/master` into this branch, resolved all conflicts, and verified no `pnpm-lock.yaml` change is included in this PR diff. ## Verification - `pnpm exec vitest run server/src/__tests__/issues-service.test.ts ui/src/components/IssueChatThread.test.tsx ui/src/pages/Inbox.test.tsx` - `pnpm run preflight:workspace-links && pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts` - `pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts server/src/__tests__/workspace-runtime-service-authz.test.ts server/src/__tests__/access-validators.test.ts` - `pnpm exec vitest run server/src/__tests__/authz-company-access.test.ts server/src/__tests__/routines-routes.test.ts server/src/__tests__/sidebar-preferences-routes.test.ts server/src/__tests__/approval-routes-idempotency.test.ts server/src/__tests__/openclaw-invite-prompt-route.test.ts server/src/__tests__/agent-cross-tenant-authz-routes.test.ts server/src/__tests__/routines-e2e.test.ts` - `pnpm exec vitest run server/src/__tests__/auth-routes.test.ts ui/src/pages/CompanyAccess.test.tsx` - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/db typecheck && pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/ui typecheck` - `pnpm db:generate` - `npx playwright test --config tests/e2e/playwright.config.ts --list` - Confirmed branch has no uncommitted changes and is `0` commits behind `public-gh/master` before PR creation. - Confirmed no `pnpm-lock.yaml` change is staged or present in the PR diff. ## Risks - High review surface area: this PR contains the accumulated multi-user branch plus follow-up fixes, so reviewers should focus especially on company-boundary enforcement and authenticated-vs-local deployment behavior. - UI behavior changed across invites, inbox, issue chat, access settings, and sidebar navigation; no browser screenshots are included in this branch-consolidation PR. - Plugin install, upgrade, and lifecycle/config mutations now require instance-admin access, which is intentional but may change expectations for non-admin board users. - A join-request dedupe migration rejects duplicate pending human requests before creating unique indexes; deployments with unusual historical duplicates should review the migration behavior. - Company member role/status/grant saves now use a new combined endpoint; older separate endpoints remain for compatibility. - Full production build was not run locally in this heartbeat; CI should cover the full matrix. ## Model Used - OpenAI Codex coding agent, GPT-5-based model, CLI/tool-use environment. Exact deployed model identifier and context window were not exposed by the 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note on screenshots: this is a branch-consolidation PR for an already-developed multi-user branch, and no browser screenshots were captured during this heartbeat. --------- Co-authored-by: dotta <dotta@example.com> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 09:44:19 -05:00
import {
IssueChatThread,
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
VIRTUALIZED_THREAD_ROW_THRESHOLD,
feat: implement multi-user access and invite flows (#3784) ## Thinking Path > - Paperclip is the control plane for autonomous AI companies. > - V1 needs to stay local-first while also supporting shared, authenticated deployments. > - Human operators need real identities, company membership, invite flows, profile surfaces, and company-scoped access controls. > - Agents and operators also need the existing issue, inbox, workspace, approval, and plugin flows to keep working under those authenticated boundaries. > - This branch accumulated the multi-user implementation, follow-up QA fixes, workspace/runtime refinements, invite UX improvements, release-branch conflict resolution, and review hardening. > - This pull request consolidates that branch onto the current `master` branch as a single reviewable PR. > - The benefit is a complete multi-user implementation path with tests and docs carried forward without dropping existing branch work. ## What Changed - Added authenticated human-user access surfaces: auth/session routes, company user directory, profile settings, company access/member management, join requests, and invite management. - Added invite creation, invite landing, onboarding, logo/branding, invite grants, deduped join requests, and authenticated multi-user E2E coverage. - Tightened company-scoped and instance-admin authorization across board, plugin, adapter, access, issue, and workspace routes. - Added profile-image URL validation hardening, avatar preservation on name-only profile updates, and join-request uniqueness migration cleanup for pending human requests. - Added an atomic member role/status/grants update path so Company Access saves no longer leave partially updated permissions. - Improved issue chat, inbox, assignee identity rendering, sidebar/account/company navigation, workspace routing, and execution workspace reuse behavior for multi-user operation. - Added and updated server/UI tests covering auth, invites, membership, issue workspace inheritance, plugin authz, inbox/chat behavior, and multi-user flows. - Merged current `public-gh/master` into this branch, resolved all conflicts, and verified no `pnpm-lock.yaml` change is included in this PR diff. ## Verification - `pnpm exec vitest run server/src/__tests__/issues-service.test.ts ui/src/components/IssueChatThread.test.tsx ui/src/pages/Inbox.test.tsx` - `pnpm run preflight:workspace-links && pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts` - `pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts server/src/__tests__/workspace-runtime-service-authz.test.ts server/src/__tests__/access-validators.test.ts` - `pnpm exec vitest run server/src/__tests__/authz-company-access.test.ts server/src/__tests__/routines-routes.test.ts server/src/__tests__/sidebar-preferences-routes.test.ts server/src/__tests__/approval-routes-idempotency.test.ts server/src/__tests__/openclaw-invite-prompt-route.test.ts server/src/__tests__/agent-cross-tenant-authz-routes.test.ts server/src/__tests__/routines-e2e.test.ts` - `pnpm exec vitest run server/src/__tests__/auth-routes.test.ts ui/src/pages/CompanyAccess.test.tsx` - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/db typecheck && pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/ui typecheck` - `pnpm db:generate` - `npx playwright test --config tests/e2e/playwright.config.ts --list` - Confirmed branch has no uncommitted changes and is `0` commits behind `public-gh/master` before PR creation. - Confirmed no `pnpm-lock.yaml` change is staged or present in the PR diff. ## Risks - High review surface area: this PR contains the accumulated multi-user branch plus follow-up fixes, so reviewers should focus especially on company-boundary enforcement and authenticated-vs-local deployment behavior. - UI behavior changed across invites, inbox, issue chat, access settings, and sidebar navigation; no browser screenshots are included in this branch-consolidation PR. - Plugin install, upgrade, and lifecycle/config mutations now require instance-admin access, which is intentional but may change expectations for non-admin board users. - A join-request dedupe migration rejects duplicate pending human requests before creating unique indexes; deployments with unusual historical duplicates should review the migration behavior. - Company member role/status/grant saves now use a new combined endpoint; older separate endpoints remain for compatibility. - Full production build was not run locally in this heartbeat; CI should cover the full matrix. ## Model Used - OpenAI Codex coding agent, GPT-5-based model, CLI/tool-use environment. Exact deployed model identifier and context window were not exposed by the 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note on screenshots: this is a branch-consolidation PR for an already-developed multi-user branch, and no browser screenshots were captured during this heartbeat. --------- Co-authored-by: dotta <dotta@example.com> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 09:44:19 -05:00
canStopIssueChatRun,
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
findLatestCommentMessageIndex,
feat: implement multi-user access and invite flows (#3784) ## Thinking Path > - Paperclip is the control plane for autonomous AI companies. > - V1 needs to stay local-first while also supporting shared, authenticated deployments. > - Human operators need real identities, company membership, invite flows, profile surfaces, and company-scoped access controls. > - Agents and operators also need the existing issue, inbox, workspace, approval, and plugin flows to keep working under those authenticated boundaries. > - This branch accumulated the multi-user implementation, follow-up QA fixes, workspace/runtime refinements, invite UX improvements, release-branch conflict resolution, and review hardening. > - This pull request consolidates that branch onto the current `master` branch as a single reviewable PR. > - The benefit is a complete multi-user implementation path with tests and docs carried forward without dropping existing branch work. ## What Changed - Added authenticated human-user access surfaces: auth/session routes, company user directory, profile settings, company access/member management, join requests, and invite management. - Added invite creation, invite landing, onboarding, logo/branding, invite grants, deduped join requests, and authenticated multi-user E2E coverage. - Tightened company-scoped and instance-admin authorization across board, plugin, adapter, access, issue, and workspace routes. - Added profile-image URL validation hardening, avatar preservation on name-only profile updates, and join-request uniqueness migration cleanup for pending human requests. - Added an atomic member role/status/grants update path so Company Access saves no longer leave partially updated permissions. - Improved issue chat, inbox, assignee identity rendering, sidebar/account/company navigation, workspace routing, and execution workspace reuse behavior for multi-user operation. - Added and updated server/UI tests covering auth, invites, membership, issue workspace inheritance, plugin authz, inbox/chat behavior, and multi-user flows. - Merged current `public-gh/master` into this branch, resolved all conflicts, and verified no `pnpm-lock.yaml` change is included in this PR diff. ## Verification - `pnpm exec vitest run server/src/__tests__/issues-service.test.ts ui/src/components/IssueChatThread.test.tsx ui/src/pages/Inbox.test.tsx` - `pnpm run preflight:workspace-links && pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts` - `pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts server/src/__tests__/workspace-runtime-service-authz.test.ts server/src/__tests__/access-validators.test.ts` - `pnpm exec vitest run server/src/__tests__/authz-company-access.test.ts server/src/__tests__/routines-routes.test.ts server/src/__tests__/sidebar-preferences-routes.test.ts server/src/__tests__/approval-routes-idempotency.test.ts server/src/__tests__/openclaw-invite-prompt-route.test.ts server/src/__tests__/agent-cross-tenant-authz-routes.test.ts server/src/__tests__/routines-e2e.test.ts` - `pnpm exec vitest run server/src/__tests__/auth-routes.test.ts ui/src/pages/CompanyAccess.test.tsx` - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/db typecheck && pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/ui typecheck` - `pnpm db:generate` - `npx playwright test --config tests/e2e/playwright.config.ts --list` - Confirmed branch has no uncommitted changes and is `0` commits behind `public-gh/master` before PR creation. - Confirmed no `pnpm-lock.yaml` change is staged or present in the PR diff. ## Risks - High review surface area: this PR contains the accumulated multi-user branch plus follow-up fixes, so reviewers should focus especially on company-boundary enforcement and authenticated-vs-local deployment behavior. - UI behavior changed across invites, inbox, issue chat, access settings, and sidebar navigation; no browser screenshots are included in this branch-consolidation PR. - Plugin install, upgrade, and lifecycle/config mutations now require instance-admin access, which is intentional but may change expectations for non-admin board users. - A join-request dedupe migration rejects duplicate pending human requests before creating unique indexes; deployments with unusual historical duplicates should review the migration behavior. - Company member role/status/grant saves now use a new combined endpoint; older separate endpoints remain for compatibility. - Full production build was not run locally in this heartbeat; CI should cover the full matrix. ## Model Used - OpenAI Codex coding agent, GPT-5-based model, CLI/tool-use environment. Exact deployed model identifier and context window were not exposed by the 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note on screenshots: this is a branch-consolidation PR for an already-developed multi-user branch, and no browser screenshots were captured during this heartbeat. --------- Co-authored-by: dotta <dotta@example.com> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 09:44:19 -05:00
resolveAssistantMessageFoldedState,
resolveIssueChatHumanAuthor,
} from "./IssueChatThread";
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
import { ToastProvider } from "../context/ToastContext";
import { ToastViewport } from "./ToastViewport";
[codex] Add structured issue-thread interactions (#4244) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies. > - Operators supervise that work through issues, comments, approvals, and the board UI. > - Some agent proposals need structured board/user decisions, not hidden markdown conventions or heavyweight governed approvals. > - Issue-thread interactions already provide a natural thread-native surface for proposed tasks and questions. > - This pull request extends that surface with request confirmations, richer interaction cards, and agent/plugin/MCP helpers. > - The benefit is that plan approvals and yes/no decisions become explicit, auditable, and resumable without losing the single-issue workflow. ## What Changed - Added persisted issue-thread interactions for suggested tasks, structured questions, and request confirmations. - Added board UI cards for interaction review, selection, question answers, and accept/reject confirmation flows. - Added MCP and plugin SDK helpers for creating interaction cards from agents/plugins. - Updated agent wake instructions, onboarding assets, Paperclip skill docs, and public docs to prefer structured confirmations for issue-scoped decisions. - Rebased the branch onto `public-gh/master` and renumbered branch migrations to `0063` and `0064`; the idempotency migration uses `ADD COLUMN IF NOT EXISTS` for old branch users. ## Verification - `git diff --check public-gh/master..HEAD` - `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts packages/mcp-server/src/tools.test.ts packages/shared/src/issue-thread-interactions.test.ts ui/src/lib/issue-thread-interactions.test.ts ui/src/lib/issue-chat-messages.test.ts ui/src/components/IssueThreadInteractionCard.test.tsx ui/src/components/IssueChatThread.test.tsx server/src/__tests__/issue-thread-interaction-routes.test.ts server/src/__tests__/issue-thread-interactions-service.test.ts server/src/services/issue-thread-interactions.test.ts` -> 9 files / 79 tests passed - `pnpm -r typecheck` -> passed, including `packages/db` migration numbering check ## Risks - Medium: this adds a new issue-thread interaction model across db/shared/server/ui/plugin surfaces. - Migration risk is reduced by placing this branch after current master migrations (`0063`, `0064`) and making the idempotency column add idempotent for users who applied the old branch numbering. - UI interaction behavior is covered by component tests, but this PR does not include browser screenshots. > 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, GPT-5-class coding agent runtime. Exact model ID and context window are not exposed in this Paperclip run; tool use and local shell/code execution were enabled. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-21 20:15:11 -05:00
import type {
AskUserQuestionsInteraction,
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
RequestConfirmationInteraction,
[codex] Add structured issue-thread interactions (#4244) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies. > - Operators supervise that work through issues, comments, approvals, and the board UI. > - Some agent proposals need structured board/user decisions, not hidden markdown conventions or heavyweight governed approvals. > - Issue-thread interactions already provide a natural thread-native surface for proposed tasks and questions. > - This pull request extends that surface with request confirmations, richer interaction cards, and agent/plugin/MCP helpers. > - The benefit is that plan approvals and yes/no decisions become explicit, auditable, and resumable without losing the single-issue workflow. ## What Changed - Added persisted issue-thread interactions for suggested tasks, structured questions, and request confirmations. - Added board UI cards for interaction review, selection, question answers, and accept/reject confirmation flows. - Added MCP and plugin SDK helpers for creating interaction cards from agents/plugins. - Updated agent wake instructions, onboarding assets, Paperclip skill docs, and public docs to prefer structured confirmations for issue-scoped decisions. - Rebased the branch onto `public-gh/master` and renumbered branch migrations to `0063` and `0064`; the idempotency migration uses `ADD COLUMN IF NOT EXISTS` for old branch users. ## Verification - `git diff --check public-gh/master..HEAD` - `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts packages/mcp-server/src/tools.test.ts packages/shared/src/issue-thread-interactions.test.ts ui/src/lib/issue-thread-interactions.test.ts ui/src/lib/issue-chat-messages.test.ts ui/src/components/IssueThreadInteractionCard.test.tsx ui/src/components/IssueChatThread.test.tsx server/src/__tests__/issue-thread-interaction-routes.test.ts server/src/__tests__/issue-thread-interactions-service.test.ts server/src/services/issue-thread-interactions.test.ts` -> 9 files / 79 tests passed - `pnpm -r typecheck` -> passed, including `packages/db` migration numbering check ## Risks - Medium: this adds a new issue-thread interaction model across db/shared/server/ui/plugin surfaces. - Migration risk is reduced by placing this branch after current master migrations (`0063`, `0064`) and making the idempotency column add idempotent for users who applied the old branch numbering. - UI interaction behavior is covered by component tests, but this PR does not include browser screenshots. > 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, GPT-5-class coding agent runtime. Exact model ID and context window are not exposed in this Paperclip run; tool use and local shell/code execution were enabled. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-21 20:15:11 -05:00
SuggestTasksInteraction,
} from "../lib/issue-thread-interactions";
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
import {
issueChatLongThreadAgentMap,
issueChatLongThreadComments,
issueChatLongThreadEvents,
issueChatLongThreadLinkedRuns,
issueChatLongThreadTranscriptsByRunId,
} from "../fixtures/issueChatLongThreadFixture";
import type {
IssueChatLinkedRun,
IssueChatTranscriptEntry,
} from "../lib/issue-chat-messages";
function hasSmoothScrollBehavior(arg: unknown) {
return typeof arg === "object"
&& arg !== null
&& "behavior" in arg
&& (arg as ScrollToOptions).behavior === "smooth";
}
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
const { markdownBodyRenderMock, markdownEditorFocusMock } = vi.hoisted(() => ({
markdownBodyRenderMock: vi.fn(),
markdownEditorFocusMock: vi.fn(),
}));
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
const { appendMock } = vi.hoisted(() => ({
appendMock: vi.fn(async () => undefined),
}));
const {
captureComposerViewportSnapshotMock,
restoreComposerViewportSnapshotMock,
shouldPreserveComposerViewportMock,
} = vi.hoisted(() => ({
captureComposerViewportSnapshotMock: vi.fn(),
restoreComposerViewportSnapshotMock: vi.fn(),
shouldPreserveComposerViewportMock: vi.fn(),
}));
vi.mock("@assistant-ui/react", () => ({
AssistantRuntimeProvider: ({ children }: { children: ReactNode }) => <div>{children}</div>,
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
useAui: () => ({ thread: () => ({ append: appendMock }) }),
}));
vi.mock("./transcript/useLiveRunTranscripts", () => ({
useLiveRunTranscripts: () => ({
transcriptByRun: new Map(),
hasOutputForRun: () => false,
}),
}));
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
vi.mock("../lib/issue-chat-scroll", async (importOriginal) => {
const actual = await importOriginal<typeof import("../lib/issue-chat-scroll")>();
return {
...actual,
captureComposerViewportSnapshot: captureComposerViewportSnapshotMock.mockImplementation(actual.captureComposerViewportSnapshot),
restoreComposerViewportSnapshot: restoreComposerViewportSnapshotMock.mockImplementation(actual.restoreComposerViewportSnapshot),
shouldPreserveComposerViewport: shouldPreserveComposerViewportMock.mockImplementation(actual.shouldPreserveComposerViewport),
};
});
vi.mock("./MarkdownBody", () => ({
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
MarkdownBody: ({ children }: { children: ReactNode }) => {
markdownBodyRenderMock(children);
return <div>{children}</div>;
},
}));
vi.mock("./MarkdownEditor", () => ({
MarkdownEditor: forwardRef(({
value = "",
onChange,
placeholder,
className,
contentClassName,
[codex] Polish issue composer and long document display (#4420) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue comments and documents are the main working surface where operators and agents collaborate > - File drops, markdown editing, and long issue descriptions need to feel predictable because they sit directly in the task execution loop > - The composer had edge cases around drag targets, attachment feedback, image drops, and long markdown content crowding the page > - This pull request polishes the issue composer, hardens markdown editor regressions, and adds a fold curtain for long issue descriptions/documents > - The benefit is a calmer issue detail surface that handles uploads and long work products without hiding state or breaking layout ## What Changed - Scoped issue-composer drag/drop behavior so the composer owns file drops without turning the whole thread into a competing drop target. - Added clearer attachment upload feedback for non-image files and image-drop stability coverage. - Hardened markdown editor and markdown body handling around HTML-like tag regressions. - Added `FoldCurtain` and wired it into issue descriptions and issue documents so long markdown previews can expand/collapse. - Added Storybook coverage for the fold curtain state. ## Verification - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/MarkdownBody.test.tsx --config ui/vitest.config.ts` passed: 3 files, 75 tests. - `git diff --check public-gh/master..pap-2228-editor-composer-polish -- . ':(exclude)ui/storybook-static'` passed. - Confirmed this PR does not include `pnpm-lock.yaml`. ## Risks - Low-to-medium risk: this changes user-facing composer/drop behavior and long markdown display. - The fold curtain uses DOM measurement and `ResizeObserver`; reviewers should check browser behavior for very long descriptions and documents. - No database migrations. > 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 coding agent based on GPT-5, with shell, git, Paperclip API, and GitHub CLI tool use in the local Paperclip workspace. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note: screenshots were not newly captured during branch splitting; the UI states are covered by component tests and a Storybook story. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 14:12:41 -05:00
fileDropTarget,
}: {
value?: string;
onChange?: (value: string) => void;
placeholder?: string;
className?: string;
contentClassName?: string;
[codex] Polish issue composer and long document display (#4420) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue comments and documents are the main working surface where operators and agents collaborate > - File drops, markdown editing, and long issue descriptions need to feel predictable because they sit directly in the task execution loop > - The composer had edge cases around drag targets, attachment feedback, image drops, and long markdown content crowding the page > - This pull request polishes the issue composer, hardens markdown editor regressions, and adds a fold curtain for long issue descriptions/documents > - The benefit is a calmer issue detail surface that handles uploads and long work products without hiding state or breaking layout ## What Changed - Scoped issue-composer drag/drop behavior so the composer owns file drops without turning the whole thread into a competing drop target. - Added clearer attachment upload feedback for non-image files and image-drop stability coverage. - Hardened markdown editor and markdown body handling around HTML-like tag regressions. - Added `FoldCurtain` and wired it into issue descriptions and issue documents so long markdown previews can expand/collapse. - Added Storybook coverage for the fold curtain state. ## Verification - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/MarkdownBody.test.tsx --config ui/vitest.config.ts` passed: 3 files, 75 tests. - `git diff --check public-gh/master..pap-2228-editor-composer-polish -- . ':(exclude)ui/storybook-static'` passed. - Confirmed this PR does not include `pnpm-lock.yaml`. ## Risks - Low-to-medium risk: this changes user-facing composer/drop behavior and long markdown display. - The fold curtain uses DOM measurement and `ResizeObserver`; reviewers should check browser behavior for very long descriptions and documents. - No database migrations. > 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 coding agent based on GPT-5, with shell, git, Paperclip API, and GitHub CLI tool use in the local Paperclip workspace. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note: screenshots were not newly captured during branch splitting; the UI states are covered by component tests and a Storybook story. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 14:12:41 -05:00
fileDropTarget?: "editor" | "parent";
}, ref) => {
useImperativeHandle(ref, () => ({
focus: markdownEditorFocusMock,
}));
return (
<textarea
aria-label="Issue chat editor"
data-class-name={className}
data-content-class-name={contentClassName}
[codex] Polish issue composer and long document display (#4420) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue comments and documents are the main working surface where operators and agents collaborate > - File drops, markdown editing, and long issue descriptions need to feel predictable because they sit directly in the task execution loop > - The composer had edge cases around drag targets, attachment feedback, image drops, and long markdown content crowding the page > - This pull request polishes the issue composer, hardens markdown editor regressions, and adds a fold curtain for long issue descriptions/documents > - The benefit is a calmer issue detail surface that handles uploads and long work products without hiding state or breaking layout ## What Changed - Scoped issue-composer drag/drop behavior so the composer owns file drops without turning the whole thread into a competing drop target. - Added clearer attachment upload feedback for non-image files and image-drop stability coverage. - Hardened markdown editor and markdown body handling around HTML-like tag regressions. - Added `FoldCurtain` and wired it into issue descriptions and issue documents so long markdown previews can expand/collapse. - Added Storybook coverage for the fold curtain state. ## Verification - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/MarkdownBody.test.tsx --config ui/vitest.config.ts` passed: 3 files, 75 tests. - `git diff --check public-gh/master..pap-2228-editor-composer-polish -- . ':(exclude)ui/storybook-static'` passed. - Confirmed this PR does not include `pnpm-lock.yaml`. ## Risks - Low-to-medium risk: this changes user-facing composer/drop behavior and long markdown display. - The fold curtain uses DOM measurement and `ResizeObserver`; reviewers should check browser behavior for very long descriptions and documents. - No database migrations. > 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 coding agent based on GPT-5, with shell, git, Paperclip API, and GitHub CLI tool use in the local Paperclip workspace. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note: screenshots were not newly captured during branch splitting; the UI states are covered by component tests and a Storybook story. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 14:12:41 -05:00
data-file-drop-target={fileDropTarget}
placeholder={placeholder}
value={value}
onChange={(event) => onChange?.(event.target.value)}
/>
);
}),
}));
vi.mock("./InlineEntitySelector", () => ({
InlineEntitySelector: () => null,
}));
vi.mock("./Identity", () => ({
Identity: ({ name }: { name: string }) => <span>{name}</span>,
}));
vi.mock("./OutputFeedbackButtons", () => ({
OutputFeedbackButtons: () => null,
}));
[codex] Polish issue and operator workflow UI (#4090) ## Thinking Path > - Paperclip operators spend much of their time in issues, inboxes, selectors, and rich comment threads. > - Small interaction problems in those surfaces slow down supervision of AI-agent work. > - The branch included related operator quality-of-life fixes for issue layout, inbox actions, recent selectors, mobile inputs, and chat rendering stability. > - These changes are UI-focused and can land independently from workspace navigation and access-profile work. > - This pull request groups the operator QoL fixes into one standalone branch. > - The benefit is a more stable and efficient board workflow for issue triage and task editing. ## What Changed - Widened issue detail content and added a desktop inbox archive action. - Fixed mobile text-field zoom by keeping touch input font sizes at 16px. - Prioritized recent picker selections for assignees/projects in issue and routine flows. - Showed actionable approvals in the Mine inbox model. - Fixed issue chat renderer state crashes and hardened tests. ## Verification - `pnpm install --frozen-lockfile` - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/lib/inbox.test.ts ui/src/lib/recent-selections.test.ts` - Split integration check: merged last after the other [PAP-1614](/PAP/issues/PAP-1614) branches with no merge conflicts. - Confirmed this branch does not include `pnpm-lock.yaml`. ## Risks - Low to medium risk: mostly UI state, layout, and selection-priority behavior. - Visual layout and mobile zoom behavior may need browser/device QA beyond component tests. - No database migrations are included. > 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, GPT-5.4 tool-enabled coding model, agentic code-editing/runtime with local shell and GitHub CLI access; exact context window and reasoning mode are not exposed by the Paperclip harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-20 06:16:41 -05:00
vi.mock("@/components/ui/tooltip", () => ({
Tooltip: ({ children }: { children: ReactNode }) => <>{children}</>,
TooltipContent: ({ children }: { children: ReactNode }) => <div>{children}</div>,
TooltipTrigger: ({ children }: { children: ReactNode }) => <>{children}</>,
}));
vi.mock("./AgentIconPicker", () => ({
AgentIcon: () => null,
}));
vi.mock("./StatusBadge", () => ({
StatusBadge: ({ status }: { status: string }) => <span>{status}</span>,
}));
[codex] Polish issue board workflows (#4224) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Human operators supervise that work through issue lists, issue detail, comments, inbox groups, markdown references, and profile/activity surfaces > - The branch had many small UI fixes that improve the operator loop but do not need to ship with backend runtime migrations > - These changes belong together as board workflow polish because they affect scanning, navigation, issue context, comment state, and markdown clarity > - This pull request groups the UI-only slice so it can merge independently from runtime/backend changes > - The benefit is a clearer board experience with better issue context, steadier optimistic updates, and more predictable keyboard navigation ## What Changed - Improves issue properties, sub-issue actions, blocker chips, and issue list/detail refresh behavior. - Adds blocker context above the issue composer and stabilizes queued/interrupted comment UI state. - Improves markdown issue/GitHub link rendering and opens external markdown links in a new tab. - Adds inbox group keyboard navigation and fold/unfold support. - Polishes activity/avatar/profile/settings/workspace presentation details. ## Verification - `pnpm exec vitest run ui/src/components/IssueProperties.test.tsx ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownBody.test.tsx ui/src/lib/inbox.test.ts ui/src/lib/optimistic-issue-comments.test.ts` ## Risks - Low to medium risk: changes are UI-focused but cover high-traffic issue and inbox surfaces. - This branch intentionally does not include the backend runtime changes from the companion PR; where UI calls newer API filters, unsupported servers should continue to fail visibly through existing API error handling. - Visual screenshots were not captured in this heartbeat; targeted component/helper tests cover the changed behavior. > 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, GPT-5-based coding agent runtime, shell/git tool use enabled. Exact hosted model build and context window are not exposed in this Paperclip heartbeat environment. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge
2026-04-21 12:25:34 -05:00
vi.mock("./IssueLinkQuicklook", () => ({
IssueLinkQuicklook: ({
children,
to,
issuePathId,
className,
}: {
children: ReactNode;
to: string;
issuePathId: string;
className?: string;
}) => (
<a href={to} data-issue-path-id={issuePathId} className={className}>
{children}
</a>
),
}));
vi.mock("../hooks/usePaperclipIssueRuntime", () => ({
usePaperclipIssueRuntime: () => ({}),
}));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
[codex] Add structured issue-thread interactions (#4244) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies. > - Operators supervise that work through issues, comments, approvals, and the board UI. > - Some agent proposals need structured board/user decisions, not hidden markdown conventions or heavyweight governed approvals. > - Issue-thread interactions already provide a natural thread-native surface for proposed tasks and questions. > - This pull request extends that surface with request confirmations, richer interaction cards, and agent/plugin/MCP helpers. > - The benefit is that plan approvals and yes/no decisions become explicit, auditable, and resumable without losing the single-issue workflow. ## What Changed - Added persisted issue-thread interactions for suggested tasks, structured questions, and request confirmations. - Added board UI cards for interaction review, selection, question answers, and accept/reject confirmation flows. - Added MCP and plugin SDK helpers for creating interaction cards from agents/plugins. - Updated agent wake instructions, onboarding assets, Paperclip skill docs, and public docs to prefer structured confirmations for issue-scoped decisions. - Rebased the branch onto `public-gh/master` and renumbered branch migrations to `0063` and `0064`; the idempotency migration uses `ADD COLUMN IF NOT EXISTS` for old branch users. ## Verification - `git diff --check public-gh/master..HEAD` - `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts packages/mcp-server/src/tools.test.ts packages/shared/src/issue-thread-interactions.test.ts ui/src/lib/issue-thread-interactions.test.ts ui/src/lib/issue-chat-messages.test.ts ui/src/components/IssueThreadInteractionCard.test.tsx ui/src/components/IssueChatThread.test.tsx server/src/__tests__/issue-thread-interaction-routes.test.ts server/src/__tests__/issue-thread-interactions-service.test.ts server/src/services/issue-thread-interactions.test.ts` -> 9 files / 79 tests passed - `pnpm -r typecheck` -> passed, including `packages/db` migration numbering check ## Risks - Medium: this adds a new issue-thread interaction model across db/shared/server/ui/plugin surfaces. - Migration risk is reduced by placing this branch after current master migrations (`0063`, `0064`) and making the idempotency column add idempotent for users who applied the old branch numbering. - UI interaction behavior is covered by component tests, but this PR does not include browser screenshots. > 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, GPT-5-class coding agent runtime. Exact model ID and context window are not exposed in this Paperclip run; tool use and local shell/code execution were enabled. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-21 20:15:11 -05:00
function createSuggestedTasksInteraction(
overrides: Partial<SuggestTasksInteraction> = {},
): SuggestTasksInteraction {
return {
id: "interaction-suggest-1",
companyId: "company-1",
issueId: "issue-1",
kind: "suggest_tasks",
title: "Suggested follow-up work",
summary: "Preview the next issue tree before accepting it.",
status: "pending",
continuationPolicy: "wake_assignee",
createdByAgentId: "agent-1",
createdByUserId: null,
resolvedByAgentId: null,
resolvedByUserId: null,
createdAt: new Date("2026-04-06T12:02:00.000Z"),
updatedAt: new Date("2026-04-06T12:02:00.000Z"),
resolvedAt: null,
payload: {
version: 1,
tasks: [
{
clientKey: "task-1",
title: "Prototype the card",
},
],
},
result: null,
...overrides,
};
}
function createQuestionInteraction(
overrides: Partial<AskUserQuestionsInteraction> = {},
): AskUserQuestionsInteraction {
return {
id: "interaction-question-1",
companyId: "company-1",
issueId: "issue-1",
kind: "ask_user_questions",
title: "Clarify the phase",
status: "pending",
continuationPolicy: "wake_assignee",
createdByAgentId: "agent-1",
createdByUserId: null,
resolvedByAgentId: null,
resolvedByUserId: null,
createdAt: new Date("2026-04-06T12:03:00.000Z"),
updatedAt: new Date("2026-04-06T12:03:00.000Z"),
resolvedAt: null,
payload: {
version: 1,
submitLabel: "Submit answers",
questions: [
{
id: "scope",
prompt: "Pick one scope",
selectionMode: "single",
required: true,
options: [
{ id: "phase-1", label: "Phase 1" },
{ id: "phase-2", label: "Phase 2" },
],
},
],
},
result: null,
...overrides,
};
}
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
function createExpiredRequestConfirmationInteraction(
overrides: Partial<RequestConfirmationInteraction> = {},
): RequestConfirmationInteraction {
return {
id: "interaction-confirmation-expired",
companyId: "company-1",
issueId: "issue-1",
kind: "request_confirmation",
title: "Approve the plan",
status: "expired",
continuationPolicy: "wake_assignee_on_accept",
createdByAgentId: "agent-1",
createdByUserId: null,
resolvedByAgentId: null,
resolvedByUserId: "user-1",
createdAt: new Date("2026-04-06T12:04:00.000Z"),
updatedAt: new Date("2026-04-06T12:05:00.000Z"),
resolvedAt: new Date("2026-04-06T12:05:00.000Z"),
payload: {
version: 1,
prompt: "Approve the plan and let the assignee start implementation?",
acceptLabel: "Approve plan",
rejectLabel: "Request revisions",
},
result: {
version: 1,
outcome: "superseded_by_comment",
commentId: "comment-1",
},
...overrides,
};
}
[codex] Polish issue composer and long document display (#4420) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue comments and documents are the main working surface where operators and agents collaborate > - File drops, markdown editing, and long issue descriptions need to feel predictable because they sit directly in the task execution loop > - The composer had edge cases around drag targets, attachment feedback, image drops, and long markdown content crowding the page > - This pull request polishes the issue composer, hardens markdown editor regressions, and adds a fold curtain for long issue descriptions/documents > - The benefit is a calmer issue detail surface that handles uploads and long work products without hiding state or breaking layout ## What Changed - Scoped issue-composer drag/drop behavior so the composer owns file drops without turning the whole thread into a competing drop target. - Added clearer attachment upload feedback for non-image files and image-drop stability coverage. - Hardened markdown editor and markdown body handling around HTML-like tag regressions. - Added `FoldCurtain` and wired it into issue descriptions and issue documents so long markdown previews can expand/collapse. - Added Storybook coverage for the fold curtain state. ## Verification - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/MarkdownBody.test.tsx --config ui/vitest.config.ts` passed: 3 files, 75 tests. - `git diff --check public-gh/master..pap-2228-editor-composer-polish -- . ':(exclude)ui/storybook-static'` passed. - Confirmed this PR does not include `pnpm-lock.yaml`. ## Risks - Low-to-medium risk: this changes user-facing composer/drop behavior and long markdown display. - The fold curtain uses DOM measurement and `ResizeObserver`; reviewers should check browser behavior for very long descriptions and documents. - No database migrations. > 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 coding agent based on GPT-5, with shell, git, Paperclip API, and GitHub CLI tool use in the local Paperclip workspace. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note: screenshots were not newly captured during branch splitting; the UI states are covered by component tests and a Storybook story. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 14:12:41 -05:00
function createFileDragEvent(type: string, files: File[]) {
const event = new Event(type, { bubbles: true, cancelable: true }) as Event & {
dataTransfer: {
types: string[];
files: File[];
dropEffect?: string;
};
};
event.dataTransfer = {
types: ["Files"],
files,
};
return event;
}
describe("IssueChatThread", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.createElement("div");
document.body.appendChild(container);
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
window.scrollTo = vi.fn();
localStorage.clear();
});
afterEach(() => {
container.remove();
vi.useRealTimers();
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
appendMock.mockReset();
markdownEditorFocusMock.mockReset();
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
captureComposerViewportSnapshotMock.mockClear();
restoreComposerViewportSnapshotMock.mockClear();
shouldPreserveComposerViewportMock.mockClear();
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
markdownBodyRenderMock.mockClear();
});
it("drops the count heading and does not use an internal scrollbox", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("Jump to latest");
expect(container.textContent).not.toContain("Chat (");
const viewport = container.querySelector('[data-testid="thread-viewport"]') as HTMLDivElement | null;
expect(viewport).not.toBeNull();
expect(viewport?.className).not.toContain("overflow-y-auto");
expect(viewport?.className).not.toContain("max-h-[70vh]");
act(() => {
root.unmount();
});
});
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
it("virtualizes long merged threads so only a windowed slice mounts", () => {
const root = createRoot(container);
const totalMergedRows =
issueChatLongThreadComments.length
+ issueChatLongThreadEvents.length
+ issueChatLongThreadLinkedRuns.length;
expect(totalMergedRows).toBeGreaterThanOrEqual(VIRTUALIZED_THREAD_ROW_THRESHOLD);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={issueChatLongThreadLinkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
showComposer={false}
showJumpToLatest={false}
enableLiveTranscriptPolling={false}
transcriptsByRunId={issueChatLongThreadTranscriptsByRunId}
hasOutputForRun={(runId) => issueChatLongThreadTranscriptsByRunId.has(runId)}
/>
</MemoryRouter>,
);
});
const virtualizer = container.querySelector(
'[data-testid="issue-chat-thread-virtualizer"]',
) as HTMLDivElement | null;
expect(virtualizer).not.toBeNull();
expect(virtualizer?.dataset.virtualCount).toBe(String(totalMergedRows));
const rows = container.querySelectorAll('[data-testid="issue-chat-message-row"]');
expect(rows.length).toBeGreaterThan(0);
expect(rows.length).toBeLessThan(totalMergedRows);
const virtualRows = container.querySelectorAll(
'[data-testid="issue-chat-thread-virtual-row"]',
);
expect(virtualRows.length).toBe(rows.length);
for (const row of Array.from(virtualRows)) {
const transform = (row as HTMLDivElement).style.transform;
expect(transform).toMatch(/translateY\(/);
}
act(() => {
root.unmount();
});
});
it("measures tall virtual rows before positioning following rows", async () => {
const root = createRoot(container);
const requestAnimationFrameMock = vi
.spyOn(window, "requestAnimationFrame")
.mockImplementation((callback) => {
callback(0);
return 0;
});
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={issueChatLongThreadLinkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
showComposer={false}
showJumpToLatest={false}
enableLiveTranscriptPolling={false}
transcriptsByRunId={issueChatLongThreadTranscriptsByRunId}
hasOutputForRun={(runId) => issueChatLongThreadTranscriptsByRunId.has(runId)}
/>
</MemoryRouter>,
);
});
const virtualRows = container.querySelectorAll<HTMLDivElement>(
'[data-testid="issue-chat-thread-virtual-row"]',
);
expect(virtualRows.length).toBeGreaterThan(1);
Object.defineProperty(virtualRows[0], "getBoundingClientRect", {
configurable: true,
value: () => ({
x: 0,
y: 0,
width: 700,
height: 800,
top: 0,
right: 700,
bottom: 800,
left: 0,
toJSON: () => ({}),
}),
});
await act(async () => {
virtualRows[0].dispatchEvent(new MouseEvent("click", { bubbles: true }));
await Promise.resolve();
});
const nextTransform = virtualRows[1].style.transform;
const translateY = Number(nextTransform.match(/translateY\(([-\d.]+)px\)/)?.[1] ?? "0");
expect(translateY).toBeGreaterThanOrEqual(800);
act(() => {
root.unmount();
});
requestAnimationFrameMock.mockRestore();
});
it("scrolls loaded hash targets through the virtualized message index", () => {
const root = createRoot(container);
const targetComment = issueChatLongThreadComments.at(-1);
expect(targetComment).toBeDefined();
const scrollToMock = vi.spyOn(window, "scrollTo").mockImplementation(() => {});
act(() => {
root.render(
<MemoryRouter initialEntries={[`/issues/PAP-1#comment-${targetComment!.id}`]}>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={issueChatLongThreadLinkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
showComposer={false}
showJumpToLatest={false}
enableLiveTranscriptPolling={false}
transcriptsByRunId={issueChatLongThreadTranscriptsByRunId}
hasOutputForRun={(runId) => issueChatLongThreadTranscriptsByRunId.has(runId)}
/>
</MemoryRouter>,
);
});
expect(scrollToMock.mock.calls.some(([arg]) => hasSmoothScrollBehavior(arg))).toBe(true);
scrollToMock.mockRestore();
act(() => {
root.unmount();
});
});
it("uses the virtualizer when jumping to the latest long-thread row", () => {
const root = createRoot(container);
const scrollToMock = vi.spyOn(window, "scrollTo").mockImplementation(() => {});
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={issueChatLongThreadLinkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
transcriptsByRunId={issueChatLongThreadTranscriptsByRunId}
hasOutputForRun={(runId) => issueChatLongThreadTranscriptsByRunId.has(runId)}
/>
</MemoryRouter>,
);
});
const jump = Array.from(container.querySelectorAll("button")).find(
(button) => button.textContent === "Jump to latest",
) as HTMLButtonElement | undefined;
expect(jump).toBeDefined();
act(() => {
jump?.click();
});
expect(scrollToMock.mock.calls.some(([arg]) => hasSmoothScrollBehavior(arg))).toBe(true);
scrollToMock.mockRestore();
act(() => {
root.unmount();
});
});
// Regression for PAP-2660: on the real issue page the chat thread is wrapped
// in `<main id="main-content" overflow-auto>`, so the virtualizer must bind
// to that ancestor's scroll instead of `window` (which never moves on
// desktop). When mounted inside an overflow-auto ancestor the jump-to-latest
// action must drive that element's scrollTo, not window.scrollTo.
it("targets an overflow-auto ancestor instead of window scroll on jump-to-latest", () => {
container.remove();
const scrollHost = document.createElement("main");
scrollHost.id = "main-content";
scrollHost.style.overflowY = "auto";
scrollHost.style.overflow = "auto";
scrollHost.style.height = "640px";
document.body.appendChild(scrollHost);
container = document.createElement("div");
scrollHost.appendChild(container);
const root = createRoot(container);
const windowScrollToMock = vi.spyOn(window, "scrollTo").mockImplementation(() => {});
const elementScrollToMock = vi.fn();
scrollHost.scrollTo = elementScrollToMock as unknown as typeof scrollHost.scrollTo;
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={issueChatLongThreadLinkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
transcriptsByRunId={issueChatLongThreadTranscriptsByRunId}
hasOutputForRun={(runId) => issueChatLongThreadTranscriptsByRunId.has(runId)}
/>
</MemoryRouter>,
);
});
const jump = Array.from(container.querySelectorAll("button")).find(
(button) => button.textContent === "Jump to latest",
) as HTMLButtonElement | undefined;
expect(jump).toBeDefined();
windowScrollToMock.mockClear();
elementScrollToMock.mockClear();
act(() => {
jump?.click();
});
expect(elementScrollToMock.mock.calls.some(([arg]) => hasSmoothScrollBehavior(arg))).toBe(true);
expect(windowScrollToMock.mock.calls.some(([arg]) => hasSmoothScrollBehavior(arg))).toBe(false);
windowScrollToMock.mockRestore();
act(() => {
root.unmount();
});
scrollHost.remove();
});
// Regression for PAP-2672: when the merged feed ends with a non-comment row
// (run/timeline/embedded output) we still want Jump to latest to land on the
// last comment, not whichever activity row sorts last.
it("targets the latest comment row when trailing rows are non-comments (PAP-2672)", () => {
const lastComment = issueChatLongThreadComments.at(-1);
expect(lastComment).toBeDefined();
const trailingRunStart = new Date(new Date(lastComment!.createdAt).getTime() + 60_000);
const trailingRun: IssueChatLinkedRun = {
runId: "trailing-run-pap-2672",
status: "failed",
agentId: "agent-perf-codex",
agentName: "TrailingRunner",
adapterType: "codex_local",
createdAt: trailingRunStart,
startedAt: trailingRunStart,
finishedAt: trailingRunStart,
hasStoredOutput: true,
};
const trailingTranscriptEntries: readonly IssueChatTranscriptEntry[] = [
{
kind: "assistant",
ts: trailingRunStart.toISOString(),
text: "Trailing run posted after the latest comment.",
},
];
const transcriptsByRunId = new Map(issueChatLongThreadTranscriptsByRunId);
transcriptsByRunId.set(trailingRun.runId, trailingTranscriptEntries);
const linkedRuns: IssueChatLinkedRun[] = [
...issueChatLongThreadLinkedRuns,
trailingRun,
];
container.remove();
const scrollHost = document.createElement("main");
scrollHost.id = "main-content";
scrollHost.style.overflowY = "auto";
scrollHost.style.overflow = "auto";
scrollHost.style.height = "800px";
Object.defineProperty(scrollHost, "scrollHeight", {
configurable: true,
get: () => 200_000,
});
Object.defineProperty(scrollHost, "clientHeight", {
configurable: true,
get: () => 800,
});
document.body.appendChild(scrollHost);
container = document.createElement("div");
scrollHost.appendChild(container);
const elementScrollToMock = vi.fn();
scrollHost.scrollTo = elementScrollToMock as unknown as typeof scrollHost.scrollTo;
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={linkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
transcriptsByRunId={transcriptsByRunId}
hasOutputForRun={(runId) => transcriptsByRunId.has(runId)}
/>
</MemoryRouter>,
);
});
const virtualizerEl = container.querySelector<HTMLDivElement>(
'[data-testid="issue-chat-thread-virtualizer"]',
);
expect(virtualizerEl).not.toBeNull();
const totalMergedRows = Number(virtualizerEl?.dataset.virtualCount ?? "0");
expect(totalMergedRows).toBeGreaterThan(VIRTUALIZED_THREAD_ROW_THRESHOLD);
elementScrollToMock.mockClear();
const jump = Array.from(container.querySelectorAll("button")).find(
(button) => button.textContent === "Jump to latest",
) as HTMLButtonElement | undefined;
expect(jump).toBeDefined();
act(() => {
jump?.click();
});
const smoothCalls = elementScrollToMock.mock.calls
.map((call) => call[0] as ScrollToOptions)
.filter(hasSmoothScrollBehavior);
expect(smoothCalls.length).toBeGreaterThan(0);
// For align="end" with the very last index, tanstack-virtual short-circuits
// to getMaxScrollOffset() (= scrollHeight - clientHeight = 199_200 here).
// A jump to the latest comment row (one slot earlier) lands at item.end -
// clientHeight, which is strictly less. Asserting top < maxScrollOffset
// proves the button isn't routing to the trailing run row.
const maxScrollOffset = 200_000 - 800;
const lastTop = smoothCalls[smoothCalls.length - 1]?.top;
expect(typeof lastTop).toBe("number");
expect(lastTop as number).toBeLessThan(maxScrollOffset);
expect(lastTop as number).toBeGreaterThan(0);
act(() => {
root.unmount();
});
scrollHost.remove();
});
// Regression for PAP-2672 follow-up: clicking Jump to latest must refresh
// the comments page so a comment that arrived after the initial load is
// present before we scroll. Otherwise the user lands on the latest *loaded*
// comment but not the absolute newest.
it("invokes onRefreshLatestComments before scrolling on Jump to latest", async () => {
const refreshMock = vi.fn(async () => undefined);
const directComments = issueChatLongThreadComments.slice(0, 8);
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={directComments}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
onRefreshLatestComments={refreshMock}
/>
</MemoryRouter>,
);
});
const jump = Array.from(container.querySelectorAll("button")).find(
(button) => button.textContent === "Jump to latest",
) as HTMLButtonElement | undefined;
expect(jump).toBeDefined();
act(() => {
jump?.click();
});
expect(refreshMock).toHaveBeenCalledTimes(1);
act(() => {
root.unmount();
});
});
it("findLatestCommentMessageIndex prefers the last comment-anchored row (PAP-2672)", () => {
const messages = [
{ metadata: { custom: { anchorId: "comment-a" } } },
{ metadata: { custom: { anchorId: "run-1" } } },
{ metadata: { custom: { anchorId: "comment-b" } } },
{ metadata: { custom: { anchorId: "run-2" } } },
{ metadata: { custom: { anchorId: "activity-3" } } },
];
expect(findLatestCommentMessageIndex(messages as never)).toBe(2);
expect(
findLatestCommentMessageIndex([
{ metadata: { custom: { anchorId: "run-only" } } },
] as never),
).toBe(-1);
expect(findLatestCommentMessageIndex([] as never)).toBe(-1);
});
it("keeps the direct render path for short threads under the virtualization threshold", () => {
const root = createRoot(container);
const directComments = issueChatLongThreadComments.slice(0, 12);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={directComments}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
showComposer={false}
showJumpToLatest={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(
container.querySelector('[data-testid="issue-chat-thread-virtualizer"]'),
).toBeNull();
const rows = container.querySelectorAll('[data-testid="issue-chat-message-row"]');
expect(rows.length).toBe(directComments.length);
act(() => {
root.unmount();
});
});
it("renders virtualized rows with the same role/kind metadata as the direct path", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={issueChatLongThreadLinkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={async () => {}}
showComposer={false}
showJumpToLatest={false}
enableLiveTranscriptPolling={false}
transcriptsByRunId={issueChatLongThreadTranscriptsByRunId}
hasOutputForRun={(runId) => issueChatLongThreadTranscriptsByRunId.has(runId)}
/>
</MemoryRouter>,
);
});
const rows = container.querySelectorAll('[data-testid="issue-chat-message-row"]');
expect(rows.length).toBeGreaterThan(0);
const roles = new Set<string>();
const kinds = new Set<string>();
for (const row of Array.from(rows)) {
const element = row as HTMLDivElement;
const role = element.dataset.messageRole;
const kind = element.dataset.messageKind;
if (role) roles.add(role);
if (kind) kinds.add(kind);
}
expect(roles.size).toBeGreaterThan(0);
expect(kinds.size).toBeGreaterThan(0);
act(() => {
root.unmount();
});
});
it("does not re-render long-thread markdown rows for unrelated layout updates", () => {
const root = createRoot(container);
const onAdd = async () => {};
const hasOutputForRun = (runId: string) => issueChatLongThreadTranscriptsByRunId.has(runId);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={issueChatLongThreadLinkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={onAdd}
showComposer={false}
showJumpToLatest={false}
enableLiveTranscriptPolling={false}
transcriptsByRunId={issueChatLongThreadTranscriptsByRunId}
hasOutputForRun={hasOutputForRun}
/>
</MemoryRouter>,
);
});
expect(markdownBodyRenderMock).toHaveBeenCalled();
markdownBodyRenderMock.mockClear();
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={issueChatLongThreadComments}
linkedRuns={issueChatLongThreadLinkedRuns}
timelineEvents={issueChatLongThreadEvents}
liveRuns={[]}
agentMap={issueChatLongThreadAgentMap}
currentUserId="user-board"
onAdd={onAdd}
showComposer={false}
showJumpToLatest
enableLiveTranscriptPolling={false}
transcriptsByRunId={issueChatLongThreadTranscriptsByRunId}
hasOutputForRun={hasOutputForRun}
/>
</MemoryRouter>,
);
});
expect(markdownBodyRenderMock).not.toHaveBeenCalled();
act(() => {
root.unmount();
});
});
it("does not re-render unchanged markdown when feedback votes change", () => {
const root = createRoot(container);
const onAdd = async () => {};
const onVote = async () => {};
const comments = [{
id: "comment-agent-feedback",
companyId: "company-1",
issueId: "issue-1",
authorAgentId: "agent-1",
authorUserId: null,
body: "Agent summary with **markdown**",
createdAt: new Date("2026-04-06T12:00:00.000Z"),
updatedAt: new Date("2026-04-06T12:00:00.000Z"),
}];
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={comments}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={onAdd}
onVote={onVote}
feedbackVotes={[]}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(markdownBodyRenderMock).toHaveBeenCalled();
markdownBodyRenderMock.mockClear();
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={comments}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={onAdd}
onVote={onVote}
feedbackVotes={[{
id: "feedback-1",
companyId: "company-1",
issueId: "issue-1",
targetType: "issue_comment",
targetId: "comment-agent-feedback",
authorUserId: "user-1",
vote: "up",
reason: null,
sharedWithLabs: false,
sharedAt: null,
consentVersion: null,
redactionSummary: null,
createdAt: new Date("2026-04-06T12:01:00.000Z"),
updatedAt: new Date("2026-04-06T12:01:00.000Z"),
}]}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(markdownBodyRenderMock).not.toHaveBeenCalled();
act(() => {
root.unmount();
});
});
it("shows explicit follow-up badges and event copy", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[{
id: "comment-1",
companyId: "company-1",
issueId: "issue-1",
authorAgentId: null,
authorUserId: "local-board",
body: "Please continue validation.",
followUpRequested: true,
createdAt: new Date("2026-03-11T10:00:00.000Z"),
updatedAt: new Date("2026-03-11T10:00:00.000Z"),
}]}
linkedRuns={[]}
timelineEvents={[{
id: "event-1",
actorType: "agent",
actorId: "agent-1",
createdAt: new Date("2026-03-11T10:00:00.000Z"),
commentId: "comment-1",
followUpRequested: true,
}]}
liveRuns={[]}
onAdd={async () => {}}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("Follow-up");
expect(container.textContent).toContain("requested follow-up");
act(() => {
root.unmount();
});
});
[codex] Polish issue board workflows (#4224) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Human operators supervise that work through issue lists, issue detail, comments, inbox groups, markdown references, and profile/activity surfaces > - The branch had many small UI fixes that improve the operator loop but do not need to ship with backend runtime migrations > - These changes belong together as board workflow polish because they affect scanning, navigation, issue context, comment state, and markdown clarity > - This pull request groups the UI-only slice so it can merge independently from runtime/backend changes > - The benefit is a clearer board experience with better issue context, steadier optimistic updates, and more predictable keyboard navigation ## What Changed - Improves issue properties, sub-issue actions, blocker chips, and issue list/detail refresh behavior. - Adds blocker context above the issue composer and stabilizes queued/interrupted comment UI state. - Improves markdown issue/GitHub link rendering and opens external markdown links in a new tab. - Adds inbox group keyboard navigation and fold/unfold support. - Polishes activity/avatar/profile/settings/workspace presentation details. ## Verification - `pnpm exec vitest run ui/src/components/IssueProperties.test.tsx ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownBody.test.tsx ui/src/lib/inbox.test.ts ui/src/lib/optimistic-issue-comments.test.ts` ## Risks - Low to medium risk: changes are UI-focused but cover high-traffic issue and inbox surfaces. - This branch intentionally does not include the backend runtime changes from the companion PR; where UI calls newer API filters, unsupported servers should continue to fail visibly through existing API error handling. - Visual screenshots were not captured in this heartbeat; targeted component/helper tests cover the changed behavior. > 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, GPT-5-based coding agent runtime, shell/git tool use enabled. Exact hosted model build and context window are not exposed in this Paperclip heartbeat environment. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge
2026-04-21 12:25:34 -05:00
it("shows unresolved blocker context above the composer", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
issueStatus="todo"
blockedBy={[
{
id: "blocker-1",
identifier: "PAP-1723",
title: "QA the install flow",
status: "blocked",
priority: "medium",
assigneeAgentId: "agent-1",
assigneeUserId: null,
},
]}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("Work on this issue is blocked by the linked issue");
expect(container.textContent).toContain("Comments still wake the assignee for questions or triage");
expect(container.textContent).toContain("PAP-1723");
expect(container.textContent).toContain("QA the install flow");
expect(container.querySelector('[data-issue-path-id="PAP-1723"]')).not.toBeNull();
act(() => {
root.unmount();
});
});
it("shows terminal blocker context when an immediate blocker is transitively blocked", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
issueStatus="blocked"
blockedBy={[
{
id: "blocker-1",
identifier: "PAP-2167",
title: "Phase 7 review",
status: "blocked",
priority: "medium",
assigneeAgentId: "agent-1",
assigneeUserId: null,
terminalBlockers: [
{
id: "terminal-1",
identifier: "PAP-2201",
title: "Security sign-off",
status: "todo",
priority: "high",
assigneeAgentId: "agent-2",
assigneeUserId: null,
},
],
},
]}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("PAP-2167");
expect(container.textContent).toContain("Phase 7 review");
expect(container.textContent).toContain("Ultimately waiting on");
expect(container.textContent).toContain("PAP-2201");
expect(container.textContent).toContain("Security sign-off");
expect(container.querySelector('[data-issue-path-id="PAP-2201"]')).not.toBeNull();
act(() => {
root.unmount();
});
});
[codex] Polish issue board workflows (#4224) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Human operators supervise that work through issue lists, issue detail, comments, inbox groups, markdown references, and profile/activity surfaces > - The branch had many small UI fixes that improve the operator loop but do not need to ship with backend runtime migrations > - These changes belong together as board workflow polish because they affect scanning, navigation, issue context, comment state, and markdown clarity > - This pull request groups the UI-only slice so it can merge independently from runtime/backend changes > - The benefit is a clearer board experience with better issue context, steadier optimistic updates, and more predictable keyboard navigation ## What Changed - Improves issue properties, sub-issue actions, blocker chips, and issue list/detail refresh behavior. - Adds blocker context above the issue composer and stabilizes queued/interrupted comment UI state. - Improves markdown issue/GitHub link rendering and opens external markdown links in a new tab. - Adds inbox group keyboard navigation and fold/unfold support. - Polishes activity/avatar/profile/settings/workspace presentation details. ## Verification - `pnpm exec vitest run ui/src/components/IssueProperties.test.tsx ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownBody.test.tsx ui/src/lib/inbox.test.ts ui/src/lib/optimistic-issue-comments.test.ts` ## Risks - Low to medium risk: changes are UI-focused but cover high-traffic issue and inbox surfaces. - This branch intentionally does not include the backend runtime changes from the companion PR; where UI calls newer API filters, unsupported servers should continue to fail visibly through existing API error handling. - Visual screenshots were not captured in this heartbeat; targeted component/helper tests cover the changed behavior. > 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, GPT-5-based coding agent runtime, shell/git tool use enabled. Exact hosted model build and context window are not exposed in this Paperclip heartbeat environment. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge
2026-04-21 12:25:34 -05:00
it("shows paused assigned agent context above the composer", () => {
const root = createRoot(container);
const pausedAgent = {
id: "agent-1",
companyId: "company-1",
name: "CodexCoder",
status: "paused",
pauseReason: "manual",
} as Agent;
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
agentMap={new Map([["agent-1", pausedAgent]])}
currentAssigneeValue="agent:agent-1"
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("CodexCoder is paused");
expect(container.textContent).toContain("New runs will not start until the agent is resumed");
expect(container.textContent).toContain("It was paused manually");
act(() => {
root.unmount();
});
});
it("supports the embedded read-only variant without the jump control", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
showComposer={false}
showJumpToLatest={false}
variant="embedded"
emptyMessage="No run output captured."
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("No run output captured.");
expect(container.textContent).not.toContain("Jump to latest");
const viewport = container.querySelector('[data-testid="thread-viewport"]') as HTMLDivElement | null;
expect(viewport?.className).toContain("space-y-3");
act(() => {
root.unmount();
});
});
[codex] Add structured issue-thread interactions (#4244) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies. > - Operators supervise that work through issues, comments, approvals, and the board UI. > - Some agent proposals need structured board/user decisions, not hidden markdown conventions or heavyweight governed approvals. > - Issue-thread interactions already provide a natural thread-native surface for proposed tasks and questions. > - This pull request extends that surface with request confirmations, richer interaction cards, and agent/plugin/MCP helpers. > - The benefit is that plan approvals and yes/no decisions become explicit, auditable, and resumable without losing the single-issue workflow. ## What Changed - Added persisted issue-thread interactions for suggested tasks, structured questions, and request confirmations. - Added board UI cards for interaction review, selection, question answers, and accept/reject confirmation flows. - Added MCP and plugin SDK helpers for creating interaction cards from agents/plugins. - Updated agent wake instructions, onboarding assets, Paperclip skill docs, and public docs to prefer structured confirmations for issue-scoped decisions. - Rebased the branch onto `public-gh/master` and renumbered branch migrations to `0063` and `0064`; the idempotency migration uses `ADD COLUMN IF NOT EXISTS` for old branch users. ## Verification - `git diff --check public-gh/master..HEAD` - `pnpm exec vitest run packages/adapter-utils/src/server-utils.test.ts packages/mcp-server/src/tools.test.ts packages/shared/src/issue-thread-interactions.test.ts ui/src/lib/issue-thread-interactions.test.ts ui/src/lib/issue-chat-messages.test.ts ui/src/components/IssueThreadInteractionCard.test.tsx ui/src/components/IssueChatThread.test.tsx server/src/__tests__/issue-thread-interaction-routes.test.ts server/src/__tests__/issue-thread-interactions-service.test.ts server/src/services/issue-thread-interactions.test.ts` -> 9 files / 79 tests passed - `pnpm -r typecheck` -> passed, including `packages/db` migration numbering check ## Risks - Medium: this adds a new issue-thread interaction model across db/shared/server/ui/plugin surfaces. - Migration risk is reduced by placing this branch after current master migrations (`0063`, `0064`) and making the idempotency column add idempotent for users who applied the old branch numbering. - UI interaction behavior is covered by component tests, but this PR does not include browser screenshots. > 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, GPT-5-class coding agent runtime. Exact model ID and context window are not exposed in this Paperclip run; tool use and local shell/code execution were enabled. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-21 20:15:11 -05:00
it("invokes the accept callback for pending suggested-task interactions", async () => {
const root = createRoot(container);
const onAcceptInteraction = vi.fn(async () => undefined);
await act(async () => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
interactions={[createSuggestedTasksInteraction()]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
onAcceptInteraction={onAcceptInteraction}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const acceptButton = Array.from(container.querySelectorAll("button")).find((button) =>
button.textContent?.includes("Accept drafts"),
);
expect(acceptButton).toBeTruthy();
await act(async () => {
acceptButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(onAcceptInteraction).toHaveBeenCalledWith(
expect.objectContaining({
id: "interaction-suggest-1",
kind: "suggest_tasks",
}),
["task-1"],
);
act(() => {
root.unmount();
});
});
it("submits only the selected draft subtree when tasks are manually pruned", async () => {
const root = createRoot(container);
const onAcceptInteraction = vi.fn(async () => undefined);
await act(async () => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
interactions={[createSuggestedTasksInteraction({
payload: {
version: 1,
tasks: [
{
clientKey: "root",
title: "Root task",
},
{
clientKey: "child",
parentClientKey: "root",
title: "Child task",
},
],
},
})]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
onAcceptInteraction={onAcceptInteraction}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const childCheckbox = container.querySelector('[aria-label="Include Child task"]');
expect(childCheckbox).toBeTruthy();
await act(async () => {
childCheckbox?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
const acceptButton = Array.from(container.querySelectorAll("button")).find((button) =>
button.textContent?.includes("Accept selected drafts"),
);
expect(acceptButton).toBeTruthy();
await act(async () => {
acceptButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(onAcceptInteraction).toHaveBeenCalledWith(
expect.objectContaining({
id: "interaction-suggest-1",
kind: "suggest_tasks",
}),
["root"],
);
act(() => {
root.unmount();
});
});
it("submits selected answers for pending question interactions", async () => {
const root = createRoot(container);
const onSubmitInteractionAnswers = vi.fn(async () => undefined);
await act(async () => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
interactions={[createQuestionInteraction()]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
onSubmitInteractionAnswers={onSubmitInteractionAnswers}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const optionButton = Array.from(container.querySelectorAll("button")).find((button) =>
button.textContent?.includes("Phase 1"),
);
const submitButton = Array.from(container.querySelectorAll("button")).find((button) =>
button.textContent?.includes("Submit answers"),
);
expect(optionButton).toBeTruthy();
expect(submitButton).toBeTruthy();
await act(async () => {
optionButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
await act(async () => {
submitButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(onSubmitInteractionAnswers).toHaveBeenCalledWith(
expect.objectContaining({
id: "interaction-question-1",
kind: "ask_user_questions",
}),
[{ questionId: "scope", optionIds: ["phase-1"] }],
);
act(() => {
root.unmount();
});
});
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
it("folds expired request confirmations into an activity row by default", async () => {
const root = createRoot(container);
await act(async () => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
interactions={[createExpiredRequestConfirmationInteraction()]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
currentUserId="user-1"
userLabelMap={new Map([["user-1", "Dotta"]])}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("Dotta");
expect(container.textContent).toContain("updated this task");
expect(container.textContent).toContain("Expired confirmation");
expect(container.textContent).not.toContain("Approve the plan");
const toggleButton = Array.from(container.querySelectorAll("button")).find((button) =>
button.textContent?.includes("Expired confirmation"),
);
expect(toggleButton).toBeTruthy();
await act(async () => {
toggleButton?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
});
expect(container.textContent).toContain("Approve the plan");
expect(container.textContent).toContain("Confirmation expired after comment");
act(() => {
root.unmount();
});
});
[codex] Polish issue and operator workflow UI (#4090) ## Thinking Path > - Paperclip operators spend much of their time in issues, inboxes, selectors, and rich comment threads. > - Small interaction problems in those surfaces slow down supervision of AI-agent work. > - The branch included related operator quality-of-life fixes for issue layout, inbox actions, recent selectors, mobile inputs, and chat rendering stability. > - These changes are UI-focused and can land independently from workspace navigation and access-profile work. > - This pull request groups the operator QoL fixes into one standalone branch. > - The benefit is a more stable and efficient board workflow for issue triage and task editing. ## What Changed - Widened issue detail content and added a desktop inbox archive action. - Fixed mobile text-field zoom by keeping touch input font sizes at 16px. - Prioritized recent picker selections for assignees/projects in issue and routine flows. - Showed actionable approvals in the Mine inbox model. - Fixed issue chat renderer state crashes and hardened tests. ## Verification - `pnpm install --frozen-lockfile` - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/lib/inbox.test.ts ui/src/lib/recent-selections.test.ts` - Split integration check: merged last after the other [PAP-1614](/PAP/issues/PAP-1614) branches with no merge conflicts. - Confirmed this branch does not include `pnpm-lock.yaml`. ## Risks - Low to medium risk: mostly UI state, layout, and selection-priority behavior. - Visual layout and mobile zoom behavior may need browser/device QA beyond component tests. - No database migrations are included. > 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, GPT-5.4 tool-enabled coding model, agentic code-editing/runtime with local shell and GitHub CLI access; exact context window and reasoning mode are not exposed by the Paperclip harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-20 06:16:41 -05:00
it("renders the transcript directly from stable Paperclip messages", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[{
id: "comment-1",
companyId: "company-1",
issueId: "issue-1",
authorAgentId: "agent-1",
authorUserId: null,
body: "Agent summary",
createdAt: new Date("2026-04-06T12:00:00.000Z"),
updatedAt: new Date("2026-04-06T12:00:00.000Z"),
}]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("Agent summary");
[codex] Polish issue and operator workflow UI (#4090) ## Thinking Path > - Paperclip operators spend much of their time in issues, inboxes, selectors, and rich comment threads. > - Small interaction problems in those surfaces slow down supervision of AI-agent work. > - The branch included related operator quality-of-life fixes for issue layout, inbox actions, recent selectors, mobile inputs, and chat rendering stability. > - These changes are UI-focused and can land independently from workspace navigation and access-profile work. > - This pull request groups the operator QoL fixes into one standalone branch. > - The benefit is a more stable and efficient board workflow for issue triage and task editing. ## What Changed - Widened issue detail content and added a desktop inbox archive action. - Fixed mobile text-field zoom by keeping touch input font sizes at 16px. - Prioritized recent picker selections for assignees/projects in issue and routine flows. - Showed actionable approvals in the Mine inbox model. - Fixed issue chat renderer state crashes and hardened tests. ## Verification - `pnpm install --frozen-lockfile` - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/lib/inbox.test.ts ui/src/lib/recent-selections.test.ts` - Split integration check: merged last after the other [PAP-1614](/PAP/issues/PAP-1614) branches with no merge conflicts. - Confirmed this branch does not include `pnpm-lock.yaml`. ## Risks - Low to medium risk: mostly UI state, layout, and selection-priority behavior. - Visual layout and mobile zoom behavior may need browser/device QA beyond component tests. - No database migrations are included. > 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, GPT-5.4 tool-enabled coding model, agentic code-editing/runtime with local shell and GitHub CLI access; exact context window and reasoning mode are not exposed by the Paperclip harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-20 06:16:41 -05:00
expect(container.textContent).not.toContain("Chat renderer hit an internal state error.");
act(() => {
root.unmount();
});
});
[codex] Add issue subtree pause, cancel, and restore controls (#4332) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies. > - This branch extends the issue control-plane so board operators can pause, cancel, and later restore whole issue subtrees while keeping descendant execution and wake behavior coherent. > - That required new hold state in the database, shared contracts, server routes/services, and issue detail UI controls so subtree actions are durable and auditable instead of ad hoc. > - While this branch was in flight, `master` advanced with new environment lifecycle work, including a new `0065_environments` migration. > - Before opening the PR, this branch had to be rebased onto `paperclipai/paperclip:master` without losing the existing subtree-control work or leaving conflicting migration numbering behind. > - This pull request rebases the subtree pause/cancel/restore feature cleanly onto current `master`, renumbers the hold migration to `0066_issue_tree_holds`, and preserves the full branch diff in a single PR. > - The benefit is that reviewers get one clean, mergeable PR for the subtree-control feature instead of stale branch history with migration conflicts. ## What Changed - Added durable issue subtree hold data structures, shared API/types/validators, server routes/services, and UI flows for subtree pause, cancel, and restore operations. - Added server and UI coverage for subtree previewing, hold creation/release, dependency-aware scheduling under holds, and issue detail subtree controls. - Rebased the branch onto current `paperclipai/paperclip:master` and renumbered the branch migration from `0065_issue_tree_holds` to `0066_issue_tree_holds` so it no longer conflicts with upstream `0065_environments`. - Added a small follow-up commit that makes restore requests return `200 OK` explicitly while keeping pause/cancel hold creation at `201 Created`, and updated the route test to match that contract. ## Verification - `pnpm --filter @paperclipai/db typecheck` - `pnpm --filter @paperclipai/shared typecheck` - `pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/ui typecheck` - `cd server && pnpm exec vitest run src/__tests__/issue-tree-control-routes.test.ts src/__tests__/issue-tree-control-service.test.ts src/__tests__/issue-tree-control-service-unit.test.ts src/__tests__/heartbeat-dependency-scheduling.test.ts` - `cd ui && pnpm exec vitest run src/components/IssueChatThread.test.tsx src/pages/IssueDetail.test.tsx` ## Risks - This is a broad cross-layer change touching DB/schema, shared contracts, server orchestration, and UI; regressions are most likely around subtree status restoration or wake suppression/resume edge cases. - The migration was renumbered during PR prep to avoid the new upstream `0065_environments` conflict. Reviewers should confirm the final `0066_issue_tree_holds` ordering is the only hold-related migration that lands. - The issue-tree restore endpoint now responds with `200` instead of relying on implicit behavior, which is semantically better for a restore operation but still changes an API detail that clients or tests could have assumed. > 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 coding agent in the Paperclip Codex runtime (GPT-5-class tool-using coding model; exact deployment ID/context window is not exposed inside 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-23 14:51:46 -05:00
it("shows deferred wake badge only for hold-deferred queued comments", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[{
id: "comment-hold",
companyId: "company-1",
issueId: "issue-1",
authorAgentId: null,
authorUserId: "user-1",
body: "Need a quick update",
queueState: "queued",
queueReason: "hold",
createdAt: new Date("2026-04-06T12:00:00.000Z"),
updatedAt: new Date("2026-04-06T12:00:00.000Z"),
}]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("Deferred wake");
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[{
id: "comment-active-run",
companyId: "company-1",
issueId: "issue-1",
authorAgentId: null,
authorUserId: "user-1",
body: "Queue behind active run",
queueState: "queued",
queueReason: "active_run",
createdAt: new Date("2026-04-06T12:01:00.000Z"),
updatedAt: new Date("2026-04-06T12:01:00.000Z"),
}]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("Queued");
expect(container.textContent).not.toContain("Deferred wake");
act(() => {
root.unmount();
});
});
it("stores and restores the composer draft per issue key", () => {
vi.useFakeTimers();
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
draftKey="issue-chat-draft:test-1"
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const editor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
expect(editor).not.toBeNull();
expect(editor?.placeholder).toBe("Reply");
act(() => {
const valueSetter = Object.getOwnPropertyDescriptor(
window.HTMLTextAreaElement.prototype,
"value",
)?.set;
valueSetter?.call(editor, "Draft survives refresh");
editor?.dispatchEvent(new Event("input", { bubbles: true }));
});
act(() => {
vi.advanceTimersByTime(900);
});
expect(localStorage.getItem("issue-chat-draft:test-1")).toBe("Draft survives refresh");
act(() => {
root.unmount();
});
const remount = createRoot(container);
act(() => {
remount.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
draftKey="issue-chat-draft:test-1"
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const restoredEditor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
expect(restoredEditor?.value).toBe("Draft survives refresh");
act(() => {
remount.unmount();
});
});
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
it("keeps the composer floating with a capped editor height", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
const dock = container.querySelector('[data-testid="issue-chat-composer-dock"]') as HTMLDivElement | null;
expect(dock).not.toBeNull();
expect(dock?.className).toContain("sticky");
expect(dock?.className).toContain("bottom-[calc(env(safe-area-inset-bottom)+20px)]");
expect(dock?.className).toContain("z-20");
const composer = container.querySelector('[data-testid="issue-chat-composer"]') as HTMLDivElement | null;
expect(composer).not.toBeNull();
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
expect(composer?.className).toContain("rounded-md");
expect(composer?.className).not.toContain("rounded-lg");
expect(composer?.className).toContain("p-[15px]");
const editor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
2026-04-08 09:51:45 -05:00
expect(editor?.dataset.contentClassName).toContain("max-h-[28dvh]");
expect(editor?.dataset.contentClassName).toContain("overflow-y-auto");
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
expect(editor?.dataset.contentClassName).not.toContain("min-h-[72px]");
[codex] Polish issue composer and long document display (#4420) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue comments and documents are the main working surface where operators and agents collaborate > - File drops, markdown editing, and long issue descriptions need to feel predictable because they sit directly in the task execution loop > - The composer had edge cases around drag targets, attachment feedback, image drops, and long markdown content crowding the page > - This pull request polishes the issue composer, hardens markdown editor regressions, and adds a fold curtain for long issue descriptions/documents > - The benefit is a calmer issue detail surface that handles uploads and long work products without hiding state or breaking layout ## What Changed - Scoped issue-composer drag/drop behavior so the composer owns file drops without turning the whole thread into a competing drop target. - Added clearer attachment upload feedback for non-image files and image-drop stability coverage. - Hardened markdown editor and markdown body handling around HTML-like tag regressions. - Added `FoldCurtain` and wired it into issue descriptions and issue documents so long markdown previews can expand/collapse. - Added Storybook coverage for the fold curtain state. ## Verification - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/MarkdownBody.test.tsx --config ui/vitest.config.ts` passed: 3 files, 75 tests. - `git diff --check public-gh/master..pap-2228-editor-composer-polish -- . ':(exclude)ui/storybook-static'` passed. - Confirmed this PR does not include `pnpm-lock.yaml`. ## Risks - Low-to-medium risk: this changes user-facing composer/drop behavior and long markdown display. - The fold curtain uses DOM measurement and `ResizeObserver`; reviewers should check browser behavior for very long descriptions and documents. - No database migrations. > 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 coding agent based on GPT-5, with shell, git, Paperclip API, and GitHub CLI tool use in the local Paperclip workspace. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note: screenshots were not newly captured during branch splitting; the UI states are covered by component tests and a Storybook story. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 14:12:41 -05:00
expect(editor?.dataset.fileDropTarget).toBe("parent");
act(() => {
root.unmount();
});
});
it("shows full-composer drop instructions while dragging files over the issue composer", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
imageUploadHandler={async () => "/api/attachments/image/content"}
onAttachImage={async () => undefined}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const composer = container.querySelector('[data-testid="issue-chat-composer"]') as HTMLDivElement | null;
expect(composer).not.toBeNull();
const fileInput = container.querySelector('input[type="file"]') as HTMLInputElement | null;
expect(fileInput?.getAttribute("accept")).toBeNull();
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
act(() => {
[codex] Polish issue composer and long document display (#4420) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue comments and documents are the main working surface where operators and agents collaborate > - File drops, markdown editing, and long issue descriptions need to feel predictable because they sit directly in the task execution loop > - The composer had edge cases around drag targets, attachment feedback, image drops, and long markdown content crowding the page > - This pull request polishes the issue composer, hardens markdown editor regressions, and adds a fold curtain for long issue descriptions/documents > - The benefit is a calmer issue detail surface that handles uploads and long work products without hiding state or breaking layout ## What Changed - Scoped issue-composer drag/drop behavior so the composer owns file drops without turning the whole thread into a competing drop target. - Added clearer attachment upload feedback for non-image files and image-drop stability coverage. - Hardened markdown editor and markdown body handling around HTML-like tag regressions. - Added `FoldCurtain` and wired it into issue descriptions and issue documents so long markdown previews can expand/collapse. - Added Storybook coverage for the fold curtain state. ## Verification - `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/MarkdownBody.test.tsx --config ui/vitest.config.ts` passed: 3 files, 75 tests. - `git diff --check public-gh/master..pap-2228-editor-composer-polish -- . ':(exclude)ui/storybook-static'` passed. - Confirmed this PR does not include `pnpm-lock.yaml`. ## Risks - Low-to-medium risk: this changes user-facing composer/drop behavior and long markdown display. - The fold curtain uses DOM measurement and `ResizeObserver`; reviewers should check browser behavior for very long descriptions and documents. - No database migrations. > 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 coding agent based on GPT-5, with shell, git, Paperclip API, and GitHub CLI tool use in the local Paperclip workspace. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note: screenshots were not newly captured during branch splitting; the UI states are covered by component tests and a Storybook story. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 14:12:41 -05:00
composer?.dispatchEvent(createFileDragEvent("dragenter", [
new File(["hello"], "notes.txt", { type: "text/plain" }),
]));
});
expect(container.querySelector('[data-testid="issue-chat-composer-drop-overlay"]')).not.toBeNull();
expect(container.textContent).toContain("Drop to upload");
expect(container.textContent).toContain("Images insert into the reply");
expect(container.textContent).toContain("Other files are added to this issue");
expect(composer?.className).toContain("border-primary/45");
act(() => {
root.unmount();
});
});
it("shows non-image attachment upload state in the composer after a drop", async () => {
const root = createRoot(container);
const onAttachImage = vi.fn(async (file: File) => ({
id: "attachment-1",
companyId: "company-1",
issueId: "issue-1",
issueCommentId: null,
assetId: "asset-1",
provider: "local_disk",
objectKey: "issues/issue-1/report.pdf",
contentPath: "/api/attachments/attachment-1/content",
originalFilename: file.name,
contentType: file.type,
byteSize: file.size,
sha256: "abc123",
createdByAgentId: null,
createdByUserId: "user-1",
createdAt: new Date("2026-04-24T12:00:00.000Z"),
updatedAt: new Date("2026-04-24T12:00:00.000Z"),
}));
await act(async () => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
onAttachImage={onAttachImage}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const composer = container.querySelector('[data-testid="issue-chat-composer"]') as HTMLDivElement | null;
const file = new File(["report body"], "report.pdf", { type: "application/pdf" });
await act(async () => {
composer?.dispatchEvent(createFileDragEvent("drop", [file]));
});
expect(onAttachImage).toHaveBeenCalledWith(file);
const attachmentList = container.querySelector('[data-testid="issue-chat-composer-attachments"]');
expect(attachmentList).not.toBeNull();
expect(container.textContent).toContain("report.pdf");
expect(container.textContent).toContain("Attached to issue");
await act(async () => {
root.unmount();
});
});
it("shows only the outer composer drop overlay when dragging over the reply editor", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
imageUploadHandler={async () => "/api/attachments/image/content"}
onAttachImage={async () => undefined}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const composer = container.querySelector('[data-testid="issue-chat-composer"]') as HTMLDivElement | null;
const editor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
expect(composer).not.toBeNull();
expect(editor).not.toBeNull();
act(() => {
editor?.dispatchEvent(createFileDragEvent("dragenter", [
new File(["hello"], "notes.txt", { type: "text/plain" }),
]));
});
expect(container.querySelector('[data-testid="issue-chat-composer-drop-overlay"]')).not.toBeNull();
expect(container.textContent).toContain("Drop to upload");
expect(container.textContent).not.toContain("Drop image to upload");
expect(composer?.className).toContain("border-primary/45");
const fileInput = container.querySelector('input[type="file"]') as HTMLInputElement | null;
expect(fileInput?.getAttribute("accept")).toBeNull();
act(() => {
root.unmount();
});
});
it("shows non-image attachment upload state in the composer after a drop from the editor", async () => {
const root = createRoot(container);
const onAttachImage = vi.fn(async (file: File) => ({
id: "attachment-1",
companyId: "company-1",
issueId: "issue-1",
issueCommentId: null,
assetId: "asset-1",
provider: "local_disk",
objectKey: "issues/issue-1/report.pdf",
contentPath: "/api/attachments/attachment-1/content",
originalFilename: file.name,
contentType: file.type,
byteSize: file.size,
sha256: "abc123",
createdByAgentId: null,
createdByUserId: "user-1",
createdAt: new Date("2026-04-24T12:00:00.000Z"),
updatedAt: new Date("2026-04-24T12:00:00.000Z"),
}));
await act(async () => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
onAttachImage={onAttachImage}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const editor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
const file = new File(["report body"], "report.pdf", { type: "application/pdf" });
await act(async () => {
editor?.dispatchEvent(createFileDragEvent("drop", [file]));
});
expect(onAttachImage).toHaveBeenCalledWith(file);
const attachmentList = container.querySelector('[data-testid="issue-chat-composer-attachments"]');
expect(attachmentList).not.toBeNull();
expect(attachmentList?.className).toContain("mb-3");
expect(container.textContent).toContain("report.pdf");
expect(container.textContent).toContain("Attached to issue");
await act(async () => {
[codex] Improve issue thread review flow (#4381) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - Issue detail is where operators coordinate review, approvals, and follow-up work with active runs > - That thread UI needs to surface blockers, descendants, review handoffs, and reply ergonomics clearly enough for humans to guide agent work > - Several small gaps in the issue-thread flow were making review and navigation clunkier than necessary > - This pull request improves the reply composer, descendant/blocker presentation, interaction folding, and review-request handoff plumbing together as one cohesive issue-thread workflow slice > - The benefit is a cleaner operator review loop without changing the broader task model ## What Changed - restored and refined the floating reply composer behavior in the issue thread - folded expired confirmation interactions and improved post-submit thread scrolling behavior - surfaced descendant issue context and inline blocker/paused-assignee notices on the issue detail view - tightened large-board first paint behavior in `IssuesList` - added loose review-request handoffs through the issue execution-policy/update path and covered them with tests ## Verification - `pnpm vitest run ui/src/pages/IssueDetail.test.tsx` - `pnpm vitest run server/src/__tests__/issues-service.test.ts server/src/__tests__/issue-execution-policy.test.ts` - `pnpm exec vitest run --project @paperclipai/ui ui/src/components/IssueChatThread.test.tsx ui/src/components/IssueProperties.test.tsx ui/src/components/IssuesList.test.tsx ui/src/lib/issue-tree.test.ts ui/src/api/issues.test.ts` - `pnpm exec vitest run --project @paperclipai/adapter-utils packages/adapter-utils/src/server-utils.test.ts` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-comment-reopen-routes.test.ts -t "coerces executor handoff patches into workflow-controlled review wakes|wakes the return assignee with execution_changes_requested"` - `pnpm exec vitest run --project @paperclipai/server server/src/__tests__/issue-execution-policy.test.ts server/src/__tests__/issues-service.test.ts` ## Visual Evidence - UI layout changes are covered by the focused issue-thread component and issue-detail tests listed above. Browser screenshots were not attachable from this automated greploop environment, so reviewers should use the running preview for final visual confirmation. ## Risks - Moderate UI-flow risk: these changes touch the issue detail experience in multiple spots, so regressions would most likely show up as thread-layout quirks or incorrect review-handoff behavior > 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 GPT-5-based coding agent with tool use and code execution in the Codex CLI environment ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots or documented the visual verification path - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-24 08:02:45 -05:00
root.unmount();
});
});
it("renders the bottom spacer with zero height until the user has submitted", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[{
id: "comment-spacer-1",
companyId: "company-1",
issueId: "issue-1",
authorAgentId: null,
authorUserId: "user-1",
body: "hello",
createdAt: new Date("2026-04-22T12:00:00.000Z"),
updatedAt: new Date("2026-04-22T12:00:00.000Z"),
}]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const spacer = container.querySelector('[data-testid="issue-chat-bottom-spacer"]') as HTMLDivElement | null;
expect(spacer).not.toBeNull();
expect(spacer?.style.height).toBe("0px");
act(() => {
root.unmount();
});
});
it("omits the bottom spacer when the composer is hidden", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
showComposer={false}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const spacer = container.querySelector('[data-testid="issue-chat-bottom-spacer"]');
expect(spacer).toBeNull();
act(() => {
root.unmount();
});
});
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
it("hides the reopen control and infers reopen for closed agent-assigned issue replies", async () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
issueStatus="done"
currentAssigneeValue="agent:agent-1"
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).not.toContain("Re-open");
const editor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
const submitButton = Array.from(container.querySelectorAll("button")).find(
(element) => element.textContent === "Send",
) as HTMLButtonElement | undefined;
expect(editor).not.toBeNull();
expect(submitButton).toBeDefined();
act(() => {
const valueSetter = Object.getOwnPropertyDescriptor(
window.HTMLTextAreaElement.prototype,
"value",
)?.set;
valueSetter?.call(editor, "Please pick this back up");
editor?.dispatchEvent(new Event("input", { bubbles: true }));
});
await act(async () => {
submitButton?.click();
});
expect(appendMock).toHaveBeenCalledWith(
expect.objectContaining({
content: [{ type: "text", text: "Please pick this back up" }],
runConfig: {
custom: {
reopen: true,
},
},
}),
);
act(() => {
root.unmount();
});
});
[codex] Split PR #4692 UI/QoL updates (#4701) ## Thinking Path > - Paperclip orchestrates AI agents through a company-scoped control plane. > - The affected surface is the board UI for issue threads, issue lists, routines, dialogs, navigation, and issue review indicators. > - Closed PR #4692 bundled backend, schema, docs, workflow, and UI/QoL work into one oversized change set. > - Greptile could not keep reviewing that broad PR because it exceeded the 100-file review limit and mixed unrelated concerns. > - This pull request extracts the UI/QoL slice into a fresh branch under the review limit while leaving workflow and lockfile churn out. > - The benefit is a focused review path for the board UI performance and workflow improvements without reopening the oversized PR. ## What Changed - Added long issue-thread virtualization, scroll-container binding, anchor preservation, latest-comment jump targeting, and related regression/perf fixtures. - Improved issue list scalability with scroll-based loading, server offset parameters, and pagination-focused UI tests. - Reduced new issue dialog typing churn and split dialog action subscriptions so broad layout/nav surfaces avoid unnecessary renders. - Added routine variables help and routine description mention options for users, agents, and projects. - Added productivity review badge/link UI and fixed the badge to use Paperclip's company-prefixed router link. - Kept the split PR below Greptile's review limit and excluded `.github/workflows/pr.yml` and `pnpm-lock.yaml`. ## Verification - `pnpm install --no-frozen-lockfile` in the clean worktree to install `@tanstack/react-virtual` locally without committing lockfile churn. - `pnpm --filter @paperclipai/ui exec vitest run --config vitest.config.ts src/components/IssueChatThread.test.tsx src/components/IssuesList.test.tsx src/components/NewIssueDialog.test.tsx src/pages/Routines.test.tsx src/pages/Issues.test.tsx` passed: 5 files, 83 tests. - `pnpm --filter @paperclipai/ui typecheck` passed. - `git diff --check origin/master..HEAD` passed. - Split-scope checks: 53 changed files; no `.github/workflows/pr.yml`; no `pnpm-lock.yaml`. - Screenshots were not captured in this heartbeat; the changes are primarily virtualization, routing, pagination, and editor behavior covered by focused regression tests. ## Risks - Moderate UI risk because issue-thread virtualization changes scroll behavior on long conversations; regression tests cover anchor jumps, latest-comment targeting, row metadata, and short-thread fallback. - Moderate integration risk because the issue-list offset parameter and productivity review field depend on matching API behavior. - Dependency risk: the UI package adds `@tanstack/react-virtual` while repository policy keeps `pnpm-lock.yaml` out of PRs, so CI must resolve dependency changes through the repo's normal lockfile policy. > 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, GPT-5 coding agent, tool-enabled local repository and GitHub workflow. Exact runtime context window was not exposed by the harness. ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-28 17:18:58 -05:00
it("warns once before sending a reply with no assignee selected", async () => {
const root = createRoot(container);
act(() => {
root.render(
<ToastProvider>
<ToastViewport />
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
enableReassign
reassignOptions={[
{ id: "", label: "No assignee" },
{ id: "agent:agent-1", label: "Agent 1" },
]}
currentAssigneeValue=""
suggestedAssigneeValue=""
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>
</ToastProvider>,
);
});
const editor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
const submitButton = Array.from(container.querySelectorAll("button")).find(
(element) => element.textContent === "Send",
) as HTMLButtonElement | undefined;
expect(editor).not.toBeNull();
expect(submitButton).toBeDefined();
act(() => {
const valueSetter = Object.getOwnPropertyDescriptor(
window.HTMLTextAreaElement.prototype,
"value",
)?.set;
valueSetter?.call(editor, "Reply without assignee");
editor?.dispatchEvent(new Event("input", { bubbles: true }));
});
await act(async () => {
submitButton?.click();
});
expect(appendMock).not.toHaveBeenCalled();
expect(document.body.textContent).toContain("No assignee selected");
await act(async () => {
submitButton?.click();
});
expect(appendMock).toHaveBeenCalledTimes(1);
expect(appendMock).toHaveBeenCalledWith(
expect.objectContaining({
content: [{ type: "text", text: "Reply without assignee" }],
}),
);
act(() => {
root.unmount();
});
});
it("does not warn when sending a reply with an assignee selected", async () => {
const root = createRoot(container);
act(() => {
root.render(
<ToastProvider>
<ToastViewport />
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
enableReassign
reassignOptions={[
{ id: "", label: "No assignee" },
{ id: "agent:agent-1", label: "Agent 1" },
]}
currentAssigneeValue="agent:agent-1"
suggestedAssigneeValue="agent:agent-1"
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>
</ToastProvider>,
);
});
const editor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
const submitButton = Array.from(container.querySelectorAll("button")).find(
(element) => element.textContent === "Send",
) as HTMLButtonElement | undefined;
act(() => {
const valueSetter = Object.getOwnPropertyDescriptor(
window.HTMLTextAreaElement.prototype,
"value",
)?.set;
valueSetter?.call(editor, "Reply with assignee");
editor?.dispatchEvent(new Event("input", { bubbles: true }));
});
await act(async () => {
submitButton?.click();
});
expect(appendMock).toHaveBeenCalledTimes(1);
expect(document.body.textContent).not.toContain("No assignee selected");
act(() => {
root.unmount();
});
});
it("exposes a composer focus handle that forwards to the editor", () => {
const root = createRoot(container);
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
const composerRef = createRef<{ focus: () => void; restoreDraft: (submittedBody: string) => void }>();
const scrollByMock = vi.spyOn(window, "scrollBy").mockImplementation(() => {});
const requestAnimationFrameMock = vi
.spyOn(window, "requestAnimationFrame")
.mockImplementation((callback: FrameRequestCallback) => {
callback(0);
return 1;
});
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
composerRef={composerRef}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const composer = container.querySelector('[data-testid="issue-chat-composer"]') as HTMLDivElement | null;
expect(composerRef.current).not.toBeNull();
expect(composer).not.toBeNull();
const scrollIntoViewMock = vi.fn();
composer!.scrollIntoView = scrollIntoViewMock;
act(() => {
composerRef.current?.focus();
});
expect(scrollIntoViewMock).toHaveBeenCalledWith({ behavior: "smooth", block: "end" });
expect(scrollByMock).toHaveBeenCalledWith({ top: 96, behavior: "smooth" });
expect(markdownEditorFocusMock).toHaveBeenCalledTimes(1);
scrollByMock.mockRestore();
requestAnimationFrameMock.mockRestore();
act(() => {
root.unmount();
});
});
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
it("restores a cancelled queued draft into the composer handle", () => {
const root = createRoot(container);
const composerRef = createRef<{ focus: () => void; restoreDraft: (submittedBody: string) => void }>();
const scrollByMock = vi.spyOn(window, "scrollBy").mockImplementation(() => {});
const requestAnimationFrameMock = vi
.spyOn(window, "requestAnimationFrame")
.mockImplementation((callback: FrameRequestCallback) => {
callback(0);
return 1;
});
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
composerRef={composerRef}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
const editor = container.querySelector('textarea[aria-label="Issue chat editor"]') as HTMLTextAreaElement | null;
expect(editor).not.toBeNull();
act(() => {
composerRef.current?.restoreDraft("Queued message");
});
expect(editor?.value).toBe("Queued message");
expect(markdownEditorFocusMock).toHaveBeenCalledTimes(1);
expect(scrollByMock).toHaveBeenCalledWith({ top: 96, behavior: "smooth" });
scrollByMock.mockRestore();
requestAnimationFrameMock.mockRestore();
act(() => {
root.unmount();
});
});
it("does not restore the composer viewport for passive live updates by default", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[{
id: "run-1",
issueId: "issue-1",
status: "running",
invocationSource: "comment",
triggerDetail: null,
startedAt: "2026-04-06T12:00:00.000Z",
finishedAt: null,
createdAt: "2026-04-06T12:00:00.000Z",
agentId: "agent-1",
agentName: "Agent 1",
adapterType: "codex_local",
}]}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(restoreComposerViewportSnapshotMock).not.toHaveBeenCalled();
act(() => {
root.unmount();
});
});
it("requests composer viewport restoration when live messages arrive during active composer interaction", () => {
const root = createRoot(container);
const scrollByMock = vi.spyOn(window, "scrollBy").mockImplementation(() => {});
shouldPreserveComposerViewportMock.mockReturnValue(true);
captureComposerViewportSnapshotMock.mockReturnValue({ composerViewportTop: 420 });
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[]}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[{
id: "run-1",
issueId: "issue-1",
status: "running",
invocationSource: "comment",
triggerDetail: null,
startedAt: "2026-04-06T12:00:00.000Z",
finishedAt: null,
createdAt: "2026-04-06T12:00:00.000Z",
agentId: "agent-1",
agentName: "Agent 1",
adapterType: "codex_local",
}]}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(restoreComposerViewportSnapshotMock).toHaveBeenCalled();
scrollByMock.mockRestore();
act(() => {
root.unmount();
});
});
it("keeps a running chain-of-thought in the Working state between commands", () => {
const root = createRoot(container);
act(() => {
root.render(
<MemoryRouter>
<IssueChatThread
comments={[]}
linkedRuns={[]}
timelineEvents={[]}
liveRuns={[{
id: "run-1",
issueId: "issue-1",
status: "running",
invocationSource: "comment",
triggerDetail: null,
startedAt: "2026-04-06T12:00:00.000Z",
finishedAt: null,
createdAt: "2026-04-06T12:00:00.000Z",
agentId: "agent-1",
agentName: "Agent 1",
adapterType: "codex_local",
}]}
transcriptsByRunId={new Map([
[
"run-1",
[
{
kind: "tool_call",
ts: "2026-04-06T12:00:10.000Z",
name: "command_execution",
toolUseId: "tool-1",
input: { command: "pnpm test" },
},
{
kind: "tool_result",
ts: "2026-04-06T12:00:20.000Z",
toolUseId: "tool-1",
toolName: "command_execution",
content: "Tests passed",
isError: false,
},
],
],
])}
onAdd={async () => {}}
enableLiveTranscriptPolling={false}
/>
</MemoryRouter>,
);
});
expect(container.textContent).toContain("Working");
expect(container.textContent).not.toContain("Worked");
act(() => {
root.unmount();
});
});
it("folds chain-of-thought when the same message transitions from running to complete", () => {
expect(resolveAssistantMessageFoldedState({
messageId: "message-1",
currentFolded: false,
isFoldable: true,
previousMessageId: "message-1",
previousIsFoldable: false,
})).toBe(true);
});
it("preserves a manually opened completed message across rerenders", () => {
expect(resolveAssistantMessageFoldedState({
messageId: "message-1",
currentFolded: false,
isFoldable: true,
previousMessageId: "message-1",
previousIsFoldable: true,
})).toBe(false);
});
[codex] Improve issue detail and issue-list UX (#3678) ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - A core part of that is the operator experience around reading issue state, agent chat, and sub-task structure > - The current branch had a long run of issue-detail and issue-list UX fixes that all improve how humans follow and steer active work > - Those changes mostly live in the UI/chat surface and should be reviewed together instead of mixed with workspace/runtime work > - This pull request packages the issue-detail, chat, markdown, and sub-issue list improvements into one standalone change > - The benefit is a cleaner, less jumpy, more reliable issue workflow on desktop and mobile without coupling it to unrelated server/runtime refactors ## What Changed - Stabilized issue chat runtime wiring, optimistic comment handling, queued-comment cancellation, and composer anchoring during live updates - Fixed several issue-detail rendering and navigation regressions including placeholder bleed, local polling scope, mobile inbox-to-issue transitions, and visible refresh resets - Improved markdown and rich-content handling with advisory image normalization, editor fallback behavior, touch mention recovery, and `issue:` quicklook links - Refined sub-issue behavior with parent-derived defaults, current-user inheritance fixes, empty-state cleanup, and a reusable issue-list presentation for sub-issues - Added targeted UI tests for the new issue-detail, chat scroll/message, placeholder-data, markdown, and issue-list behaviors ## Verification - `pnpm vitest run ui/src/components/IssueChatThread.test.tsx ui/src/components/MarkdownEditor.test.tsx ui/src/components/IssuesList.test.tsx ui/src/context/LiveUpdatesProvider.test.tsx ui/src/lib/issue-chat-messages.test.ts ui/src/lib/issue-chat-scroll.test.ts ui/src/lib/issue-detail-subissues.test.ts ui/src/lib/query-placeholder-data.test.tsx ui/src/hooks/usePaperclipIssueRuntime.test.tsx` ## Risks - Medium: this branch touches the highest-traffic issue-detail UI paths, so regressions would show up as chat/thread or sub-issue UX glitches - The changes are UI-heavy and would benefit from reviewer screenshots or a quick manual browser pass before merge ## Model Used - OpenAI Codex coding agent (GPT-5-class runtime in Codex CLI; exact deployed model ID is not exposed in this environment), reasoning enabled, tool use and local code execution enabled ## 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-04-14 12:50:48 -05:00
it("shows the stop-run action for active run-linked messages even without embedded run status", () => {
expect(canStopIssueChatRun({
runId: "run-1",
runStatus: null,
activeRunIds: new Set(["run-1"]),
})).toBe(true);
});
it("hides the stop-run action for completed historical runs", () => {
expect(canStopIssueChatRun({
runId: "run-1",
runStatus: "cancelled",
activeRunIds: new Set<string>(),
})).toBe(false);
});
feat: implement multi-user access and invite flows (#3784) ## Thinking Path > - Paperclip is the control plane for autonomous AI companies. > - V1 needs to stay local-first while also supporting shared, authenticated deployments. > - Human operators need real identities, company membership, invite flows, profile surfaces, and company-scoped access controls. > - Agents and operators also need the existing issue, inbox, workspace, approval, and plugin flows to keep working under those authenticated boundaries. > - This branch accumulated the multi-user implementation, follow-up QA fixes, workspace/runtime refinements, invite UX improvements, release-branch conflict resolution, and review hardening. > - This pull request consolidates that branch onto the current `master` branch as a single reviewable PR. > - The benefit is a complete multi-user implementation path with tests and docs carried forward without dropping existing branch work. ## What Changed - Added authenticated human-user access surfaces: auth/session routes, company user directory, profile settings, company access/member management, join requests, and invite management. - Added invite creation, invite landing, onboarding, logo/branding, invite grants, deduped join requests, and authenticated multi-user E2E coverage. - Tightened company-scoped and instance-admin authorization across board, plugin, adapter, access, issue, and workspace routes. - Added profile-image URL validation hardening, avatar preservation on name-only profile updates, and join-request uniqueness migration cleanup for pending human requests. - Added an atomic member role/status/grants update path so Company Access saves no longer leave partially updated permissions. - Improved issue chat, inbox, assignee identity rendering, sidebar/account/company navigation, workspace routing, and execution workspace reuse behavior for multi-user operation. - Added and updated server/UI tests covering auth, invites, membership, issue workspace inheritance, plugin authz, inbox/chat behavior, and multi-user flows. - Merged current `public-gh/master` into this branch, resolved all conflicts, and verified no `pnpm-lock.yaml` change is included in this PR diff. ## Verification - `pnpm exec vitest run server/src/__tests__/issues-service.test.ts ui/src/components/IssueChatThread.test.tsx ui/src/pages/Inbox.test.tsx` - `pnpm run preflight:workspace-links && pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts` - `pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts server/src/__tests__/workspace-runtime-service-authz.test.ts server/src/__tests__/access-validators.test.ts` - `pnpm exec vitest run server/src/__tests__/authz-company-access.test.ts server/src/__tests__/routines-routes.test.ts server/src/__tests__/sidebar-preferences-routes.test.ts server/src/__tests__/approval-routes-idempotency.test.ts server/src/__tests__/openclaw-invite-prompt-route.test.ts server/src/__tests__/agent-cross-tenant-authz-routes.test.ts server/src/__tests__/routines-e2e.test.ts` - `pnpm exec vitest run server/src/__tests__/auth-routes.test.ts ui/src/pages/CompanyAccess.test.tsx` - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/db typecheck && pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/shared typecheck && pnpm --filter @paperclipai/server typecheck` - `pnpm --filter @paperclipai/ui typecheck` - `pnpm db:generate` - `npx playwright test --config tests/e2e/playwright.config.ts --list` - Confirmed branch has no uncommitted changes and is `0` commits behind `public-gh/master` before PR creation. - Confirmed no `pnpm-lock.yaml` change is staged or present in the PR diff. ## Risks - High review surface area: this PR contains the accumulated multi-user branch plus follow-up fixes, so reviewers should focus especially on company-boundary enforcement and authenticated-vs-local deployment behavior. - UI behavior changed across invites, inbox, issue chat, access settings, and sidebar navigation; no browser screenshots are included in this branch-consolidation PR. - Plugin install, upgrade, and lifecycle/config mutations now require instance-admin access, which is intentional but may change expectations for non-admin board users. - A join-request dedupe migration rejects duplicate pending human requests before creating unique indexes; deployments with unusual historical duplicates should review the migration behavior. - Company member role/status/grant saves now use a new combined endpoint; older separate endpoints remain for compatibility. - Full production build was not run locally in this heartbeat; CI should cover the full matrix. ## Model Used - OpenAI Codex coding agent, GPT-5-based model, CLI/tool-use environment. Exact deployed model identifier and context window were not exposed by the 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 run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge Note on screenshots: this is a branch-consolidation PR for an already-developed multi-user branch, and no browser screenshots were captured during this heartbeat. --------- Co-authored-by: dotta <dotta@example.com> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 09:44:19 -05:00
it("uses company profile data to distinguish the current user from other humans", () => {
const userProfileMap = new Map([
["user-1", { label: "Dotta", image: "/avatars/dotta.png" }],
["user-2", { label: "Alice", image: "/avatars/alice.png" }],
]);
expect(resolveIssueChatHumanAuthor({
authorName: "You",
authorUserId: "user-1",
currentUserId: "user-1",
userProfileMap,
})).toEqual({
isCurrentUser: true,
authorName: "Dotta",
avatarUrl: "/avatars/dotta.png",
});
expect(resolveIssueChatHumanAuthor({
authorName: "Alice",
authorUserId: "user-2",
currentUserId: "user-1",
userProfileMap,
})).toEqual({
isCurrentUser: false,
authorName: "Alice",
avatarUrl: "/avatars/alice.png",
});
});
});