mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
505e3afc2a4f3bf8046851fd8dfef2f353b2b210
2842
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
505e3afc2a | Remove external mentions for deleted comments | ||
|
|
5edfa628cd | Harden external object sync edge cases | ||
|
|
04b3c6483b | Clean external references for tombstoned comments | ||
|
|
68efc373a2 | Schedule external objects after detection | ||
|
|
517d5522db | Chunk external object summary requests | ||
|
|
f6999839c1 | Address external object review findings | ||
|
|
fea7d3e54b | Remove screenshot artifacts from external object PR | ||
|
|
64ac16482b |
Align external object property values
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
89f7feb741 |
Render external object properties as plain links
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
ba59f64dea |
Simplify external object value pills
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
d4c4861abd |
Refine external object property pills
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
bb8ad4f0fa |
Use rich object property key fallback
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
f6ba07fe1c |
Render each external object as a property row
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
4394fcd00d |
Show external object display key in issue properties
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
95acb60120 |
Allow external objects to define presentation metadata
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
85351a2c9a |
Repair stale worktree provision configs
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
3a15727dc7 | Fix rebase fallout after master update | ||
|
|
f0c5c1913a |
Gate external objects behind experimental flag
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
71d08a6e05 |
Fix external object issue filtering
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
8e279837fc |
Stabilize external object service tests
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
665430757c |
Fix mock object provider workspace lockfile drift
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
dc3c02f5b9 |
Mock external object sync in ownership route tests
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
101bc15bf5 |
Harden environment-sensitive server tests
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
f1b4f2139a |
Skip embedded worktree reseed test when unsupported
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
c7b393a74e |
Prepare external object references for PR
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
e48a1a4f31 |
PAP-2277 screenshots: storybook capture script and §9 evidence
Adds a self-contained Playwright capture script that boots a static server over `ui/storybook-static` and screenshots the host-rendered external-object surfaces in light + dark mode at desktop and mobile widths. The captured stills go in `screenshots/pap-2277/` for upload to PAP-2268. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
3d75152a57 |
Storybook: cover external object decoration in chat threads
Adds an `External object decoration` scenario to the CommentThread matrix and threads `externalReferences` into the live IssueChatThread story so the new comment/document/chat plumbing renders the §2 status chip on resolved URLs while leaving unknown URLs and code-fenced URLs unchanged. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
f6f5b80972 |
Add integration test for external object decoration through CommentThread
Proves end-to-end that a non-description markdown consumer decorates a resolved URL with the §2 external status treatment and leaves an unknown URL as a plain link, using the real MarkdownBody (not a mock). Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
a2476bb79a |
Thread externalReferences through issue-scoped markdown surfaces
Extend the Phase 6 plumbing so every `MarkdownBody` rendered inside an issue context receives `externalObjectsState.markdownReferences`. Comments, documents, chat, continuation handoffs, interaction details, and run transcripts now decorate resolved external URLs with the §2 status chip. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
aa9e782ea3 |
Storybook coverage and tests for external object surfaces
- New foundations/external-objects story renders the §6 state matrix, pill examples, inline markdown decoration, severity-sorted related-work panel, and the projects sidebar rollup - Make storybook bundle by aliasing node:crypto to a browser-safe stub so shared/external-objects.ts (server-only canonicalizer) can be statically imported without breaking Vite - Inline a browser-safe mention-source label helper in useIssueExternalObjects so the UI does not pull node:crypto at runtime - externalObjectDominantCount now returns 0 when the highest severity is muted, matching the rollup-hide rule - Backfill inbox-test fixtures for the new externalObjectStatuses field - Add vitest coverage for external-objects helpers, the inline markdown decorator (known/unknown URL, code exclusion, casing tolerance, liveness copy), and the pill / status summary components Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
58d5adc1c7 |
Wire external object surfaces across markdown, properties, related work, sidebar, list, filters
- MarkdownBody/InlineEditor accept an externalReferences map and render resolved URLs with a host-rendered status icon prefix (no inline plugin React, per Phase 1B security review) - IssueProperties shows a read-only "External objects" row above Parent, with skeleton/error fallbacks - IssueRelatedWorkPanel adds a third "External objects" section between References and Referenced by, severity-sorted with mention-source chips - SidebarProjects renders a per-project ExternalObjectStatusSummary marker to the right of the project name - IssueRow accepts an externalObjectSummary in the desktop trailing slot - IssueFiltersPopover gains an "External object status" section with failed/waiting/running/auth_required/unreachable/stale/none options - Add useIssueExternalObjects, useIssueExternalObjectSummary, useProjectExternalObjectSummary hooks plus queryKeys.externalObjects - IssueDetail loads external objects once and forwards to description, properties, mobile properties drawer, and the related-work tab Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
fe3d3550a0 |
Add external object status tokens and pill primitives
- Extend status-colors with category, badge, liveness, and severity tokens shared by every external-object surface - Bump .paperclip-mention-chip min-height to 24px on touch viewports for WCAG 2.5.5 target size and add an external-object data-mention-kind hook - Introduce host-owned helpers (label, icon, severity ranking, tone fallback) and a usePrefersReducedMotion hook so the running spinner respects motion preferences - New presentational primitives: ExternalObjectStatusIcon (with stale clock overlay), ExternalObjectPill, and ExternalObjectStatusSummary Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
b66cc65035 |
Add GitHub external object provider
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
d880cb1a9a |
Add external object provider plugin contract
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
abca7f0ef3 |
Add external object reference services
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
d4dc12bd01 |
Add external object reference contracts
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
1ca3331c33 |
[codex] Fix mobile issue chat spacing (#8493)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The issue page is one of the main surfaces where operators read agent updates and manage task relationships. > - On narrow mobile viewports, agent chat bubbles kept the desktop `max-w-[85%]` cap, leaving the right side overly indented. > - The same issue sidebar can also become noisy when many blockers or sub-tasks are attached to a task. > - This pull request adjusts the mobile chat bubble width while preserving the existing desktop cap. > - It also limits long issue-relation previews until the operator expands them, then allows collapsing them again. > - The benefit is a denser, more readable mobile issue page without changing the underlying issue data model. ## Linked Issues or Issue Description No public GitHub issue exists for this internal report. Bug report: - On mobile issue pages, agent chat bubbles are unnecessarily narrow because the desktop max-width applies at all breakpoints. - Long blocked-by and sub-task relation lists can dominate the issue properties area before the operator needs the full list. - Related prior work: #4861 improved issue-thread scale and markdown polish, but did not address this mobile bubble width regression. ## What Changed - Added a responsive agent-comment bubble width class so mobile bubbles use `max-w-[calc(100%-0.5rem)]` and desktop keeps `sm:max-w-[85%]`. - Added test coverage for the responsive agent bubble classes. - Added a five-item preview limit for blocked-by and sub-task relation pills in issue properties. - Added an inline `and N more...` / `show less` toggle for long blocked-by and sub-task relation lists. - Reset relation preview expansion when the `IssueProperties` panel receives a different `issue.id`. - Added component test coverage for collapsed, expanded, re-collapsed, and issue-switch reset states. ## Verification - Passed: `pnpm exec vitest run ui/src/components/IssueProperties.test.tsx` (`27 passed`). - Attempted: `pnpm exec vitest run ui/src/components/IssueChatThread.test.tsx`. - Result: failed before reaching the changed assertion because the existing suite imports `act` from `react`, which resolves to a non-function in this local Vitest environment. - Scope: 50 render tests fail with `TypeError: act is not a function`; 8 non-render tests pass. - Attempted: `pnpm --dir ui exec vitest run src/components/IssueChatThread.test.tsx` with the same `act is not a function` result. - Passed: Greptile rerun reported Confidence Score 5/5 on commit `e0f9c40b7faedcfb877d4f4b0e9f2c77a6593c16`. - Passed: all latest-head PR checks/statuses are green, including Typecheck + Release Registry, Build, general tests, serialized server suites, e2e, canary dry run, policy, security review, Socket, Snyk, and Greptile. ## Risks Low risk: - The chat change only alters max-width classes on agent comment bubbles and preserves the desktop cap. - The relation-list change is presentational; hidden blockers and sub-tasks remain in memory and can expand/collapse in place. - Expansion state now resets when navigating between issues in a reused panel instance. - Main residual risk is visual polish on real mobile devices because local browser screenshot verification was not run in this heartbeat; screenshots were not added because the source task explicitly requested not adding screenshots/images unless specifically part of the work. > 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 repository tool use, shell execution, GitHub connector access, local Vitest verification, Greptile follow-up, and PR check monitoring. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [ ] 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] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge |
||
|
|
03362b347d |
Clean up agent config environment selector (#8504)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agent configuration is where operators set identity, adapter behavior, and execution environment defaults. > - The environment override control should only appear when there is a meaningful choice beyond the always-available local environment, or when an existing saved override must remain visible so it can be inspected or cleared. > - The previous UI used an "Execution" header, explanatory helper copy, and verbose inherited-default wording that made the agent config feel noisier than necessary. > - This pull request narrows the selector visibility to real alternatives and forced Kubernetes mode, then updates the visible copy to match the environment-focused mental model. > - The benefit is a cleaner agent configuration surface that only asks operators to make an environment choice when that choice exists. ## Linked Issues or Issue Description No public GitHub issue exists for this change. Public GitHub searches for related issues and PRs returned no matches: - `agent config environment selector` - `execution environment agent config` Bug-style issue description: What happened? The agent config form could surface an environment override section even when the operator had no meaningful non-local execution environment choice. The section was labeled "Execution", included helper/inheritance text, and described the inherited local default as "Inherit instance default (Local)". Expected behavior: The selector should stay hidden unless there is more than one configured environment choice, the section should be labeled "Environment", helper text should be removed, and the inherited default option should read like `Default: Local`. Existing saved non-local overrides should remain visible even if the target environment is no longer runnable, so operators can inspect or clear the stale selection. Steps to reproduce: 1. Run Paperclip from `master` with environments enabled and only the implicit local default, or Local plus one runnable non-local environment. 2. Open an agent configuration form. 3. Inspect the environment override section visibility and copy. Paperclip version or commit: `0b945f449` / current `master` before this branch. Deployment mode: Local dev (`pnpm dev`). Installation method: Built from source. Agent adapters involved: Not adapter-specific. Database mode: Not database-related. Access context: Board operator UI. ## What Changed - Shows the environment override selector only for forced Kubernetes mode, at least one runnable non-local environment, or an existing saved non-local override. - Keeps Local out of the runnable environment count so Local-only setups do not show a redundant selector. - Preserves stale saved non-local overrides in the selector options so operators can see and clear them. - Renames the section header from "Execution" to "Environment". - Removes the helper/inheritance text above the selector. - Changes the inherited option copy from `Inherit instance default (...)` to `Default: ...`. - Adds focused render tests for Local-only hiding, Local plus one runnable non-local environment showing the concise selector copy, and stale non-runnable override recovery. ## Verification - `pnpm --filter @paperclipai/ui exec vitest run src/components/AgentConfigForm.render.test.tsx` - `pnpm --filter @paperclipai/ui typecheck` - `git diff --check origin/master...HEAD` - Checked `ROADMAP.md` for overlapping planned core work. - Searched public GitHub issues and PRs for duplicate or related work; no matches found. ## Screenshots Before, when the selector was visible: ```text Execution Environment override Inheriting the instance default: Local. [Inherit instance default (Local)] ``` After, when Local plus a runnable non-local environment exists: ```text Environment Environment override [Default: Local] [E2B · sandbox] ``` After, when only Local is configured: ```text (no Environment section is rendered) ``` ## Risks Low risk. This is isolated to the agent config UI. The main behavioral risk is hiding the selector in an environment edge case; the current branch keeps forced Kubernetes mode, runnable non-local environments, and pre-existing saved non-local overrides visible. The added render tests cover the Local-only, single non-local alternative, and stale override cases. ## Model Used OpenAI Codex local adapter, GPT-5-based Codex coding session. The exact hosted backend model ID is not exposed in the runtime. Tool use and local shell 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 searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
0b945f449b |
Make streamlined sidebar default to on (#8496)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The board UI has an experimental streamlined left navigation mode that changes how projects and agents appear in the sidebar. > - Today that mode is opt-in, so users keep seeing the classic navigation unless they find and enable the experiment. > - The requested product behavior is to make streamlined navigation the default experience while keeping an explicit experiments opt-out. > - This pull request flips the shared/server default, updates UI consumers to treat only explicit `false` as classic mode, and covers both the default-on path and opt-out behavior in tests. > - The benefit is that new and legacy settings get the streamlined sidebar by default without removing the classic-sidebar escape hatch. ## Linked Issues or Issue Description Refs #7645 Related: #8430 takes the broader route of removing the classic sidebar. This PR intentionally keeps the opt-out path. ## What Changed - Default `enableStreamlinedLeftNavigation` to `true` in shared validation and server-side normalization. - Preserve explicit stored `false` as the experiments opt-out for the classic sidebar. - Render the sidebar and experimental settings toggle as streamlined-on unless the setting is explicitly `false`. - Add regression coverage for loading/default streamlined sidebar behavior and the opt-out patch from the experiments page. - Remove internal issue identifiers from newly touched source comments before publishing. ## Verification - `git diff --check origin/master...HEAD` — passed. - `pnpm -r typecheck` — passed. - `pnpm exec vitest run server/src/__tests__/instance-settings-service.test.ts ui/src/components/Sidebar.test.tsx ui/src/pages/InstanceExperimentalSettings.test.tsx` — passed, 3 files / 27 tests. - `pnpm build` — passed, with existing Vite/CSS/chunk-size warnings. - `pnpm test:run` — failed in unrelated `server/src/__tests__/workspace-runtime.test.ts`: the test `auto-detects the default branch via symbolic-ref when origin/HEAD is set` creates a temp repo on `main` then runs `git push -u origin main master`; `master` does not exist in that temp repo. Summary: 1 failed, 214 passed, 1780 tests passed, 1 skipped. ## Risks Low-to-medium behavioral risk: the default sidebar changes for users who never explicitly set the experiment. Explicit `false` remains respected, so users can still opt out via experimental settings. > 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 GPT-5 via Codex local adapter, with tool use and code execution. Exact context window was not surfaced in 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 checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.622.0-canary.3 |
||
|
|
ef0ccf6959 |
[codex] Fix issue chat mention warning spacing (#8486)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The board issue thread composer is the subsystem involved here. > - The composer can show both the mention coaching warning and the handoff preview row near the send controls. > - The handoff preview row sat flush against nearby composer UI, making the warning and send-control area feel crowded. > - This pull request adds vertical spacing around the visible handoff preview row and avoids rendering a spacer when there is no preview. > - The benefit is a cleaner, less cramped composer layout without changing handoff behavior. ## Linked Issues or Issue Description Refs: PAP-11281 Refs: PAP-11598 No public GitHub issue exists for this Paperclip task, so the issue is described inline using the bug report template fields. ### What happened? In the issue chat composer, the handoff preview row could render flush against the mention coach warning above it and the send controls below it. ### Expected behavior When the handoff preview is visible, it should have a small amount of vertical breathing room. When there is no preview, no empty wrapper should add phantom margin. ### Steps to reproduce 1. Open an issue thread. 2. Type a reply that produces an active handoff preview near the mention warning/send controls. 3. Inspect the composer spacing around the handoff preview row. ### Paperclip version or commit Reproduced on the PAP-11281 work branch before this fix. ### Deployment mode Local dev worktree. ## What Changed - Added a `my-2` wrapper around `ComposerHandoffPreviewRow` in `IssueChatThread`. - Guarded the wrapper behind a named `shouldRenderComposerHandoffPreview` helper so empty previews do not add phantom vertical margin. - Added a focused UI unit test covering the empty-preview and visible-preview spacing guard. ## Verification - `pnpm --filter @paperclipai/ui exec vitest run src/components/IssueChatComposerHandoffPreview.test.ts` passed locally. - `pnpm --filter @paperclipai/ui typecheck` passed locally. - `git diff --check` passed before the follow-up commit. - Reviewed the one-file UI diff and focused test diff. Screenshots: intentionally omitted for this tiny spacing-only branch because PAP-11598 explicitly says not to add design screenshots or images to this PR unless they are specifically part of the work. No screenshot or wireframe image files are committed. ## Risks Low risk. This is a narrowly scoped layout-only change in the composer. The main risk is slightly different vertical rhythm around the handoff preview row. > 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, GPT-5-class model in tool-use/code-execution mode. Exact hosted deployment identifier and context window were not exposed in 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 checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have 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] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Notes for draft status: remote CI and Greptile are re-running after the follow-up push. The checklist records the required PR-ready criteria; this PR should remain draft until GitHub reports those checks green. --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>canary/v2026.622.0-canary.2 |
||
|
|
93fdb9c218 |
[codex] Harden same-company CEO authorization (#8276)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Companies are the primary tenant boundary for agents, board users, settings, and portability operations. > - CEO agents need limited same-company management powers, but those powers must not cross into another company. > - The affected company routes mixed route-level access checks with validation middleware and repeated CEO checks, which left adjacent mutation and portability surfaces easy to drift. > - This pull request centralizes same-company CEO-or-board authorization for those company-scoped surfaces. > - It also adds regression coverage proving a CEO agent from one company cannot read, mutate, archive, delete, export, or import against another company. > - The benefit is tighter company isolation without removing legitimate same-company CEO operations. ## Linked Issues or Issue Description Internal task: PAP-11205 / PAP-11347. Bug report: - What happened: same-company CEO authorization for company settings, branding, and portability routes was implemented per-route, making it possible for adjacent surfaces to drift and risking company-boundary mistakes. - Expected behavior: an agent API key must only manage the company that owns the authenticated agent, and only CEO agents should get the limited same-company management permissions. - Steps to reproduce: authenticate as a CEO agent from Company A and call Company B company routes such as `PATCH /api/companies/:companyId`, `PATCH /api/companies/:companyId/branding`, export/preview export, safe import preview/apply, archive, delete, or read. - Version/commit: fixed on this branch at `45edaccb8` on top of `public/master` `ddc193c2b`. - Deployment mode: server API behavior; no UI change. Related search results reviewed, not duplicates of this exact route hardening: - Refs #2212 - Refs #1083 - Refs #8053 ## What Changed - Added a shared `assertSameCompanyCeoAgentOrBoard` company route guard and reused it for company settings, branding, export, and safe import endpoints. - Moved request parsing after authorization on sensitive company mutation/export/import routes so unauthorized cross-company callers are rejected before route body validation side effects or service calls. - Tightened archive and delete ordering to assert route company access before board-only mutation authorization. - Added a cross-company company-route authorization regression suite covering read, settings, branding, archive, delete, export, export preview, import preview, and import apply paths. - Extended adjacent route/service tests to prove non-CEO and cross-company agent keys are rejected on the relevant company-scoped surfaces. - Addressed Greptile follow-ups by removing a redundant board assertion and inlining the portability authorization wrapper. ## Verification Local focused verification on rebased head `45edaccb8`: - `pnpm exec vitest run server/src/__tests__/companies-route-cross-company-authz.test.ts server/src/__tests__/company-branding-route.test.ts server/src/__tests__/company-portability-routes.test.ts server/src/__tests__/agent-permissions-routes.test.ts server/src/__tests__/authorization-service.test.ts server/src/__tests__/openclaw-invite-prompt-route.test.ts` - 6 test files passed - 127 tests passed Remote PR checks on rebased head `45edaccb8`: - Paperclip PR workflow: green, including policy, typecheck, build, e2e, canary dry run, workspace tests, server general tests, and all serialized server shards. - Greptile Review: success with 5/5 confidence on `45edaccb8`. - Greptile review threads: all resolved. ## Risks Low to moderate risk. This intentionally tightens company route authorization and changes whether some unauthorized requests fail at the authz layer before schema validation. Legitimate board users and same-company CEO agents remain covered by tests, but callers that depended on validation errors from unauthorized company routes will now receive authorization errors first. No migrations. No `pnpm-lock.yaml` changes. No `.github/workflows` changes. No screenshots or design images added. > 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.5-based coding agent with tool use, terminal execution, repository inspection, and GitHub connector access. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have 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 (N/A: no UI change) - [x] I have updated relevant documentation to reflect my changes (N/A: no docs needed beyond this PR description) - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.622.0-canary.1 |
||
|
|
ddc193c2b9 |
docs: clarify plan task dependency handling (#8485)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Paperclip planning skills turn approved plans into executable issue graphs for agents > - The executor starts assigned tasks that have no open blockers > - Parent/child nesting gives structure, but it does not create execution dependencies > - Planning guidance that does not make this distinction can let dependent tasks run too early > - This pull request clarifies that hard dependencies must be encoded as `blockedByIssueIds` > - The benefit is that agents converting plans into tasks have a clearer checklist for creating and verifying runnable task graphs ## Linked Issues or Issue Description No public GitHub issue was found for this documentation update. Problem: - The planning guidance could be read as if hierarchy, phase order, or prose blocker notes were enough to sequence execution. - In Paperclip, only explicit blockers prevent an otherwise-ready assigned task from starting. Expected behavior: - Skill guidance should tell planners to encode each hard dependency as `blockedByIssueIds` on the dependent issue. - It should also tell planners to verify the created issue graph before closing the source planning issue. ## What Changed - Clarified that parent/child issue nesting is structural and not an execution blocker. - Added guidance to build a compact task matrix with task, owner, initial status, and blockers when converting accepted plans into tasks. - Added verification guidance to re-fetch or otherwise inspect created issues before marking the source planning issue done. - Updated the bundled task-planning skill handoff text to point at the same dependency expectations without duplicating the full companion skill text. ## Verification - Ran `git diff --check origin/master...HEAD` locally. - Rebased cleanly onto the latest `master` from `paperclipai/paperclip` before pushing. - Greptile completed at 5/5 on the latest head; the previous P2 wording thread was fixed and resolved. - GitHub PR checks are green on latest head `2b07db9aef22ca32c65fa66fcca2db86c5b01220`, including policy, commitperclip review, typecheck/release registry, general test shards, build, serialized server suites, e2e, canary dry run, verify, Socket, security-review, Snyk, and Greptile. - No additional local unit test command was run because this is a documentation/skill-text-only change and the remote PR suite covered the repository gates. ## Risks Low risk. This changes skill guidance only; it does not alter runtime behavior, database schema, migrations, workflows, or UI code. > 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 in the Paperclip local adapter runtime. Exact backend model ID and context window were not exposed by the runtime. Used shell, git, GitHub CLI, and the GitHub connector for repository inspection and PR creation. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [ ] 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] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.622.0-canary.0 |
||
|
|
9ac24317e6 |
fix(issues): ignore cancelled child blockers in attention (#7577)
Fixes #7578 ## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies. > - Blocked issue health is surfaced through blockerAttention so operators can see whether blocked work has a live path. > - The blockerAttention graph uses both explicit blockedBy edges and direct child issue edges. > - Done children were already ignored, but cancelled direct children still appeared as unresolved blockers. > - Explicit cancelled dependencies should remain visible as dependency problems, but terminal direct children should not inflate a parent blocker count. > - This pull request narrows child-edge traversal to non-terminal children and adds a regression test for the observed case. > - The benefit is that cancelled child issues no longer make blocked parents look like they have extra unresolved blocker attention. ## What Changed - Added terminal child status filtering for blockerAttention parent-child traversal so cancelled direct children are ignored with done children. - Added a server regression test where a blocked parent has active explicit blockers plus a cancelled direct child; the cancelled child no longer increases unresolved counts or becomes the sample blocker. ## Verification - `perl -e 'alarm shift; exec @ARGV' 300 pnpm exec vitest run server/src/__tests__/issue-blocker-attention.test.ts` -> 19 tests passed. ## Risks - Low risk: the change only affects implicit direct-child blockerAttention edges. - Explicit blockedBy edges to cancelled issues are intentionally unchanged and remain represented as attention-required dependency problems. ## Model Used - OpenAI GPT-5, Codex coding agent in tool-enabled CLI environment; reasoning and code execution used for repository inspection, patching, git operations, and targeted test verification. ## 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 (not applicable; no UI change) - [x] I have updated relevant documentation to reflect my changes (not applicable; bugfix covered by regression test) - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.621.0-canary.6 |
||
|
|
d1e6662ed8 |
fix(server): let codex_local agents inherit host Codex login by default (#8425)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The `codex_local` adapter spawns the Codex CLI for an agent, and `server/src/routes/agents.ts` normalizes each agent's `adapterConfig.env` on create/hire/update > - PR #8272 added an isolation guard that, on every codex_local agent, force-set a per-agent `CODEX_HOME` and injected `OPENAI_API_KEY = ""`, and rejected any "shared" home > - This broke the common case: operators who deleted `CODEX_HOME` / `OPENAI_API_KEY` in the UI saw them silently re-appear on save, and every agent was forced into an isolated home instead of sharing the device's existing Codex login (`~/.codex` / `$CODEX_HOME`) > - This pull request replaces the always-on isolation guard with key-scoped isolation: a keyless agent gets no env overrides and inherits the host Codex login at runtime; we only carve out an isolated per-agent `CODEX_HOME` when the agent sets its own `OPENAI_API_KEY` > - The benefit is that env-var deletion now persists, agents on one device share the host login by default, and per-account isolation is still available by setting a per-agent key ## Linked Issues or Issue Description No public GitHub issue exists. Bug report (following `bug_report.yml`): **What happened?** In a `codex_local` agent's configuration, removing the `CODEX_HOME` and `OPENAI_API_KEY` env vars via the UI (clicking the X) appears to work, but on save they instantly re-appear. The persisted config never loses the slots. **Root cause.** `applyCodexLocalIsolationGuard` in `server/src/routes/agents.ts` (added in #8272) re-injected `CODEX_HOME` (defaulting to a per-agent home) and `OPENAI_API_KEY = ""` on every create/hire/update, and rejected shared homes outright. So a PATCH that omitted those keys had them written back server-side. **Expected behavior.** Deleting these env vars should persist. A codex_local agent with no key should inherit whatever Codex login already exists on the device. **Steps to reproduce.** 1. Open a `codex_local` agent's configuration with `CODEX_HOME` and `OPENAI_API_KEY` set. 2. Remove both env vars and save. 3. Re-open the config — both slots are back. Related (different approach): Refs #8399 (keeps per-agent isolation, fixes only the empty `OPENAI_API_KEY` slot), Refs #8272 (introduced the guard), Refs #8403 (managed-auth seeding into isolated homes). ## What Changed - `server/src/routes/agents.ts` — replaced `applyCodexLocalIsolationGuard` (+ `assertCodexLocalHomeIsNotShared` / `normalizeCodexLocalHomePath`) with `applyCodexLocalKeyIsolation`. A codex_local agent now receives **no** env overrides unless it explicitly sets `OPENAI_API_KEY`; only then is an isolated per-agent `CODEX_HOME` injected (and only if the agent has not set its own `CODEX_HOME`). Keyless agents fall back to the host Codex login at runtime. Dropped the now-unused `node:os` import and the shared-home rejection. - `server/src/__tests__/agent-adapter-validation-routes.test.ts` — updated the validation-route tests to assert env-var deletion persists, keyless agents get no overrides, and key-bearing agents still get an isolated `CODEX_HOME`. ## Verification ```bash cd server && npx vitest run src/__tests__/agent-adapter-validation-routes.test.ts ``` All 6 tests pass locally. Manually verified in the live UI: removing `CODEX_HOME` and `OPENAI_API_KEY` from a codex_local agent and saving now persists the deletion (slots no longer re-appear on reload). ## Risks - **Host-key leak for keyless agents on a host with `OPENAI_API_KEY` set.** Low/intended: the product direction here is that codex_local agents inherit the host's Codex login by default; per-account isolation is opt-in via a per-agent `OPENAI_API_KEY`, which then gets its own `CODEX_HOME`. - **Divergence from #8399.** That PR retains the per-agent isolation default and only stops injecting the empty key, so it does not address the `CODEX_HOME` re-injection half of this bug. This PR intentionally changes the default to host-login inheritance. Reviewers should pick one direction. - **No migration.** Existing agents that already store these slots are not auto-cleaned, but operators can now delete them and the deletion sticks. ## Model Used - Provider: Anthropic (Claude) - Model ID: `claude-opus-4-8` - Capabilities: tool use, code execution, extended reasoning, agentic workflow ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] 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 - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [ ] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.621.0-canary.5 |
||
|
|
2c98c8e1e5 |
Fix sandbox git publishing and large workspace uploads (#8422)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Sandbox and SSH runtimes need to preserve agent work across isolated execution environments > - Git-backed workspaces were being copied mostly as filesystem archives, which breaks when `.git` points outside the mounted workspace and makes sandbox agents unable to publish their own branches > - Large ignored dependency trees could also be swept into the sandbox overlay, causing multi-GB transfers and max-string failures in some sandbox clients > - This pull request makes sandbox runtime setup use a git-backed HEAD sync plus a small dirty/untracked overlay, and bounds sandbox file transfers so large archives do not need one huge string > - The benefit is that sandbox agents can commit and push from a usable git checkout without uploading dependency trees such as `node_modules` ## Linked Issues or Issue Description Refs #8395 No public duplicate issue or PR was found after searches for `sandbox git workspace`, `git push sandbox`, and `node_modules sandbox upload`. Bug report: - What happened: sandbox-backed agent workspaces could receive a `.git` file that pointed at host-only git state, leaving the sandbox unable to run normal git workflows. The sandbox overlay upload could also include ignored dependency directories, creating very large transfers. - Expected behavior: sandbox and remote runtimes should prepare a usable git-backed workspace, copy only the necessary workspace overlay, and restore git history plus file changes without depending on a host-only `.git` path. - Steps to reproduce: 1. Run an agent in a sandbox-backed workspace whose local git checkout is a worktree. 2. Ask the agent to complete a GitHub workflow that requires commit/push access. 3. Observe that git operations can fail inside the sandbox, and ignored dependency trees can be uploaded as part of the workspace overlay. - Paperclip version or commit: reproduced against `master` before this PR, base `7aa212296eb1`. - Deployment mode: local dev / sandbox-backed runtime. - Installation method: built from source. - Agent adapters involved: local adapters using shared adapter-utils runtime preparation. - Database mode: not database-related. - Access context: agent runtime. - Local verification environment: Node.js v25.6.1, pnpm 9.15.4, macOS arm64. - Privacy checklist: all pasted output was reviewed for secrets, private hostnames, local usernames, and internal instance links. ## What Changed - Added a GitHub workflow push preflight so agent runs can detect missing push credentials when a workflow explicitly needs GitHub publishing. - Added shared git workspace sync helpers for shallow HEAD import/export and dirty/untracked overlay tracking. - Updated sandbox managed runtime setup to use git history plus a selected overlay instead of uploading the full local workspace for git-backed workspaces. - Bounded sandbox archive upload/download paths so large payloads stream or chunk instead of materializing one oversized string. - Excluded `.git` and ignored dependency trees from sandbox upload, download, and restore baselines while preserving local ignored directories during sync-back. - Added focused tests for git workspace sync, sandbox overlay selection, transfer chunking, and heartbeat push-preflight behavior. ## Verification - `pnpm exec vitest run packages/adapter-utils/src/git-workspace-sync.test.ts packages/adapter-utils/src/sandbox-managed-runtime.test.ts packages/adapter-utils/src/command-managed-runtime.test.ts server/src/__tests__/heartbeat-project-env.test.ts server/src/__tests__/heartbeat-workspace-session.test.ts` - `pnpm --filter @paperclipai/adapter-utils typecheck` - `pnpm --filter @paperclipai/server typecheck` - `pnpm build` - Public-hygiene scan of the PR diff and commit messages for internal issue ids, local paths, private hostnames, and obvious token patterns. ## Risks - Medium risk: this changes sandbox runtime synchronization semantics for git-backed workspaces, especially around dirty tracked files, untracked files, deleted paths, and ignored files. - The main mitigation is focused test coverage for upload contents, restore exclusions, and git round-trip behavior. - The SSH runtime keeps the current bundle-based implementation from `master`; this PR only aligns shared excludes and sandbox behavior with that model. ## Model Used OpenAI Codex, GPT-5-based coding agent, tool-enabled shell/git/GitHub workflow, with code execution and repository inspection. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] 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] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.621.0-canary.4 |
||
|
|
33353ce62b |
feat(skills): remove bundled paperclip-dev skill and retire required skill attribute (#7029)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Local adapters (Claude, Codex, Cursor, Gemini, Grok, OpenCode, Pi, ACPX) ship bundled "skills" — opinionated Markdown prompt bundles materialized into the agent's runtime > - One of those bundled skills, `paperclip-dev`, existed to let agents develop Paperclip itself; it has now moved to its own external repo and no longer belongs in the core tree > - The adapter skill model also carried a `required` / `requiredReason` attribute plus a `paperclip_required` `AdapterSkillOrigin` variant, all of which only existed to mark bundled skills as non-optional in the UI and adapter sync logic > - With `paperclip-dev` gone, no bundled skill is "required" anymore, and the type / runtime surface for `required` is dead weight — but it is computed at request time and never persisted, so a clean removal is safe (no compatibility shim needed) > - This pull request deletes `skills/paperclip-dev/` and removes every trace of the `required` / `requiredReason` field and the `paperclip_required` origin across shared types, validators, adapter-utils, all eight local adapters, server routes, the company-skills service, the UI, the storybook fixtures, and the test suite > - The benefit is a smaller, simpler adapter-skill surface: one origin (`company_managed`) for managed bundled skills, `resolvePaperclipDesiredSkillNames` collapses to "just the configured desired set", and the AgentDetail skills tab no longer renders a "Required by Paperclip" section that no longer applies ## Linked Issues or Issue Description <!-- No existing public GitHub issue; describing the underlying work inline (feature_request template fields). --> **Summary** Remove the bundled `paperclip-dev` skill (now maintained in its own external repo) and retire the `required` / `requiredReason` skill attribute and the `paperclip_required` skill origin, which only existed to support it. **Problem or motivation** `paperclip-dev` is the only bundled skill that was ever marked "required". Now that it lives in a separate repository, shipping it inside the core tree is wrong, and the entire `required` surface (a type field, a validator field, a synthesized `paperclip_required` origin, UI "Required by Paperclip" section, and required-skill merging in the desired-skills calculation) becomes dead weight. The `required` value is computed at request time and never persisted, so it can be removed cleanly without a migration or compatibility shim. **Proposed solution** Delete `skills/paperclip-dev/`, drop the `required` / `requiredReason` fields and `paperclip_required` origin everywhere they are produced or consumed, collapse managed-skill origin to a single `company_managed` value, and simplify `resolvePaperclipDesiredSkillNames` to return only the configured desired set. **Alternatives considered** Keeping the `required` attribute as a no-op for forward compatibility — rejected because it is request-time only (nothing persists it), so leaving it in place is pure dead surface area with no callers. **Roadmap alignment** Internal cleanup / dead-code removal that simplifies the adapter-skill surface; it does not introduce or duplicate any planned core feature in ROADMAP.md. ## What Changed - Deleted bundled `skills/paperclip-dev/` (moved to a separate repo). - Dropped `required`, `requiredReason`, and the `paperclip_required` origin from `packages/shared/src/types/adapter-skills.ts`, `packages/shared/src/validators/adapter-skills.ts`, and `packages/adapter-utils/src/types.ts`. - In `packages/adapter-utils/src/server-utils.ts`: removed `readSkillRequired()`; dropped `required`/`requiredReason` from `listPaperclipSkillEntries()`, `normalizeConfiguredPaperclipRuntimeSkills()`, `buildPersistentSkillSnapshot()`, and `PaperclipSkillEntry`; collapsed `buildManagedSkillOrigin()` to always return `company_managed`; simplified `resolvePaperclipDesiredSkillNames()` to return only the configured desired set (signature preserved so adapter call sites are untouched). - Walked all eight local adapters (`acpx-local`, `claude-local`, `codex-local`, `cursor-local`, `gemini-local`, `grok-local`, `opencode-local`, `pi-local`) and removed every remaining `requiredReason` / `paperclip_required` reference. - `server/src/services/company-skills.ts`: dropped the `required = sourceKind === "paperclip_bundled"` synthesis when listing runtime skill entries. - `server/src/routes/agents.ts`: removed required-skill merging from the desired-skills calculation in the persist-config path and the unsupported-snapshot path (keeping the current version-aware `desiredSkillEntries` structure). - `ui/src/pages/AgentDetail.tsx`: dropped required-based filters, the required tooltip, and the entire "Required by Paperclip" section from the agent skills tab; storybook fixtures in `ui/storybook/stories/acpx-local.stories.tsx` cleaned up to match. - Tests: deleted the `required: false` case in `paperclip-skill-utils.test.ts` and the "keeps required bundled skills installed" case in every `*-local-skill-sync.test.ts`; `acpx-local-execute.test.ts`, `cursor-local-execute.test.ts`, `cursor-local-skill-sync.test.ts`, `agent-skills-routes.test.ts`, and `packages/adapter-utils/src/server-utils.test.ts` were updated to drop removed fields and map `origin: "paperclip_required"` → `"company_managed"`. - `server/src/adapters/registry.ts`: two `as unknown as ServerAdapterModule["..."]` casts on `hermesListSkills` / `hermesSyncSkills` (matching the existing `executeHermesLocal` pattern). `hermes-paperclip-adapter@0.2.0` still depends on the published `@paperclipai/adapter-utils` which keeps the retired `paperclip_required` variant; the cast bridges the workspace-vs-published type mismatch at the registry seam and can drop once hermes upgrades. ## Verification Run from the workspace root: ```sh grep -rn "skills/paperclip-dev" . grep -rn "paperclip_required" --include="*.ts" --include="*.tsx" . grep -rn "requiredReason" --include="*.ts" --include="*.tsx" . pnpm -w typecheck pnpm --filter @paperclipai/server exec vitest run paperclip-skill-utils pnpm --filter @paperclipai/server exec vitest run skill-sync ``` The first three greps return only the explanatory comment in `server/src/adapters/registry.ts` (no live `paperclip_required` / `requiredReason` usage) and zero `skills/paperclip-dev` source hits. Locally: - `pnpm -w typecheck` → all packages this PR touches pass (adapter-utils, shared, server, ui, cli, and the cursor/gemini/opencode/pi adapters). - Affected vitest suites pass: `paperclip-skill-utils`, `server-utils`, all eight `*-local-skill-sync`, `agent-skills-routes`, and the `acpx`/`cursor`/`pi` execute suites. ## Risks - Behavioral shift in the agent skills UI: the "Required by Paperclip" section disappears. No bundled skill is required anymore, so this only affects environments that previously surfaced `paperclip-dev` as a forced-on row; those installs will see the skill move into the regular "company-managed" list (and be uninstalled on next sync unless explicitly listed as desired). - Existing agents may still have the string `"paperclip-dev"` in their persisted `desiredSkills`. That entry is inert (no source for it to install from); a one-time DB cleanup is out of scope. Low risk. - Hermes adapter type bridge: two casts in `registry.ts` paper over a type-only divergence between the workspace `@paperclipai/adapter-utils` and the published version still pinned by `hermes-paperclip-adapter@0.2.0`. Runtime behavior is unaffected because the retired `paperclip_required` value is no longer produced by anything in this tree. The casts can be removed once hermes upgrades its dependency. ## Model Used - Provider: Anthropic - Model: Claude Opus 4.7 (`claude-opus-4-7`) - Capability: agent tool use via Paperclip's `claude_local` adapter ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [ ] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.621.0-canary.3 |
||
|
|
7aa212296e |
codex_local adapter output inactivity monitor (#5017)
## Thinking Path > - Paperclip orchestrates AI agents for zero-human companies > - The `codex_local` adapter runs `codex exec` as a child process and streams JSONL events from its stdout > - NEE-79 caught a real-world `codex_local` orphan: codex sat in `read()` on stdin for 1h+, no JSON events emitted past startup, no LLM call in flight. The adapter had no inactivity timer; the only safety net was the platform-level 1h silent-run detector > - This is precisely the failure shape NEE-80 scoped: an adapter-detected fault that should be killed *by the adapter* and surfaced as `failed`, not waited out for an hour > - This pull request adds an output-inactivity watchdog inside the codex-local adapter that resets on every parsed JSONL event from stdout, kills the child via SIGTERM → 5s grace → SIGKILL when it fires, and resolves the run with a structured watchdog failure > - The benefit is that NEE-79-class hangs shorter than 1h stop reaching the platform-level safety net — they fail fast and visibly at the adapter layer, with diagnostic logs that don't require host shell access ## Linked Issues or Issue Description No existing GitHub issue covers this; describing the underlying bug in-PR per the bug report template (`.github/ISSUE_TEMPLATE/bug_report.yml`): - **What happened?** A `codex_local` run sat in `read()` on stdin for over an hour: codex emitted its startup JSONL events, then nothing — no further events, no LLM call in flight, no exit. The adapter kept the child alive indefinitely; the run was only reaped by the platform-level 1h silent-run safety net, an hour after it had effectively died. - **Expected behavior:** The adapter should detect that its child has stopped producing output long before the platform-level safety net, kill it, and surface the run as `failed` with a diagnostic that explains what happened. - **Steps to reproduce:** Run any `codex_local` issue where `codex exec` hangs after startup (e.g. codex blocks reading stdin and never emits another JSONL event). Observe the run stays alive until the 1h platform safety net fires. - **Paperclip version or commit:** reproduced on master prior to this branch. - **Agent adapter(s) involved:** codex_local. Related PRs found while searching for duplicates (none implement an event-aware inactivity watchdog inside `codex_local`): - #4004 — generic idle + wall watchdogs for `runChildProcess` in adapter-utils; complementary, operates below the JSONL parse layer and is not codex-event-aware - #4742 — fail-fast on codex-local *startup* hang; this PR covers the post-startup hang class - #6861 — zombie-run termination for codex-local; reaping after exit, not inactivity detection - #7811 — the analogous output-idle timeout for grok-local ## What Changed - `packages/adapters/codex-local/src/server/watchdog.ts` *(new)* — pure watchdog primitive with injectable timers/clock: `resolveCodexInactivityTimeout`, `createCodexInactivityWatchdog`, `formatWatchdogErrorMessage`. Default `7 * 60_000` ms; honors `null` as the disabled escape hatch - `packages/adapters/codex-local/src/server/execute.ts` — `runAttempt` now wraps `onSpawn` to capture `pid`/`processGroupId`, feeds stdout chunks through `noteStdoutChunk`, and on watchdog fire sends SIGTERM to the process group, schedules SIGKILL after 5s, and returns an `AdapterExecutionResult` with `exitCode: null`, `signal: SIGTERM|SIGKILL`, `errorMessage: "watchdog: no codex output for {N}m {S}s"`, `errorCode: "codex_output_inactivity_watchdog"`. With `errorMessage` set and `timedOut: false`, `heartbeat.ts:5860` maps the run to `outcome === "failed"` (not `cancelled`) - `packages/adapters/codex-local/src/index.ts` — `agentConfigurationDoc` documents `outputInactivityTimeoutMs` (number ms; `null` disables; non-positive falls back to default with a warning log at spawn) - `packages/adapters/codex-local/src/server/watchdog.test.ts` *(new)* — 13 tests covering acceptance criteria 2 and 3 plus supporting cases: fires after silence, no-fire across 12× (threshold − 1s) cycles, multi-event chunks, non-JSON ignoring, single-fire idempotency, formatter shape, full resolution table, `null` → disabled - `packages/adapters/codex-local/src/server/watchdog.integration.test.ts` *(new)* — real Node subprocess that prints one JSONL event then sleeps; `runChildProcess` reaps it within `threshold + 6s`; signal is SIGTERM or SIGKILL; `parsedEventCount === 1` (acceptance criteria 1 and 4) ## Verification ``` $ pnpm --filter @paperclipai/adapter-codex-local typecheck > tsc --noEmit # clean $ pnpm --filter @paperclipai/adapter-codex-local exec vitest run ✓ src/server/quota-spawn-error.test.ts (1 test) ✓ src/server/codex-home.test.ts (3 tests) ✓ src/server/codex-args.test.ts (3 tests) ✓ src/server/watchdog.test.ts (13 tests) ✓ src/server/parse.test.ts (9 tests) ✓ src/server/execute.remote.test.ts (4 tests) ✓ src/ui/parse-stdout.test.ts (3 tests) ✓ src/ui/build-config.test.ts (1 test) ✓ src/server/watchdog.integration.test.ts (1 test) Test Files 9 passed (9) Tests 38 passed (38) ``` Acceptance criteria check: 1. ✅ Simulated child emits one event then sleeps → killed at threshold; result `errorMessage` matches `watchdog: no codex output for {N}m {S}s` (`watchdog.integration.test.ts`) 2. ✅ Child emits events every (threshold − 1s) → not killed (`watchdog.test.ts: "does not fire when events arrive every (threshold - 1s)"`) 3. ✅ `outputInactivityTimeoutMs: null` disables the watchdog (`resolveCodexInactivityTimeout` returns `disabled`; `execute.ts` skips watchdog construction and logs a startup warning) 4. ✅ Real subprocess reaped well within `threshold + 6s` — 250 ms threshold, 290 ms wall clock in CI 5. ✅ Adapter-level fault → `outcome === "failed"` per `heartbeat.ts:5860`. NEE-79-class hangs <1h get caught at the adapter, not the platform-level safety net Post-rebase verification (head `2a8703fab`, rebased onto master `69a368ed5`): ``` $ pnpm --filter @paperclipai/adapter-codex-local typecheck # clean $ pnpm --filter @paperclipai/adapter-codex-local exec vitest run Test Files 11 passed (11) Tests 64 passed (64) ``` ## Risks - Low risk. Behind a default-on watchdog that only fires after 7m of zero parsed JSON events. Operators can disable it with `outputInactivityTimeoutMs: null` for known-slow tasks - The kill path reuses the same `process.kill(-pgid, signal)` pattern that `runChildProcess` already uses for its terminal-result cleanup, so signal semantics match the existing code path - `timedOut: false` is preserved on watchdog fire — the platform-level timeout outcome is unchanged, only the `failed`-vs-success classification flips. No behavioral shift for already-failing runs - Sandbox/SSH execution targets: the watchdog fires and emits the structured log, but the kill is best-effort because remote pids aren't owned by this process. The platform-level 1h safety net still applies. Out of scope for NEE-81 by design ## Model Used - Provider: Anthropic Claude - Model: claude-opus-4-7 - Mode: Claude Code (extended thinking, tool use) ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have 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 (N/A — no UI changes) - [x] I have updated relevant documentation to reflect my changes (`agentConfigurationDoc` for `outputInactivityTimeoutMs`) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green (re-running on the rebased head) - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (P2 addressed; review threads resolved) - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Neeraj Kumar Singh <b.nirajkumarsingh@hotmail.com> Co-authored-by: Devin Foley <devin@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing> |
||
|
|
5ebbe67ebd |
fix(workspace-runtime): base fresh worktrees on origin/master and refresh unstarted reuses (#8412)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agent work runs inside git worktrees created by the workspace runtime, each branched from a configured base ref (typically the repo's default branch) > - When the local `master` is stale or ahead of `origin/master` (committed but unpushed work, or local-only commits), a freshly created worktree inherits that divergence — so an unrelated task branch silently carries commits it never intended to touch > - This surfaced as a docs-only task whose PR accidentally pulled in unrelated changes from a diverged local master > - The base for a fresh worktree should be resolved authoritatively to the remote-tracking ref (`origin/<branch>`), and an idle/unstarted reused worktree should be safely fast-forwarded — without ever destroying in-progress work > - This pull request makes both behaviors explicit in the workspace runtime > - The benefit is that task branches start from a clean, authoritative base, eliminating accidental inclusion of unrelated local changes ## Linked Issues or Issue Description This is a bug fix. No public GitHub issue exists, so describing it inline following the Bug Report template: **What happened** A task intended to change only docs produced a PR that also contained unrelated changes pulled in from `master`. The root cause: when a new worktree is created from a configured local branch (e.g. `master`), the worktree inherits whatever that local branch points at. If the local `master` has committed divergence from `origin/master` (unpushed or local-only commits), that divergence leaks into the new task branch. The leak comes from committed local-vs-`origin/master` ref drift, not uncommitted working-tree changes (each worktree has its own working tree). **Expected behavior** A fresh worktree should be based on the authoritative `origin/master` head so unrelated local commits never seed a task branch. **Steps to reproduce** 1. Have a local `master` that is ahead of `origin/master` (committed but unpushed work). 2. Create a new worktree/task branched from `master` via the workspace runtime. 3. Open a PR from that branch — it carries the unrelated local commits. **Deployment mode** Self-hosted / local workspace runtime. ## What Changed - Fresh worktrees now resolve their base ref authoritatively: a configured local branch (e.g. `"master"`) is mapped to its `origin/<branch>` remote-tracking counterpart so unpushed/ahead local commits can never seed a task branch. Remote-tracking refs, SHAs, and tags are used verbatim; an unset/`HEAD` base falls back to the detected default branch. The resolved ref is recorded (`repoRef`) so downstream drift checks stay accurate. - If a configured local branch has no matching `origin/<branch>`, the runtime warns and falls back to the local ref rather than failing. - On reuse, a *provably unstarted* worktree (no commits past base + clean tree including untracked files) is fast-forwarded to the latest `origin/master`. Started or dirty worktrees keep the prior warn-only behavior, so in-progress work is never reset. Only remote-tracking bases are eligible for the refresh. ## Verification - `cd server && npx vitest run src/__tests__/workspace-runtime.test.ts` - 5 new tests cover: local-branch→`origin/<branch>` mapping, no-remote fallback warning, unstarted-reuse fast-forward, and that started/dirty worktrees are left untouched. - Result: 65 passed. 1 pre-existing failure (`auto-detects the default branch via symbolic-ref when origin/HEAD is set`) is unrelated to this change and fails only due to the test host's git default-branch config (test setup runs `git push -u origin main master` but the local default branch is `main`); it also fails on `master`. ## Risks - Low risk. The refresh path is intentionally conservative: it only fast-forwards worktrees that are provably unstarted (zero commits past base and a fully clean tree, including untracked files) and only when the base is a remote-tracking ref. Started or dirty worktrees fall through to the existing warn-only drift behavior, so no in-progress work can be destroyed. - Behavioral shift: fresh worktrees configured against a local branch will now base on `origin/<branch>` instead of the local ref. This is the intended fix; the only case it changes is when local and remote have diverged. ## Model Used Claude — `claude-opus-4-8` (extended thinking, tool use / code execution via Claude Code). ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] If this change affects the UI, I have included before/after screenshots (N/A — no UI changes) - [x] I have updated relevant documentation to reflect my changes (N/A — no doc changes needed) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green (pending CI run) - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (pending review) - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.621.0-canary.2 |
||
|
|
a937b89a47 |
fix(daytona): valid memory input in env config form + size presets (#8389)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Environments are configured through a JSON-schema-driven form (`JsonSchemaForm`), and each sandbox provider (here, Daytona) supplies a manifest describing its fields > - In the Daytona environment config form, the "memory" field rendered as a free-text input; on save the value round-tripped to `0`, producing a server-side "number must be greater than zero" error even when the user typed a valid number like `2` > - Rather than patch the free-text input, memory is now a true dropdown of the sandbox sizes Daytona actually supports, so an invalid value can no longer be typed or coerced > - The dropdown leads with a blank "None" row that is selected by default (meaning "not configured — use Daytona's defaults"); `0` is never offered because it is not a valid configuration > - The benefit is that operators pick a valid memory size from a constrained list, it saves correctly as an integer, and leaving it unset cleanly omits the field instead of submitting `0` ## Linked Issues or Issue Description No public GitHub issue exists; describing the bug inline per the bug report template. ### What happened? In the Daytona environment configuration form, the memory field is a free-text input labelled "gigabytes of RAM". Entering a value such as `2` and saving coerced the value to `0`, and the server rejected the save with "the number must be greater than zero". There was no way to enter a valid memory size through the form. ### Expected behavior Selecting a valid memory size (e.g. `2`) keeps that value and saves cleanly as an integer. Leaving memory unset is valid and submits no value (Daytona defaults apply). `0` is never selectable. ### Steps to reproduce 1. Open the environment configuration form for a Daytona sandbox provider. 2. In the memory field, type `2`. 3. Click Save. 4. Observe the value becomes `0` and the form errors with "the number must be greater than zero". ## What Changed - Daytona manifest: `memory` is now an `enum` of the supported sandbox sizes `[1, 2, 4, 8]` (GiB). It stays optional, so "not configured" remains valid. `0` is not in the list. - `JsonSchemaForm` `EnumField`: optional enums now render a leading blank **None** row that is selected by default when no value is set, letting the user express "not configured" and clear a previous selection (Radix `Select` forbids an empty-string item value, so the unset state maps to a sentinel that translates back to `undefined`). - `JsonSchemaForm` `EnumField`: when every enum option is numeric, the selected value is coerced back to a number on change so the payload keeps the schema's integer type (a stringified `"2"` would otherwise fail server-side integer validation — this is what fixes the original bug for the dropdown path). - Tests: added `EnumField` coverage in `JsonSchemaForm.test.tsx` (blank row present, no `0`, blank selected by default, numeric coercion, blank → unset) and Daytona manifest coverage in the plugin test (memory enum is `[1,2,4,8]`, excludes `0`, stays optional). ## Verification - `cd ui && npx vitest run src/components/JsonSchemaForm.test.tsx src/pages/CompanyEnvironments.test.tsx` → 16/16 passing (14 + 2). - `vitest run` in `packages/plugins/sandbox-providers/daytona` → 19/19 passing (incl. 3 new manifest tests). - `cd ui && npx tsc --noEmit` → clean. - Behavior: the memory field now renders as a dropdown showing **None / 1 / 2 / 4 / 8**, with **None** selected by default. Picking `2` stores the integer `2`; picking **None** clears the field so it is omitted from the payload (no `0`, no "must be greater than zero" error). ## Risks - Low risk. The blank-row + numeric-coercion changes live in `EnumField`. The blank row is only added for **optional** enums (required enums are unaffected); numeric coercion only triggers when every option is numeric, so existing string enums (`egressMode`, `backend`, `sessionStrategy`) are unchanged. The manifest change is scoped to the Daytona provider. ## Model Used Claude (Anthropic), Opus-class model, used via the Paperclip agent workflow (author + reviewer agents) with tool use and code execution. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above (none found) - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal Paperclip ticket id - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.621.0-canary.1 |
||
|
|
254b01d2af |
docs: drop contributor screenshot requirement in favor of cutter.sh bot (#8409)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Contributors follow `CONTRIBUTING.md` and the PR template when opening pull requests > - Those docs still tell contributors to manually capture and attach before/after screenshots for UI changes > - That requirement is now redundant: the `cutter.sh` bot automatically captures and posts before/after UI screenshots to every PR > - Asking contributors to also do it by hand adds friction and produces duplicate screenshots > - This pull request removes the manual screenshot obligation from `CONTRIBUTING.md` and the PR template, and documents that `cutter.sh` handles it > - The benefit is a clearer, lower-friction contribution flow that matches how screenshots actually get posted today ## Linked Issues or Issue Description No public GitHub issue. Underlying change: Our contributor docs and PR template instructed contributors to attach before/after screenshots for any UI change. We now run a bot (`cutter.sh`) that automatically captures and posts before/after UI screenshots to the PR, so the manual step is no longer needed. This change removes the manual requirement and instead documents that the bot handles screenshots, asking contributors to simply describe the visible change. ## What Changed - `CONTRIBUTING.md`: removed the "Before / After screenshots" requirement from the Path 2 PR checklist and from the "Writing a Good PR message" section; both now explain that the `cutter.sh` bot posts UI screenshots automatically and ask contributors to describe the visible change instead. - `.github/PULL_REQUEST_TEMPLATE.md`: updated the Verification guidance to note that `cutter.sh` posts before/after screenshots automatically, and removed the "include before/after screenshots" item from the checklist. - Issue templates were intentionally left unchanged — they only offer screenshots as an optional "if helpful" field, never a requirement. ## Verification - Docs-only change; no code paths affected. - `grep -rin "screenshot" CONTRIBUTING.md .github/` confirms no screenshot *requirement* remains — only the new `cutter.sh` wording and the optional "if helpful" fields in issue templates. - Render `CONTRIBUTING.md` and the PR template to confirm the wording reads cleanly. ## Risks Low risk — documentation-only change. No build, runtime, or migration impact. ## Model Used Claude (Anthropic), model `claude-opus-4-8`, extended thinking with tool use. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass (docs-only; no tests apply) - [ ] I have added or updated tests where applicable (N/A — docs-only) - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green (pending CI) - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (pending review) - [x] I will address all Greptile and reviewer comments before requesting mergecanary/v2026.621.0-canary.0 |