2026-04-06 09:28:03 -05:00
|
|
|
// @vitest-environment jsdom
|
|
|
|
|
|
2026-04-08 09:24:32 -05:00
|
|
|
import { act, createRef, forwardRef, useImperativeHandle } from "react";
|
2026-04-06 09:28:03 -05:00
|
|
|
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,
|
|
|
|
|
canStopIssueChatRun,
|
|
|
|
|
resolveAssistantMessageFoldedState,
|
|
|
|
|
resolveIssueChatHumanAuthor,
|
|
|
|
|
} from "./IssueChatThread";
|
[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";
|
2026-04-06 09:28:03 -05:00
|
|
|
|
2026-04-08 09:24:32 -05:00
|
|
|
const { markdownEditorFocusMock } = vi.hoisted(() => ({
|
|
|
|
|
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(),
|
|
|
|
|
}));
|
|
|
|
|
|
2026-04-06 09:28:03 -05:00
|
|
|
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 }) }),
|
2026-04-06 09:28:03 -05:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
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),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-06 09:28:03 -05:00
|
|
|
vi.mock("./MarkdownBody", () => ({
|
|
|
|
|
MarkdownBody: ({ children }: { children: ReactNode }) => <div>{children}</div>,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
vi.mock("./MarkdownEditor", () => ({
|
2026-04-08 09:24:32 -05:00
|
|
|
MarkdownEditor: forwardRef(({
|
2026-04-06 11:00:12 -05:00
|
|
|
value = "",
|
|
|
|
|
onChange,
|
2026-04-06 11:43:45 -05:00
|
|
|
placeholder,
|
2026-04-08 09:11:21 -05:00
|
|
|
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,
|
2026-04-06 11:00:12 -05:00
|
|
|
}: {
|
|
|
|
|
value?: string;
|
|
|
|
|
onChange?: (value: string) => void;
|
2026-04-06 11:43:45 -05:00
|
|
|
placeholder?: string;
|
2026-04-08 09:11:21 -05:00
|
|
|
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";
|
2026-04-08 09:24:32 -05:00
|
|
|
}, 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}
|
2026-04-08 09:24:32 -05:00
|
|
|
placeholder={placeholder}
|
|
|
|
|
value={value}
|
|
|
|
|
onChange={(event) => onChange?.(event.target.value)}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}),
|
2026-04-06 09:28:03 -05:00
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
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}</>,
|
|
|
|
|
}));
|
|
|
|
|
|
2026-04-06 09:28:03 -05:00
|
|
|
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>
|
|
|
|
|
),
|
|
|
|
|
}));
|
|
|
|
|
|
2026-04-06 09:28:03 -05:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-06 09:28:03 -05:00
|
|
|
describe("IssueChatThread", () => {
|
|
|
|
|
let container: HTMLDivElement;
|
|
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
container = document.createElement("div");
|
|
|
|
|
document.body.appendChild(container);
|
2026-04-06 11:00:12 -05:00
|
|
|
localStorage.clear();
|
2026-04-06 09:28:03 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
container.remove();
|
2026-04-06 11:00:12 -05:00
|
|
|
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();
|
2026-04-08 09:24:32 -05:00
|
|
|
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();
|
2026-04-06 09:28:03 -05:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-06 11:00:12 -05:00
|
|
|
|
2026-04-24 15:50:32 -05:00
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-24 15:50:32 -05:00
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-07 18:17:29 -05:00
|
|
|
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", () => {
|
2026-04-08 17:14:02 -05:00
|
|
|
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.");
|
2026-04-08 17:14:02 -05:00
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-06 11:00:12 -05:00
|
|
|
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();
|
2026-04-06 11:43:45 -05:00
|
|
|
expect(editor?.placeholder).toBe("Reply");
|
2026-04-06 11:00:12 -05:00
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-07 17:02:48 -05:00
|
|
|
|
[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", () => {
|
2026-04-08 09:11:21 -05:00
|
|
|
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");
|
|
|
|
|
|
2026-04-08 09:11:21 -05:00
|
|
|
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]");
|
2026-04-08 09:11:21 -05:00
|
|
|
|
|
|
|
|
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]");
|
2026-04-08 09:11:21 -05:00
|
|
|
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();
|
2026-04-08 09:11:21 -05:00
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-08 09:24:32 -05:00
|
|
|
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 }>();
|
2026-04-08 16:41:13 -05:00
|
|
|
const scrollByMock = vi.spyOn(window, "scrollBy").mockImplementation(() => {});
|
2026-04-08 09:24:32 -05:00
|
|
|
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" });
|
2026-04-08 16:41:13 -05:00
|
|
|
expect(scrollByMock).toHaveBeenCalledWith({ top: 96, behavior: "smooth" });
|
2026-04-08 09:24:32 -05:00
|
|
|
expect(markdownEditorFocusMock).toHaveBeenCalledTimes(1);
|
2026-04-08 16:41:13 -05:00
|
|
|
scrollByMock.mockRestore();
|
2026-04-08 09:24:32 -05:00
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-24 15:50:32 -05:00
|
|
|
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();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2026-04-07 17:02:48 -05:00
|
|
|
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",
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-04-06 09:28:03 -05:00
|
|
|
});
|