Move child indentation from wrapper paddingLeft into desktopMetaLeading
so the unread dot stays in the leftmost column regardless of nesting
depth. When nesting is enabled, all issue rows get a fixed-width folding
column (chevron or empty spacer) for consistent alignment. Children
indent after the folding column. When nesting is disabled, no folding
column is rendered.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Builds a flat navigation list that includes expanded child issues alongside
top-level items, so j/k moves through every visible row including children.
Also adds the NavEntry type and updates archive/read/enter actions to work
with both top-level work items and nested child issues.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Adds a ListTree icon button in the inbox top bar to toggle nesting
on/off. Preference is persisted in localStorage. When disabled, all
issues display as a flat list without grouping.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Groups child issues under their parent in the inbox, matching the
nesting pattern used on the issues list page. Parent groups sort by
the most recent activity across all family members. Archived parents
don't hide their children — orphans show independently.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The handleChatImageClick useCallback (and its dependencies) was defined
after conditional early returns, violating React's rules of hooks and
causing "Rendered more hooks than during the previous render" crashes.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Clicking an image in a chat message now opens the same ImageGalleryModal
used by the attachments gallery. Matches by contentPath or assetId.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Rework the shimmer-text CSS to use a Cursor-style sweep: full-opacity base
with a narrow transparent highlight band that slides across, linear timing,
tighter background-size. Add a "Status tokens" section to the Issue Chat UX
Lab showing both the active shimmer "Working" state and the static "Worked"
state side-by-side for quick visual review.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
## Thinking Path
> - Paperclip orchestrates AI agents for zero-human companies
> - The issue detail page displays comment threads with rich timeline
rendering
> - Long threads (100+ items) cause severe typing lag in the comment
composer because every keystroke re-renders the entire timeline
> - CDP tracing confirmed 110ms avg key→paint latency and 60 long tasks
blocking the main thread for 3.7s total
> - This pull request memoizes the timeline, stabilizes callback props,
debounces editor observers, and reduces idle polling frequency
> - The benefit is responsive typing (21ms avg, 5.3× faster) even on
threads with 100+ timeline items
## What Changed
- **CommentThread.tsx**: Memoize `TimelineList` with `useMemo` so typing
state changes don't re-render 143 timeline items; extract
`handleFeedbackVote` to `useCallback`; added missing deps
(`pendingApprovalAction`, `onApproveApproval`, `onRejectApproval`) to
useMemo array
- **IssueDetail.tsx**: Extract inline callbacks (`handleCommentAdd`,
`handleCommentVote`, `handleCommentImageUpload`,
`handleCommentAttachImage`, `handleInterruptQueued`) to `useCallback`
with `.mutateAsync` deps (not full mutation objects) for stable
references; add conditional polling intervals (3s active / 30s idle) for
`liveRuns`, `activeRun`, `linkedRuns`, and timeline queries
- **MarkdownEditor.tsx**: Debounce `MutationObserver` and
`selectionchange` handlers via `requestAnimationFrame` coalescing
- **LiveRunWidget.tsx**: Accept optional `liveRunsData` and
`activeRunData` props to reuse parent-fetched data instead of duplicate
polling
## Verification
- Navigated to [IP address]:3105/PAPA/issues/PAPA-32 (thread with 100+
items)
- Typed in comment composer — lag eliminated, characters appear
instantly
- CDP trace test script (`test-typing-lag.mjs`) confirmed: avg 21ms
key→paint (was 110ms), 5 long tasks (was 60), 0.5s blocking (was 3.7s)
- Ran `pnpm test:run` locally — all tests pass
## Risks
- Low risk. All changes are additive memoization and callback
stabilization — no behavioral changes. Polling intervals are only
reduced for idle state; active runs still poll at 3–5s.
## Model Used
- Claude Opus 4.6 (`claude-opus-4-6`) via Claude Code CLI, with tool use
and extended context
## 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
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
Adds a "parent" column option to the inbox column toggle dropdown.
When enabled, sub-issues display the parent's identifier (e.g. PAP-123)
with the parent title as a tooltip. Uses the existing issueById lookup
map to resolve parent info without additional API calls.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- When no sub-issues exist, show "Add sub-issue" button alongside
"Upload attachment" and "New document" in the action row
- When sub-issues exist, show them in a dedicated section above
Documents with "Sub-issues" header and "Add sub-issue" button
- Remove the sub-issues tab from the comments/activity tabs
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Image attachments now render in a 4-column grid with square aspect ratio
and center-cropped thumbnails. Clicking opens the existing gallery modal.
Hover reveals a trash icon; clicking it shows an inline confirmation
overlay before deleting. Non-image attachments retain the original list
layout.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
On mobile, the search input, tab selector, and "Show / hide columns" button
were all crammed into one row causing horizontal overflow. Now:
- Search appears as a full-width row above the tabs on mobile
- "Show / hide columns" button is hidden on mobile (columns are desktop-only)
- Desktop layout is unchanged
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Add overflow-hidden to the outer container to prevent horizontal scroll
- Add min-w-0 to grid children so long monospace content in inputs
respects container width instead of expanding it
- Truncate the workspace name heading for long names
- Add min-w-0 to the header name container
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When unchecking the "Inherit project workspace runtime config" checkbox,
if the runtime config field is empty, automatically populate it with the
inherited config value so the user has a starting point to edit from.
Existing values are preserved and never overwritten.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Reduce card padding on small screens (p-4 → p-4 sm:p-5)
- Reduce spacing between sections on mobile (space-y-4 sm:space-y-6)
- Scale heading text (text-xl sm:text-2xl)
- Truncate long description on mobile, show full on sm+
- Reduce textarea min-heights on mobile (sm: prefix for larger sizes)
- Stack linked issue cards vertically on mobile, horizontal scroll on sm+
- Remove min-width constraint on linked issue cards on mobile
Co-Authored-By: Paperclip <noreply@paperclip.ing>
When dragging files like .zip onto the issue description editor, non-image
files are now uploaded as attachments instead of being silently ignored.
Images continue to be handled inline by MDXEditor's image plugin.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The archive mutation was only using CSS opacity to hide items while the
network request was in flight. When the query refetch completed or the
archiving timer expired, the item could reappear. Now we optimistically
remove the item from React Query caches on mutate, snapshot previous
data for rollback on error, and sync with the server in onSettled.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
fixes https://github.com/paperclipai/paperclip/issues/2336
## Thinking Path
<!--
Required. Trace your reasoning from the top of the project down to this
specific change. Start with what Paperclip is, then narrow through the
subsystem, the problem, and why this PR exists. Use blockquote style.
Aim for 5–8 steps. See CONTRIBUTING.md for full examples.
-->
- Paperclip allows to manage projects
- During the project creation you can optionally enter a description
- In the project overview or configuration you can edit the description
- However, you cannot remove the description
- The user should be able to remove the project description because it's
an optional property
- This pull request fixes the frontend bug that prevented the user to
remove/clear the project description
## What Changed
<!-- Bullet list of concrete changes. One bullet per logical unit. -->
- project description can be cleared in "project configuration" and
"project overview"
## Verification
<!--
How can a reviewer confirm this works? Include test commands, manual
steps, or both. For UI changes, include before/after screenshots.
-->
In project configuration or project overview:
- In the description field remove/clear the text
## Risks
<!--
What could go wrong? Mention migration safety, breaking changes,
behavioral shifts, or "Low risk" if genuinely minor.
-->
- none
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [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
Adds two new webhook trigger signing modes for external provider
compatibility:
- github_hmac: accepts X-Hub-Signature-256 header with
HMAC-SHA256(secret, rawBody), no timestamp prefix. Compatible with
GitHub, Sentry, and services following the same standard.
- none: no authentication; the 24-char hex publicId in the URL acts
as the shared secret. For services that cannot add auth headers.
The replay window UI field is hidden when these modes are selected
since neither uses timestamp-based replay protection.
Closes#1892
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Export and Import buttons in CompanySettings used plain <a href>
anchors which bypass the router's company-prefix wrapper. The links
resolved to /company/export and /company/import instead of
/:prefix/company/export, showing a 'Company not found' error.
Replace both <a href> elements with <Link to> from @/lib/router, which
calls applyCompanyPrefix under the hood and correctly resolves to
/:prefix/company/{export,import} regardless of which company is active.
Fixes: #2910