mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 02:00:52 +01:00
ed97b4130efe68232dc0749cd1fe9bc359d9b184
3028
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
ed97b4130e |
Exclude built-in resources from company exports
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
8162a52013 |
Add built-in resources migration journal entry
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
238b4ab0ce |
Put built-in routines section last
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
cdea5bd642 |
Separate built-in routines on routines page
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
dc5cbb7d9a |
Enforce Reflection Coach mutation gates
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
e0b0d410ee |
test reflection coach apply gate
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
1b472f7363 |
Auto-provision Reflection Coach for fresh companies
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
e5c627ea9b |
Fix built-in routine stock hash normalization
Normalize built-in routine defaults through the same projection used by persisted routine status checks so pristine bundles do not report operator_modified after a clean reconcile. Add regression coverage for the status read path after Reflection Coach materialization. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
81d8c90e73 |
Add Reflection Coach routine controls
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
c64671e738 |
Add Reflection Coach built-in bundle status UI (PAP-13099)
Implements the bundle status panel for the Reflection Coach built-in agent on
AgentDetail, per the PAP-13097 UX spec and the PAP-13098 server contract:
- ResourceStatusChip: readiness + drift chip grammar (ready/needs-setup/missing/
update-available/drifted/schedule-off), token-only via brandChipBadge, glyph +
word so state is never color-alone (WCAG 1.4.1).
- BuiltInBundlePanel: adapter/skill/instructions/routine rows with per-resource
Update/Reset/Recreate actions (confirm dialogs, ux-spec §8 copy), View links,
and the zero-token-by-default routine row. Adapter readiness derives from the
agent lifecycle status; skill/instructions/routine from state.resources.
- Scoped per-resource reset wired to built-in-agents/:key/reset { resources:[kind] }
(re-materializes one resource to the newest shipped default, preserving other
edits and adapter credentials); Configure opens the existing modal.
- API client: BuiltInAgentBundleMeta + BuiltInManagedResourceState types,
resources[] on BuiltInAgentState, scoped reset + reconcile.
- Storybook board + BuiltInBundlePanel.test.tsx (7 tests). tsc, token-gates,
and tests green.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
|
||
|
|
7e0d9bac4b |
Implement Reflection Coach built-in bundle server support
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
c3e45912ad |
Register reflection-coach in shipped catalog test fixture (PAP-13095)
The Reflection Coach built-in source bundle (bc944f529) added the bundled reflection-coach skill and regenerated catalog.json, but the shipped-catalog enumeration test still expected the prior 12-key bundled set. Add the new key so the catalog key-set and count assertions match the shipped catalog. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
874414ea5c |
Add Reflection Coach built-in source bundle (PAP-13076)
Phase 1 of PAP-13031: markdown-backed shipped defaults for the built-in Reflection Coach — agent AGENTS.md, paused-by-default recent-agent-reflection routine template, and the bundled reflection-coach operations skill. Grounded in the live coach but cleaned up: adds the interaction-gated apply model (displayed diff + accepted interaction + separate follow-up run) now that the built-in ships with skill/instruction update permissions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
e341c878d6 |
Gate built-in agents behind experimental flag
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
622e0cf799 | Fix built-in agents route | ||
|
|
41ebe3579c | Document built-in agent OpenAPI routes | ||
|
|
248a8d2e2d | Fix server CI test expectations | ||
|
|
0aee005b1f | Reject stale built-in approval setup retries | ||
|
|
bce8dacb21 | Address built-in agent review feedback | ||
|
|
d6f73eb1cf | Fix UI token gate violations | ||
|
|
c35876aa40 |
Fix built-in agent roster name collapsing under chip cluster
At narrow widths the agent name could collapse when the built-in badge and setup chip cluster stayed at full width. Give the name a readable floor and let the lower-priority chip cluster wrap instead. Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
c1d8d98adc |
Fix built-in agent badge token usage
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
4e7fc07e2e | Fix built-in agents checklist test command | ||
|
|
a71e4e6927 |
Built-in agents P2: roster badges, detail banner, configure modal, gate
Implements all UI surfaces for built-in agents (PAP-12978) against the P3 ux-spec (PAP-12977): - InlineBanner: token-backed info/warning banner primitive (brandBanner tokens) - BuiltInAgentBadge / BuiltInLifecycleChip: provenance + lifecycle chips - Roster (Agents page + org tree + sidebar): Built-in badge, Needs-setup / Pending-approval chip, inline Set up button, and a Built-in filter tab - AgentDetail: provenance banner, Reset to defaults, pause-confirm dialog with dependency warning, Terminate hidden for built-ins - ConfigureBuiltInAgentModal: reuses AgentConfigForm adapter/model pickers (no second model picker), optional budget, provisions via the API - BuiltInAgentGate: loading / setup / pending-approval / paused / ready states - Use-while-paused toast helper (single View-agent link, per D9) - EmptyState gains an optional title; AgentActionButtons gains pauseConfirm + hideTerminate; forward-compatible with the server's board-approval flow - Component tests for gate states + modal submit path; Storybook story + /design-guide entries for the new components Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
8527883759 | Freeze pending approval agent config | ||
|
|
3cbc4e7df7 | Fix built-in agent approval gating | ||
|
|
f1f629dbd0 |
Add built-in agent routes and gate
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
4d5ad7408d |
Add built-in agent provisioning foundation
Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
4d50fa9f29 |
chore(lockfile): refresh pnpm-lock.yaml (#9304)
Auto-generated lockfile refresh after dependencies changed on master. This PR only updates pnpm-lock.yaml. Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com> |
||
|
|
b13eb5b2b5 |
Skill Studio: three-pane skill IDE with sandboxed test runs (#9241)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The Skills Manager gives operators a reusable skill layer, but iteration still required manual edits, ad hoc prompts, and indirect run inspection. > - Skill authors need a focused workflow for editing skill files, saving representative test inputs, and running those inputs through an agent without exposing harness tasks as normal company work. > - The backend therefore needs durable test inputs, reusable run templates, hidden harness issues, scoped run execution, retention metadata, and read-containment rules around hidden work. > - The frontend needs a three-pane Studio that keeps skill files, saved inputs/templates, and run output/history visible together while preserving the existing design system and token rules. > - This pull request ships that Skill Studio surface end to end: database migrations, shared contracts, server APIs/services, hidden harness execution behavior, UI routes/components, and focused tests. > - The benefit is faster and safer skill iteration, with inspectable outputs and fewer ways for internal harness work to leak into normal task lists, costs, or adjacent read APIs. ## Linked Issues or Issue Description No public GitHub issue exists for this feature. Feature request summary: - Problem: Skill authors need to edit and test company skills in one place instead of switching between the skill detail page, task creation, run output, and manual prompt history. - Proposed solution: Add a Skill Studio workbench with saved inputs, reusable templates, hidden sandboxed test runs, live run status, output inspection, run history, rerun/delete controls, and frontmatter-aware editing. - Expected users: Paperclip operators and agent-company maintainers who create, fork, import, and tune skills. - Related public PRs: Supersedes #9205, which was replaced so the public PR branch name follows contributor policy. - Duplicate search: searched public GitHub issues and PRs for "Skill Studio"; no other active public issue or PR directly covers this feature. ## What Changed - Added database migrations for Skill Studio test inputs, test runs, test run retention, and reusable run templates. - Added shared Skill Studio types, validators, route helpers, frontmatter utilities, and status handling. - Added server services and routes for saved inputs, test runs, templates, reruns, terminal-run deletion, hidden harness issue execution, and run-detail hydration. - Strengthened hidden-issue read containment across issue-adjacent routes and cost rollups used by skill test harness work. - Added the Skill Studio UI with skill file editing, frontmatter editing, saved inputs, templates, run creation/cancel/rerun/delete flows, output rendering, history, route support, and responsive pane behavior. - Added focused backend, shared, and UI tests for the new APIs, routing logic, editor/run behavior, hidden-issue containment, and migration safety. - Rebased onto current `master`, removed the generated lockfile diff from the PR, and verified no workflow files are changed. ## Verification - [x] `pnpm --filter @paperclipai/db check:migrations` - [x] `pnpm check:token-gates` - [x] `pnpm exec vitest run server/src/__tests__/company-skills-service.test.ts server/src/__tests__/company-skills-routes.test.ts server/src/__tests__/company-skill-test-runs-service.test.ts ui/src/lib/skill-studio.test.ts ui/src/pages/SkillStudio.test.tsx` — 5 files, 132 tests passed - [x] Greptile review on the latest PR head - [x] GitHub PR checks on the latest PR head ## Risks - Medium risk because this is a broad feature touching database schema, server orchestration, issue visibility, and a large UI surface. - Hidden harness issue containment is security-sensitive; this PR includes regression coverage for adjacent read paths and cost rollups. - The new migrations are additive and use idempotent guards where applicable, but deployed databases that previously tested draft migration numbers should still be checked carefully. - The UI depends on a new resizable panels package in `ui/package.json`; the lockfile is intentionally left to repository automation. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex, GPT-5 coding agent with shell, git, and GitHub CLI tool use. Earlier feature commits include assistance from other Paperclip coding agents; this PR preparation, rebase, cleanup commit, and PR body were completed by OpenAI Codex in a Paperclip worktree. ## 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> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>canary/v2026.709.0-canary.10 |
||
|
|
3571b6c38b |
feat(models): add gpt-5.4-mini to Codex and OpenCode selection (and openai/gpt-5.5 to OpenCode) (#4357)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agent runtimes are selected through adapters, and each adapter exposes the model IDs an operator can pick in the UI > - The `codex_local` and `opencode_local` adapters hardcode those lists, so a newly released model stays unreachable until it is added > - `gpt-5.4-mini` is available via both the Codex CLI and the OpenCode CLI, but neither adapter lists it; `openai/gpt-5.5` is likewise missing from `opencode_local` > - This pull request adds those entries, and deliberately keeps `gpt-5.4-mini` out of the Codex Fast mode allowlist because the model does not support Fast mode > - The benefit is that operators can select these models from the UI instead of falling back to a manual model ID, and Fast mode fails closed rather than sending unsupported overrides to the CLI ## Linked Issues or Issue Description No existing issue covers this. Describing it inline, following the feature request template: ### Problem or motivation `gpt-5.4-mini` is absent from the `models` list of both the `codex_local` and `opencode_local` adapters, and `openai/gpt-5.5` is absent from `opencode_local`. (`codex_local` already ships `gpt-5.5` — it is the default model on master.) Operators who want these models must type a manual model ID. For `codex_local` that has a real side effect. `isCodexLocalFastModeSupported` treats any *unknown* model as Fast-mode-capable and passes `service_tier="fast"` and `features.fast_mode=true` through to the CLI. Because `gpt-5.4-mini` does not support Codex Fast mode, an agent configured with a manual `gpt-5.4-mini` model ID and `fastMode` enabled silently sends overrides the CLI cannot honor. ### Proposed solution Add the three missing entries to the two `models` lists, and leave `CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS` untouched. Listing `gpt-5.4-mini` in `models` is precisely what makes it a *known* model, so `isCodexLocalFastModeSupported` returns `false`, `buildCodexExecArgs` omits the Fast mode overrides, and `fastModeIgnoredReason` is surfaced to the operator. ### Alternatives considered Adding `gpt-5.4-mini` to `CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS` as well — rejected, because the model does not support Fast mode and the overrides would be rejected at run time. Leaving the models unlisted so operators keep using manual IDs — rejected, because that is the path that silently enables Fast mode for a model that cannot use it. ### Roadmap alignment Not core roadmap work. `ROADMAP.md` does not plan adapter model-list maintenance; this is routine upkeep as upstream CLIs ship new models. ## What Changed - Add `gpt-5.4-mini` to the `codex_local` adapter's `models` list, positioned after `gpt-5.4` (newest-first ordering). - Add `openai/gpt-5.5` and `openai/gpt-5.4-mini` to the `opencode_local` adapter's `models` list. - Add a `buildCodexExecArgs` test asserting Fast mode is ignored for `gpt-5.4-mini`. `CODEX_LOCAL_FAST_MODE_SUPPORTED_MODELS` is intentionally unchanged. No behavior changes to existing models or adapter logic. ## Verification ``` pnpm --filter @paperclipai/adapter-codex-local --filter @paperclipai/adapter-opencode-local typecheck npx vitest run packages/adapters/codex-local packages/adapters/opencode-local ``` Both pass: typecheck clean on both packages, and 22 test files / 133 tests green, including the new `ignores fast mode for gpt-5.4-mini` case. ## Risks Low risk. The change is additive: three entries appended to two model-selection lists, plus one test. No default model changes, no adapter logic changes, no migrations. One behavioral shift is intended. An operator who had `gpt-5.4-mini` configured as a *manual* model ID with `fastMode` enabled was getting Fast mode overrides passed through to the Codex CLI. After this change `gpt-5.4-mini` is a known model, so those overrides are dropped and `fastModeIgnoredReason` explains why. ## Model Used - OpenAI Codex CLI with GPT-5 / GPT-5.5-assisted code editing (the original commits on this branch). - Anthropic Claude Opus 4.8 (`claude-opus-4-8`, 1M context, extended thinking, tool use) for the master merge, conflict resolution, and the scope reduction in the latest commit. ## 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 the GitHub PR list for similar or duplicate PRs and confirmed this one is not a duplicate - [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 (N/A; the adapter docs describe Fast mode support, which is unchanged) - [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: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Andrew Aymeloglu <aaymeloglu@gmail.com>canary/v2026.709.0-canary.9 |
||
|
|
1c75a46c10 |
feat(ui): add waiting-on-live-work blocked notice (#9298)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Operators rely on the issue detail thread to understand whether a task is blocked, live, or waiting on another task. > - A blocked issue can have a healthy blocker chain where downstream work is actively running and the parent will resume automatically. > - Showing that case with the same amber blocked notice as a stalled or attention-needed blocker makes the state look more severe than it is. > - The UI already receives blocker-attention state, blocker summaries, and company live-run ids, so this can be clarified without a new API shape. > - This pull request adds a blue "Waiting on live work" notice for covered blocker chains while preserving the existing amber notice for the other blocked states. > - The benefit is that operators can distinguish healthy queued work from blocked work that needs intervention. ## Linked Issues or Issue Description Refs #3820 Refs #8271 Related PR: #3877 Supersedes #9295 ## What Changed - Added a blue `IssueBlockedNotice` variant when `blockerAttention.state` is `covered` and the blocker chain has live work. - Rendered blocker-chain progress as done, running, and queued steps, including a "Now running" row for live terminal blockers. - Preserved the existing amber blocked notice for stalled, attention-needed, ordinary blocked, and successful-run handoff states. - Plumbed the existing `liveIssueIds`, `blockedBy`, and `blockerAttention` data from issue detail into the chat-thread blocked notice. - Added regression coverage around the covered live-work state, the no-confirmed-live fallback, numeric step ordering, and amber fallback states. - Hardened a low-trust server route test cleanup helper so CI deletes heartbeat run events before deleting heartbeat runs. ## Verification - `pnpm check:token-gates` - `pnpm --filter @paperclipai/ui typecheck` - `pnpm exec vitest run ui/src/components/IssueBlockedNotice.test.tsx` - GitHub PR workflow is green on head `52ab6d9076ce233c183bf7133fa666e8597b6765`. - Greptile check is green on head `52ab6d9076ce233c183bf7133fa666e8597b6765` with zero unresolved review threads. ## Risks Low runtime risk: the product change is frontend-only and uses data already returned to the issue detail page. The main risk is visual regression in the blocked notice; the change keeps non-covered states on the existing amber path and adds focused regression coverage. The server-side change is test-only cleanup for an existing CI shard failure. > 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 using GPT-5, tool-use enabled in a repository workspace. The runtime did not expose a more specific model build id or context-window size. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.709.0-canary.8 |
||
|
|
97e0752158 |
Fix work timeline visible stats and kickoff attribution (#9271)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The work timeline helps operators understand what agents did, when they did it, and who kicked off each run > - Timeline statistics should describe the window the operator is viewing, not hidden work outside the viewport > - Kickoff chips should point to the run that was actually closest to the triggering edge, not stale later runs on the same issue > - This pull request scopes timeline summary stats to the visible window and deduplicates kickoff attribution to the nearest matching run > - The benefit is that operators get a more accurate, less misleading timeline while scanning agent work ## Linked Issues or Issue Description No matching public GitHub issue was found. Public duplicate search found no open PR for "work timeline visible window kickoff". ### What happened? Work timeline summary stats could count hidden spans outside the selected visible window, and kickoff attribution could appear on a stale matching run instead of the closest run associated with the edge. ### Expected behavior Visible timeline stats should reflect only the current visible range, and each kickoff edge should attach to the nearest matching run. ### Steps to reproduce 1. View a work timeline with agent spans that begin before or end after the selected visible window. 2. Compare the summary stats against only the spans visible in the viewport. 3. View repeated runs for the same actor and issue that share a kickoff edge. 4. Check which run gets the kickoff chip. ### Paperclip version or commit Current `origin/master` before this PR. ### Deployment mode Board UI. ## What Changed - Filters timeline summary stats to the visible time window. - Passes visible-window metadata into the work timeline chart and page state. - Assigns each kickoff edge to only the closest matching run, with deterministic tie-breaking. - Adds focused regression coverage for visible stats and stale kickoff attribution. ## Verification - `pnpm exec vitest run ui/src/components/timeline/WorkTimelineChart.test.tsx ui/src/lib/timeline/layout.test.ts ui/src/pages/Timeline.test.tsx` -- 38 tests passed. - `pnpm check:token-gates` -- all gates clean. - `git diff --check origin/master...HEAD` -- passed. ## Visual Evidence Public review artifacts for the user-visible timeline behaviours. The SVGs use sanitized run labels and no internal Paperclip issue identifiers.   Artifact gist: https://gist.github.com/cryppadotta/dc2645d54c4bc56ffc0323224b3ea4bf ## Risks - Low risk. The change affects timeline rendering and summary calculations only; the main risk is a subtle difference in which run gets a kickoff chip when multiple runs are very close together. > 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. See `CONTRIBUTING.md`. ## Model Used OpenAI Codex coding agent based on GPT-5, tool-enabled shell workflow. Exact hosted model variant and context window were not exposed by the runtime. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have 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.709.0-canary.7 |
||
|
|
7cf0d3ebb0 |
Require health readiness for Paperclip dev services (#9269)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents often run against managed workspace runtime services, including reusable Paperclip dev servers > - A running process and an open root URL are not enough to prove the Paperclip API is actually ready > - If the API health endpoint is still failing, agents can reuse a service that looks alive but cannot safely serve the board or API clients > - This pull request makes Paperclip dev runtime readiness probe the resolved `/api/health` endpoint > - The benefit is that runtime service reuse waits for the same health signal operators and agents depend on ## Linked Issues or Issue Description No matching public GitHub issue was found. Public duplicate search found no open PR for "workspace runtime health readiness". Bug report: ### What happened? A managed Paperclip dev runtime service could satisfy HTTP readiness at the exposed base URL even when the Paperclip health endpoint was returning an unhealthy status. ### Expected behavior Paperclip dev runtime services should not be considered ready until their health endpoint succeeds. ### Steps to reproduce 1. Start a workspace runtime service named `paperclip-dev` whose base URL responds successfully. 2. Make that same service return HTTP 503 from `/api/health`. 3. Ask Paperclip to ensure the runtime service for a run. 4. Observe that the service can be reused even though the API health endpoint is not ready. ### Paperclip version or commit Current `origin/master` before this PR. ### Deployment mode Local workspace runtime service management. ## What Changed - Resolve Paperclip dev runtime readiness checks to the service health URL before polling. - Surface readiness errors with the actual health URL that failed. - Add a regression test that fails when `/api/health` returns HTTP 503 even if the service process is running. ## Verification - `pnpm exec vitest run server/src/__tests__/workspace-runtime.test.ts` — 81 tests passed. - `git diff --check origin/master...HEAD` — passed. ## Risks - Low to medium risk. This tightens readiness for Paperclip dev runtime services, so a service that previously looked ready while unhealthy will now fail fast instead of being reused. > 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, tool-enabled shell workflow. Exact hosted model variant and context window were not exposed by the runtime. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have 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.709.0-canary.6 |
||
|
|
3e63a7e3e5 |
Fail fast stalled Daytona Git network commands
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The Daytona sandbox provider executes agent commands inside ephemeral Daytona workspaces via `executeCommand` > - Git operations inside these workspaces can block indefinitely when remotes are unreachable or when git prompts for credentials interactively (e.g. via askpass or terminal prompts) > - When git blocks, it consumes the full 900s adapter RPC ceiling, which surfaces as a hard timeout crash on the Paperclip side rather than an actionable error > - This PR adds noninteractive credential defaults and a 120s cap on detected Git network subcommands so stalled operations fail fast with a useful message > - The benefit is that engineers and agents see an actionable error pointing at missing credentials or unreachable remotes instead of an opaque 900s RPC crash ## Linked Issues or Issue Description <!-- No public GitHub issue exists for this internal infrastructure fix. Describing the issue inline. --> **Bug: Daytona sandbox Git network commands stall for up to 900 seconds** **What happened?** `executeCommand` hangs for the full 900 s adapter RPC ceiling when a Daytona workspace git network command (push/fetch/pull/clone) prompts for credentials interactively or the remote is unreachable. The command blocks silently for up to 900 s then crashes with a generic timeout error that names no actionable root cause. **Steps to reproduce** Run any agent handoff that includes a `git push`, `git fetch`, or `git pull` to a remote inside a Daytona workspace where the remote is unreachable or credentials are missing. **Expected behavior** Command fails fast (within ~120 s) with an actionable error naming the unreachable remote or the missing noninteractive credential. **Deployment mode** Daytona sandbox provider (`packages/plugins/sandbox-providers/daytona`). Root cause: Daytona one-shot execution wrappers did not set `GIT_TERMINAL_PROMPT=0`, `GCM_INTERACTIVE=Never`, or disabled askpass helpers, so git blocked waiting for interactive terminal input; no per-operation timeout existed for network-bound git subcommands. ## What Changed - Added `GIT_TERMINAL_PROMPT=0`, `GCM_INTERACTIVE=Never`, `GIT_ASKPASS=echo`, `SSH_ASKPASS=echo`, `SSH_ASKPASS_REQUIRE=force` to all Daytona one-shot execution wrapper invocations so git never blocks waiting for a credential prompt; callers may override via the `env` parameter - Detects Git network subcommands (`push`, `fetch`, `pull`, `ls-remote`, `clone`, `remote update`, `submodule update`) and caps their timeout at 120 s instead of the full 900 s adapter RPC ceiling - Returns an actionable timeout message that names the unreachable remote or the missing noninteractive credential rather than propagating the raw SDK error - Adds two new Vitest tests: one verifying noninteractive credential defaults are injected, one verifying the 120 s network cap and the improved timeout message ## Verification - `corepack pnpm exec vitest run packages/plugins/sandbox-providers/daytona/src/plugin.test.ts --config packages/plugins/sandbox-providers/daytona/vitest.config.ts` — 40 tests pass - `corepack pnpm exec tsc -p tsconfig.json --noEmit` from `packages/plugins/sandbox-providers/daytona` — clean - `corepack pnpm check:no-git-push` — clean > **Known CI note:** The standalone provider package is intentionally excluded from the root workspace. Direct `corepack pnpm test` from the provider directory fails before running tests due to Vitest tsconfig-root resolution in a grafted checkout. The root-config Vitest invocation above is the passing test signal. ## Risks - **Low overall risk.** The new `GIT_TERMINAL_PROMPT=0` / askpass defaults only affect Daytona one-shot execution; they do not touch any shared git config or host environment. - Callers that previously relied on interactive credential prompts inside Daytona (an unlikely pattern for agent workspaces) will now fail fast instead of prompting — this is the intended behavior. - The 120 s network timeout applies only when the command string starts with a recognized git network subcommand, so non-network git operations and all non-git commands are unaffected. - No PII, telemetry schema, crypto, auth flow, or new external endpoint changes. ## Model Used Claude Sonnet 4.6 (`claude-sonnet-4-6`) — extended thinking mode, tool use, code execution. Anthropic Claude running via Paperclip Claude Code 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) - [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 - [ ] 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 merge --------- Co-authored-by: Harold Kim <harold.kim@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing>canary/v2026.709.0-canary.5 |
||
|
|
cf8b6e1bdd |
chore: trigger Docker build-and-push for lockfile refresh (post #9252)
Empty commit to trigger Docker workflow on the fixed lockfile lineage (
canary/v2026.709.0-canary.4
|
||
|
|
ea301442e8 |
chore(lockfile): refresh pnpm-lock.yaml (#9252)
Auto-generated lockfile refresh after dependencies changed on master. This PR only updates pnpm-lock.yaml. Co-authored-by: lockfile-bot <lockfile-bot@users.noreply.github.com> |
||
|
|
719da5f9b5 |
Harden environment deletion and expose delete blast radius (#9250)
## Thinking Path > - Paperclip manages AI agents that each have an associated execution environment (local, Kubernetes, etc.) > - Instance administrators can create and delete environments; currently the DELETE endpoint has no protection against deleting managed or in-use environments > - Deleting the managed local environment or the instance-default environment would break all agents using those environments with no path to recovery > - The endpoint also suffered a TOCTOU race: a check-then-delete pattern allowed the managed-local or default guard to pass if the environment's role changed between the read and the delete > - This pull request adds a blast-radius read endpoint so admins can preview impact, hard-blocks the dangerous deletes atomically, cleans up all dependent references after a valid delete, and fixes a concurrent creation race in ensureLocalEnvironment ## Linked Issues or Issue Description Fixes #9251 ## What Changed - **New endpoint** `GET /api/environments/:id/delete-blast-radius` (instance-admin gated): returns reference counts (agent defaults, workspace selections, issue selections, project selections, secret bindings, active leases, active setup sessions) and blocking reasons — no config, env-var values, or secret data returned. - **Atomic delete guard** `environmentService.removeIfDeletable(id)`: performs the DELETE with an inline `WHERE driver != 'local' AND NOT EXISTS (instanceSettings where defaultEnvironmentId = id)` predicate, eliminating the TOCTOU race between the app-level check and the DB write. - **Route hardening**: `DELETE /environments/:id` now calls `getDeleteBlastRadius` first (app-level check + logging), then calls `removeIfDeletable` (atomic guard). If the atomic guard returns null the route fetches a fresh blast-radius snapshot and rejects with a 409 Conflict carrying `deleteBlockedReasons`. - **Reference cleanup on valid delete**: after a successful delete, the route clears environment selections on all company execution workspaces, issues, and projects; syncs env-var secret bindings to `{}` (removing bindings for the deleted environment); syncs config secret refs to `[]` for the environment target; and removes the SSH private-key secret if one was stored. - **Race fix in `ensureLocalEnvironment`**: the insert-or-nothing path now catches a `environments_name_idx` unique-constraint violation and falls through to the existing SELECT, treating the name conflict as idempotent. - **Shared types**: `EnvironmentDeleteBlastRadius` and `EnvironmentDeleteBlockedReason` exported from `@paperclipai/shared`. - **OpenAPI**: registers the new blast-radius endpoint; updates the delete-environment response schema to document 403/404/409. - **Tests**: 56 existing environment-route and service tests continue to pass; new service-level regression tests assert the atomic guard rejects `local`-driver environments and instance-default environments and succeeds for deletable ones. ## Verification ``` corepack pnpm exec vitest run \ server/src/__tests__/environment-routes.test.ts \ server/src/__tests__/environment-service.test.ts # 56 tests, all passing corepack pnpm --filter @paperclipai/shared typecheck node scripts/ensure-plugin-build-deps.mjs cd server && ../node_modules/.bin/tsc --noEmit ``` ## Risks - **Blast-radius endpoint auth**: guarded by `assertCanAccessInstanceEnvironments`, the same gate as the existing environment-list and delete routes. Non-admin callers receive 401/403 before any data is returned. - **Atomic guard may reject a delete that the app-level check passed**: this is intentional — it means the environment became protected between the read and the write. The caller receives a fresh blast-radius snapshot explaining why. - **Secret cleanup ordering**: cleanup runs after the atomic DELETE succeeds, in parallel across companies. If cleanup partially fails the environment row is already gone; partial-cleanup state is recoverable by re-running the sync operations. Risk: low — these are idempotent upsert/sync operations. - **ensureLocalEnvironment race fix**: swapping a unique-constraint error for an idempotent SELECT adds one extra query on the conflict path. This path is rare (only fires during concurrent boot) and is significantly safer than the previous behavior. - **No migration**: all changes are application-level; no schema changes required. ## Model Used - Provider: Anthropic - Model: claude-sonnet-4-6 (Claude Sonnet 4.6) - Context window: 200k tokens - Mode: agentic tool use via Paperclip agent system (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. `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 - [ ] 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 merge --------- Co-authored-by: Priya Raman <priya.raman@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Harold Kim <harold.kim@paperclip.ing>canary/v2026.709.0-canary.3 |
||
|
|
1b16f9611c |
feat(telemetry): document credential health retention (#9248)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The shared telemetry package (`packages/shared/src/telemetry`) defines the public contract for first-party telemetry events — event names, dimension shapes, and now retention windows > - A new telemetry event, `codex.credential_health`, carries credential-observability fields (enums, booleans, counts, coarse buckets) — no token material and no PII > - The retention window for this event and its class was undocumented at the contract level, leaving data-infra and reviewers without a discoverable source of truth > - This pull request adds `retention.ts` as the canonical retention-contract surface, assigns `codex.credential_health` to the `operational_enum_count` class (90-day window), exports the contract from the shared package, and updates the README > - The benefit is that the retention window is discoverable from the event definition rather than being implicit pipeline knowledge, and the no-token/no-PII note is locked in a contract test rather than relying on prose ## Issue Description No public GitHub issue exists for this change. Inline description follows the [feature request template](.github/ISSUE_TEMPLATE/feature_request.yml): ### Problem or motivation `packages/shared/src/telemetry/` applies a 90-day retention window to `codex.credential_health` events at the pipeline level, but this policy is not stated anywhere in the shared telemetry contract. Without a discoverable retention declaration, reviewers and data-infra must read pipeline configuration to understand retention behaviour — there is no contract-level source of truth. The `codex.credential_health` event carries only enums, booleans, counts, and coarse buckets — no token material and no PII. ### Proposed solution Add a `retention.ts` module to the shared telemetry package that defines the `operational_enum_count` retention class (90-day window) and maps `codex.credential_health` to it. Export the contract from the package index and add a focused contract test. Update the README with a Retention section and a pointer in the Public Sources table. This is additive documentation only — no runtime paths change. ### Alternatives considered Keep retention implicit in pipeline configuration only. Rejected: this leaves no discoverable, versioned contract for reviewers or data-infra, and means every consumer must read pipeline config to understand retention semantics. A schema-level declaration is the correct long-term home. ### Roadmap alignment Aligns with the telemetry contract hardening track — making implicit operational knowledge explicit and testable at the shared-package level. ## What Changed - **`packages/shared/src/telemetry/retention.ts`** (new): defines `RETENTION_DAYS` (class → days) and `EVENT_RETENTION_CLASS` (event name → class). `operational_enum_count` is the only class: 90-day window for enum/count/bucket events with no token material or PII. `codex.credential_health` is the first entry. The `string` key type is intentional to accommodate cross-system events (e.g. the Codex CLI) not yet promoted to the first-party `PaperclipEventName` schema. - **`packages/shared/src/telemetry/retention.test.ts`** (new): three focused assertions — `operational_enum_count` is 90 days, `codex.credential_health` is assigned that class, and the resolved window is 90 days. - **`packages/shared/src/telemetry/index.ts`**: exports `RETENTION_DAYS`, `EVENT_RETENTION_CLASS`, and `RetentionClass` from the shared package. - **`packages/shared/src/telemetry/README.md`**: adds `retention.ts` to the Public Sources table and a new Retention section with a class reference table and guidance for future assignments. ## Verification - `git diff --check` passes (no whitespace errors) - `pnpm --filter @paperclipai/shared exec vitest run src/telemetry/retention.test.ts src/telemetry/readme-contract.test.ts` — runs the new contract tests and the existing readme-contract test - `pnpm --filter @paperclipai/shared typecheck` — confirms the new exports compile cleanly - CI gates green ## Risks Low risk. This is a documentation-only addition: - No new telemetry event, dimension, emitter, or schema change - No runtime code paths changed - The new file is tree-shaken away in any consumer that doesn't import from it - `satisfies Record<string, number>` on `RETENTION_DAYS` ensures the type stays correct as new classes are added ## Model Used Claude Sonnet 4.6 (`claude-sonnet-4-6`) — Anthropic, 200k context window, tool use enabled, no extended thinking mode. Used for code authoring and PR composition. ## 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: Harold Kim <harold.kim@paperclip.ing> Co-authored-by: Paperclip <noreply@paperclip.ing> Co-authored-by: Harold Kim <harold-kim@paperclip.ing>canary/v2026.709.0-canary.2 |
||
|
|
eedc7ddef2 |
Make ACP the default engine for local adapters (#9238)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Adapter packages are the bridge between the control plane and local agent harnesses such as Claude Code, Codex, and Gemini CLI. > - ACP support was concentrated in a separate `acpx_local` adapter, which made ACP feel like a separate agent choice instead of an execution capability of the harness adapters. > - Claude, Codex, and Gemini now have ACP-capable harnesses, so the native adapter should own ACP selection, fallback, config, transcript parsing, and environment diagnostics. > - The standalone ACPX adapter still needs a compatibility path for existing rows, but it should not be offered as an active adapter for new agents. > - This pull request moves the shared ACP runtime into `@paperclipai/acpx-engine`, wires Claude/Codex/Gemini local adapters to prefer ACP when prerequisites are available, and retires `acpx_local` to a tombstone. > - The benefit is one adapter per harness, richer ACP transcripts by default where possible, and a migration path for existing Claude/Codex ACPX agents. ## Linked Issues or Issue Description Closes #5932 — the broken default `acpx_local` Claude path is replaced by native `claude_local` ACP support, existing Claude/Codex ACPX rows migrate to native adapters, and new agents no longer choose the standalone ACPX adapter. Refs #4893 — original merged ACPX local adapter runtime that this PR replaces with native per-harness ACP engines. Refs #6590 — prior ACPX-Claude seamlessness work folded into the new native Claude ACP path. Refs #197 — related open generic ACP/Kiro adapter work; this PR does not close it because Kiro/custom generic ACP remains a separate adapter decision. Refs #7018 — related Kimi-specific `acpx_local` shell failure; this PR retires the built-in standalone adapter but does not add a native Kimi adapter. Refs #8864 — related ACPX prompt/API guidance PR; this PR moves runtime guidance into the shared/native ACP engine path instead of the old standalone adapter. Refs #8881 — related `acpx_local` POSIX shell failure from the old `acpx` pin; this PR updates ACP dependencies but does not claim custom/OMP ACP support as a first-class native adapter. Refs #8964 — related open `acpx_local` stderr cleanup PR; this PR makes the old runtime path obsolete for new agents but keeps it as a non-closing reference. Problem description: - The standalone `acpx_local` adapter duplicates Claude/Codex agent choices that already have first-class local adapters. - ACP should be an execution engine capability of each harness adapter when the underlying harness supports ACP. - Existing `acpx_local` agents should either migrate to native harness adapters or fail with an explicit retirement message instead of silently falling back to the process adapter. ## What Changed - Added `@paperclipai/acpx-engine` as the shared ACP execution, session-codec, CLI formatter, and UI parser package. - Wired `claude_local`, `codex_local`, and `gemini_local` to auto-select ACP by default when prerequisites pass, with `engine=cli` opt-out and `engine=acp` strict mode. - Added ACP config schema/UI fields, environment checks, session-codec preservation, transcript parsing, and adapter capability metadata for the native adapters. - Retired `acpx_local` to a server tombstone, removed its UI/package/runtime image surface, and added a migration for existing Claude/Codex ACPX agents. - Updated package manifests, lockfile, release tooling, docs, Kubernetes sandbox defaults, and tests. ## Verification - `corepack pnpm --filter @paperclipai/acpx-engine typecheck` - `corepack pnpm --filter @paperclipai/adapter-claude-local typecheck` - `corepack pnpm --filter @paperclipai/adapter-codex-local typecheck` - `corepack pnpm --filter @paperclipai/adapter-gemini-local typecheck` - `corepack pnpm --filter @paperclipai/acpx-engine exec vitest run` - `corepack pnpm --filter @paperclipai/adapter-claude-local exec vitest run src/server/acp.test.ts src/server/execute.acp-fallback.test.ts src/ui/build-config.test.ts` - `corepack pnpm --filter @paperclipai/adapter-codex-local exec vitest run src/server/acp.test.ts src/ui/build-config.test.ts` - `corepack pnpm --filter @paperclipai/adapter-gemini-local exec vitest run src/server/acp.test.ts src/ui/build-config.test.ts src/ui/parse-stdout.test.ts` - `corepack pnpm --filter @paperclipai/plugin-sdk ensure-build-deps && corepack pnpm --filter @paperclipai/server exec tsc --noEmit` - `corepack pnpm --filter @paperclipai/server exec vitest run src/__tests__/adapter-routes.test.ts src/__tests__/adapter-session-codecs.test.ts src/__tests__/adapter-models.test.ts` - `corepack pnpm --filter @paperclipai/ui typecheck` - `corepack pnpm --filter @paperclipai/ui exec vitest run src/adapters/metadata.test.ts src/adapters/adapter-display-registry.test.ts src/components/AgentConfigForm.test.ts src/components/AgentConfigForm.render.test.tsx src/components/transcript/RunTranscriptView.test.tsx` - `node --test scripts/bootstrap-npm-package.test.mjs scripts/release-package-map.test.mjs scripts/verify-release-registry-state.test.mjs` Note: the server typecheck script calls `pnpm` internally; this dev shell exposes pnpm through Corepack only, so I ran the two script steps manually with `corepack pnpm`. ## Risks - Migration changes existing `acpx_local` Claude/Codex agents to native adapter types and clears old ACPX task sessions/runtime state. - Custom ACP commands remain on the retired tombstone and will need a separate future adapter/plugin path. - ACP auto-selection depends on local Node and ACP server command prerequisites; remote and unsupported environments fall back to CLI unless `engine=acp` is explicit. - `@paperclipai/acpx-engine` is a new public package and needs npm trusted-publishing bootstrap before release automation can publish it. > 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 coding agent. Exact hosted model build and context-window size are not exposed in this runtime. Tool use included shell execution, repository editing, GitHub CLI operations, and local test/typecheck 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 - [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.709.0-canary.1 |
||
|
|
187a929d97 |
docs: explain Codex and Claude credential ownership
Squash-merges the adapter credential ownership doc PR. - Documents codex_local host-owns-auth topology and CODEX_HOME auth precedence - Documents claude_local snapshot-owns-auth topology (sandbox targets only) - Adds API-key vs ChatGPT-subscription guidance for high-concurrency fleets - Adds deferred config-validation warning spec for sandbox credential mismatches - Fixes: SSH scope mismatch (Greptile P1) and codex auth.json materialization note (Greptile P2) Co-Authored-By: Paperclip <noreply@paperclip.ing> |
||
|
|
3288ec4f47 |
chore: ignore materialized Paperclip runtime directory
Adds .paperclip-runtime/ to .gitignore so the materialized adapter credentials directory is never accidentally committed. |
||
|
|
c90e66bdd6 |
feat(ui): design-system component convergence — Card/Badge adoption, multiplicative radius ladder, unified list surfaces (#9240)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Its UI is governed by a design system (`DESIGN.md` + the token layer in `ui/src/index.css`, merged in #9134) whose first principle is "one way to say each thing" — one Card, one Badge, one nav row > - After the token extraction landed, ~35 files still hand-rolled card containers, ~45 files hand-rolled pill spans, the sidebar agents section duplicated the nav-row chrome, and the inbox and tasks lists rendered the same task rows two subtly different ways > - Each divergence is a place where a future design change (radius, hover language, status vocabulary) silently misses surfaces, defeating the "edit tokens + run checks" model the design system exists for > - This pull request converges those surfaces onto the shared primitives, codifies the radius scale as the modern multiplicative shadcn ladder, and unifies the row/hover/tree-guide language across the inbox and tasks lists — every visible delta was human-reviewed screen-by-screen against a live instance across nine feedback rounds > - The benefit is that the app's look is now steerable from single knobs (one `--radius` anchor, one Card, one Badge, one row component), and the visual regression suite covers the result (514 snapshots including a new AgentDetail page story) ## Linked Issues or Issue Description No public GitHub issue exists for this work; describing per the feature template: - **Problem**: after the design-token foundation (#9134), component-level drift remained — hand-rolled cards/pills, duplicated sidebar row chrome, and two different renderings of task rows (inbox vs tasks list) meant design changes had to be applied per-surface and frequently missed spots (e.g. status glyphs rendered 16px in the inbox but 20px in the tasks list because a slot override silently beat the component default). - **Proposed behavior**: all card-shaped containers render via `Card`, all label pills via `Badge`, sidebar rows via `SidebarNavItem`, and both task-list surfaces via one `IssueRow` configuration; the radius scale is a single multiplicative ladder anchored at `--radius: 0.5rem`. - **Alternatives considered**: converting interactive `<button>`/`<Link>` cards to `Card` divs (rejected — breaks semantics; documented inline with `design-allow` comments instead); keeping the legacy additive radius ladder (rejected in favor of the standard shadcn multiplicative mapping). ## What Changed - `Card` adoption across ~35 files (settings pages, auth/board flows, dashboards, list containers, KPI tiles); non-adoptable sites (interactive cards, `<li>` rows, class-string props, chart tooltip) carry documented `design-allow(card-pattern)` comments - `Card` gains an `interactive` prop — one quiet hover affordance for clickable cards (cursor, border darken, shadow lift, focus ring), applied to skills tiles, artifact cards, and the company selector; cards carry no resting shadow - `Badge` adoption for 113 hand-rolled pill spans across ~45 files; `PropertyChip` wraps `Badge` internally; `StatusBadge`, external-object chips, and match chips stay bespoke by documented decision (WCAG-tuned status mechanics) - Radius ladder becomes the multiplicative shadcn mapping (`sm/md/lg/xl/2xl/3xl/4xl = 0.6/0.8/1.0/1.4/1.8/2.2/2.6 × --radius`, anchor `0.5rem`); every card surface unifies on `rounded-lg`; the orphaned 8px literal token is deleted - Sidebar: agent rows render via `SidebarNavItem` (new additive props: `iconNode`, `active`, `trailing`, `liveAccessory`); live dots use `--status-agent-running`; one row rhythm and inset rounded pill highlight; right-aligned trailing badges; every labeled section is collapsible - Inbox + tasks lists unified: md status glyphs, `accent/50` rounded row hovers, vertical tree guides under parent rows (opaque underlay so dark-mode translucent borders don't stack), no horizontal dividers under expanded parents; the swipe-to-archive reveal layer shows only mid-swipe; board toggle uses the `SquareKanban` glyph - Kanban: every column carries a status-hued tint; lanes default expanded (including empty); compact mode collapses empty lanes to labeled rails (fixes a clipped, label-less empty-column state) - Storybook: new AgentDetail page story (realistic fixtures, light+dark) joins the visual suite; suite captures with `reducedMotion: 'reduce'` and the ux-lab reasoning ticker honors `prefers-reduced-motion`; a stale lexical alias in `storybook/main.ts` is fixed (build was broken since the lexical 0.46 bump) - Keyboard navigation, from live review of the unified lists: inbox navigation keys work on every tab (archive keys stay scoped to the archivable tab); keyboard-driven scrolling no longer hands the selection to whatever row lands under the stationary cursor (hover selects only after real pointer movement); the tasks list view gains the same j/k / arrows / Enter selection model as the inbox; and the `g` then `i` go-to-inbox chord works app-wide instead of only on the issue detail page - Token gates restored to 3/3 CLEAN (tokenized a post-#9134 regression in the recovery card); decisions recorded in `doc/design/DECISION-SHEET.md` and `doc/design/COMPONENT-INVENTORY.md` (investigation verdicts: FileTree vs WorkspaceFileBrowser and the four entity pickers stay separate — evidence included) ## Verification - `pnpm check:token-gates` → 3/3 CLEAN - `pnpm typecheck` → green (all packages) - `cd ui && npx vitest run` → 2106/2106 (assertions updated in lockstep where they documented superseded decisions; new tests for the global go-to-inbox chord) - `pnpm --filter @paperclipai/ui build` → exit 0 - `pnpm build-storybook` → succeeds (also fixes the lexical-alias break on master) - Visual regression: 514-snapshot Playwright suite green against the updated baseline (zero diffs from the keyboard-navigation round — those changes are purely behavioral). Note: baselines live outside git per the suite design and the baseline-manifest archive is not yet published, so CI cannot run this suite — it was run locally throughout; every visible delta was reviewed screen-by-screen in a live instance across nine review rounds. Review evidence (before/after triplets) intentionally kept out of the repo for size; available on request. - Manual: exercised dashboard, tasks (list + board), inbox, agents, skills, costs, settings, and artifact surfaces in light and dark themes ## Risks - Wide but shallow visual surface: most changes are class-string substitutions with behavior preserved (props, handlers, roles, test ids). The riskiest areas — dnd-kit card refs (React 19 ref-as-prop), inbox swipe-to-archive, and sidebar overlays — are covered by existing unit tests (all green) and were manually exercised. - Intentional visual deltas (rounded cards, tinted kanban columns, md status glyphs, unified hovers) are design decisions recorded in `doc/design/DECISION-SHEET.md`; each maps to a re-baselined snapshot set locally. - The visual suite cannot yet run in CI (unpublished baseline archive — pre-existing condition from #9134); until that lands, snapshot coverage is local-only. ## Model Used - Claude Fable 5 (`claude-fable-5`, Anthropic) via Claude Code — agentic coding with tool use (file editing, test execution, Playwright screenshot verification); extended thinking 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 - [ ] All Paperclip CI gates are green (will confirm once CI runs) - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (pending first review) - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>canary/v2026.709.0-canary.0 |
||
|
|
cc17f29e7e |
fix(timeouts): raise sandbox wall-clock backstop to 4h and make acpx_local timeouts self-describing (#9232)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agent runs execute through adapters (e.g. `acpx_local`), which can run locally, over SSH, or inside sandbox execution targets, each with a wall-clock execution timeout > - Sandbox-backed runs defaulted to a 30-minute wall-clock backstop (`DEFAULT_REMOTE_SANDBOX_ADAPTER_TIMEOUT_SEC = 1800`), which kills healthy long agent runs that are still making progress — long before the recovery watchdog's 4h critical threshold would even consider them stuck > - On top of that, `acpx_local` resolved its timeout directly from `adapterConfig.timeoutSec` instead of the shared execution-target resolver, and its timeout failures surfaced as a bare `Timed out after Ns` — giving operators no clue which timer fired or which knob raises it > - This pull request raises the sandbox backstop to 4h (aligned with the recovery watchdog), routes `acpx_local` through the shared timeout resolver, logs the effective timeout and its source at run start, and makes every timeout error message self-describing > - The benefit is that long-running sandbox agent runs no longer die at 30 minutes, and when a wall-clock timeout does fire, the run log states exactly which timer fired and how to configure it ## Linked Issues or Issue Description Refs #4535 (related: wall-clock execution timeouts killing agent runs that are still making progress — that issue covers a different hardcoded 600s timer, but the operator pain is the same). No exact public issue exists for this one, so describing it in-PR: **Bug:** A long sandbox-backed `acpx_local` agent run was killed with a bare `Timed out after 1800s` even though the agent was actively working. - **What happened:** The run hit the 30-minute `DEFAULT_REMOTE_SANDBOX_ADAPTER_TIMEOUT_SEC` backstop. `acpx_local` never consulted the shared execution-target timeout resolution (it read `adapterConfig.timeoutSec` directly, default 0), so on sandbox targets the sandbox-provider default applied with no adapter-level say. The resulting error named neither the timer that fired nor the knob that controls it. - **Expected:** Healthy long runs should not be killed by a 30-minute wall-clock backstop when the recovery watchdog only treats runs as critically stuck after 4h of output silence; and any timeout error should say which timeout fired and how to raise it. - **Impact:** Long, legitimate agent runs in sandboxes fail mid-work; operators waste time reverse-engineering which of several timers produced "Timed out after Ns". ## What Changed - `packages/adapter-utils/src/execution-target.ts` - `DEFAULT_REMOTE_SANDBOX_ADAPTER_TIMEOUT_SEC` raised from `1_800` to `14_400` (4h), with a comment explaining it intentionally matches the recovery watchdog's `ACTIVE_RUN_OUTPUT_CRITICAL_THRESHOLD_MS` (4h) so the adapter backstop never fires before the watchdog path. Output-inactivity monitors remain the primary hang detectors. - New `resolveAdapterExecutionTargetTimeout(target, configuredTimeoutSec)` returns `{ timeoutSec, source }` where `source` is `configured` / `sandbox_default` / `unlimited`. The existing `resolveAdapterExecutionTargetTimeoutSec` is preserved as a thin wrapper, so current callers are unaffected. - New `formatAdapterExecutionTimeoutErrorMessage(resolution)` and `formatAdapterExecutionTimeoutStartLogLine(resolution)` produce self-describing messages that name the timer that fired and the `adapterConfig.timeoutSec` knob that controls it. - `packages/adapters/acpx-local/src/server/execute.ts` - `buildRuntime` now resolves the wall-clock timeout through the shared resolver: sandbox targets default to the 4h backstop, local/SSH keep the historical "0 = no adapter timeout", and a configured `adapterConfig.timeoutSec` always wins. - The executor logs the effective timeout and its source at run start (`[paperclip] Adapter execution timeout: …`), so a later timeout is diagnosable from the run log alone. - All three bare timeout messages (timer cancel reason, turn result `errorMessage`, catch-path `messageOverride`) now use the self-describing format. - `packages/adapters/acpx-local/src/index.ts` — the adapter configuration doc for `timeoutSec` states the sandbox default and that the output-inactivity monitor remains the primary hang detector. - Tests: `packages/adapter-utils/src/execution-target-sandbox.test.ts` and `packages/adapters/acpx-local/src/server/execute.test.ts` (see Verification). ## Verification - `pnpm --filter @paperclipai/adapter-utils typecheck` — passes - `pnpm --filter @paperclipai/adapter-acpx-local typecheck` — passes - `npx vitest run packages/adapter-utils/src/execution-target-sandbox.test.ts packages/adapters/acpx-local/src/server/execute.test.ts` — 2 files, 40 tests, all pass - New/updated test coverage: - sandbox default resolves to 4h (and the constant is asserted to be `4 * 60 * 60`) - `resolveAdapterExecutionTargetTimeout` reports `configured` / `sandbox_default` / `unlimited` sources with the correct precedence (configured > sandbox default; local/SSH stay unlimited) - exact wording of the self-describing error message and the start-of-run log line - `acpx_local` runtime picks up the sandbox default into `timeoutMs`, keeps the unlimited local default, honors configured-over-default precedence, emits the start-of-run log line, and surfaces the self-describing `errorMessage`/cancel reason when the wall-clock timer kills a turn ## Risks - **Behavioral shift:** sandbox-backed adapter runs that previously hit the 30-minute backstop now run up to 4h before the adapter kills them. Genuinely hung runs are still caught much earlier by the adapters' output-inactivity monitors and by the recovery watchdog; the wall-clock timer is a last-resort kill switch. Operators who relied on the 30-minute default can restore it explicitly via `adapterConfig.timeoutSec`. - **Error-message consumers:** any tooling that pattern-matched the exact `Timed out after Ns` string from `acpx_local` will see the new self-describing message instead. - No API or schema changes; `resolveAdapterExecutionTargetTimeoutSec` keeps its exact signature and behavior (modulo the raised sandbox default). > 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 - Claude (Anthropic) via Claude Code CLI — model ID `claude-fable-5`, extended thinking enabled, agentic tool use (file edits, shell, test 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 - [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 - [ ] 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.708.0-canary.10 |
||
|
|
4a7a732476 |
feat(skills): add company skill fork prechecks (#9235)
Adds company skill fork precheck metadata, fork result/reassignment contracts, selected-agent reassignment during fork creation, and targeted server/shared test coverage.canary/v2026.708.0-canary.9 |
||
|
|
f616b6746c |
fix(server): clean heartbeat run scratch directories (#9234)
Co-Authored-By: Paperclip <noreply@paperclip.ing>canary/v2026.708.0-canary.8 |
||
|
|
38cca22b09 |
fix(server): avoid accepted-plan workspace branch freeze before child realization (#9233)
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents tackle complex tasks via *plan* flows: a planner decomposes
work into child issues, which are accepted by the board and then
executed
> - When a plan is accepted, `createChild` in `issues.ts` inserts child
issues pre-bound to the parent's already-realized execution workspace —
carrying over its concrete branch ref
> - If the repository's base ref advances between plan acceptance and a
child's first heartbeat, the child inherits a stale branch that no
longer matches the current base
> - At first heartbeat the workspace validator detects the mismatch and
freezes the child ("branch freeze"), blocking it from starting any work
> - The real fix is to strip the concrete workspace binding when
creating accepted-plan children: they should receive only the unresolved
*intent* (mode, baseRef, branchTemplate) and realize a fresh workspace
from the current base on their own first heartbeat
> - This PR implements that strip, adds a regression test that proves a
post-base-advance child realizes cleanly, and also fixes
`parseIssueExecutionWorkspaceSettings` so `environmentId` is not
silently dropped on update round-trips (a latent bug that was masking
the original fix)
## Linked Issues or Issue Description
No public GitHub issue exists for this bug. Bug description follows the
bug-report template:
**What happened:** Accepted-plan decomposition pre-binds child issues to
the parent's realized execution workspace branch (`executionWorkspaceId`
+ `executionWorkspaceBranch`). When `origin/master` advances between
plan acceptance and the child's first heartbeat, the workspace branch
interlock fires and the child is permanently frozen before it can start.
**Expected behavior:** Accepted-plan children should receive only
unresolved workspace intent (mode, git strategy fields) and realize a
fresh isolated worktree from the current base on first heartbeat. A
base-ref advance between acceptance and first-run should be transparent.
**Steps to reproduce:**
1. Accept a plan that decomposes into one or more child issues
(isolated_workspace + git_worktree mode).
2. Allow `origin/master` to advance (new merge).
3. Observe the first child heartbeat: workspace validation fails with a
branch-freeze error.
**Paperclip version:** current `master` (pre-fix).
**Deployment mode:** any (affects all modes that use isolated workspace
+ git worktree strategy).
Supersedes #9227 (earlier attempt, now closed — the fix was incomplete
because `environmentId` was silently dropped during
`parseIssueExecutionWorkspaceSettings` update round-trips, causing the
child workspace to lose its environment binding; this PR includes that
fix).
## What Changed
- **`server/src/issues.ts` — `createChild` / accepted-plan decomposition
path:** strip resolved workspace fields (`executionWorkspaceId`,
concrete branch) when creating accepted-plan children; preserve only
unresolved intent fields (`mode`, `baseRef`, `branchTemplate`,
`environmentId`, runtime/provisioning settings).
- **`server/src/execution-workspace-policy.ts` —
`parseIssueExecutionWorkspaceSettings`:** preserve `environmentId`
through update round-trips (was silently dropped, causing environment to
detach on any workspace settings update).
-
**`server/src/__tests__/heartbeat-accepted-plan-workspace-refresh.test.ts`:**
new regression test — accepted-plan child created after `origin/master`
moves realizes a fresh isolated worktree from the moved base and passes
workspace execution.
- **`server/src/__tests__/issues-service.test.ts`:** extended
workspace-linkage and `createChild` tests covering the accepted-plan
strip and the unchanged direct-child path.
## Verification
```sh
pnpm exec vitest run server/src/__tests__/heartbeat-accepted-plan-workspace-refresh.test.ts
pnpm exec vitest run server/src/__tests__/issues-service.test.ts -t "workspace linkage|accepted plan decomposition|createChild applies"
pnpm --filter @paperclipai/server typecheck
```
All three pass on this branch.
## Risks
**Low.** The change is scoped to the accepted-plan `createChild` code
path. The direct child / follow-up issue creation path (normal non-plan
decomposition) is unchanged and covered by existing tests. The
`parseIssueExecutionWorkspaceSettings` fix is additive — it now
preserves a field that was previously silently dropped, so no consumer
loses data.
## Model Used
Claude Sonnet 4.6 (`claude-sonnet-4-6`), Anthropic, 200K context window,
extended tool use + code generation.
## 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 (supersedes #9227)
- [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
- [ ] 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.708.0-canary.7
|
||
|
|
88bf71b84e |
Reject projectless isolated git worktree tasks (#9231)
## Thinking Path
> - Paperclip is an open-source platform for orchestrating AI agents;
agents run inside execution workspaces that range from a shared
container to full git worktrees cloned from a project repository.
> - Isolated git-worktree workspaces require a project to determine
which repository to clone — without a project the worktree base path
cannot be computed.
> - A task pinned to `isolated_workspace` + `git_worktree` with no
project was previously accepted at creation time but failed late at
dispatch with the opaque `workspace_validation_failed` /
`git_worktree_base_agent_home` error — only after the heartbeat
attempted to provision the workspace.
> - Fail-closed validation should happen in two places: (1) explicit
create/update pins that contradict the requirement are rejected at the
HTTP layer with a structured 422; (2) rows that reach the heartbeat
dispatcher with this invalid combination (e.g. through inheritance or a
retroactively-removed project) are blocked before any heartbeat run or
adapter spawn.
> - This PR adds the shared detection policy, the create/update guard in
the issues service, and the heartbeat pre-dispatch guard, together with
focused unit tests for all three layers.
> - The benefit is deterministic early failure with a clear remediation
message instead of a late, cryptic runtime error.
## Linked Issues or Issue Description
No upstream public GitHub issue — describing the problem inline
(bug-report format).
**What happened?**
Creating an issue with `executionWorkspaceSettings: { mode:
"isolated_workspace", type: "git_worktree" }` and no `projectId` was
accepted without error. The issue then became blocked at dispatch time
with the opaque message `git_worktree_base_agent_home` /
`workspace_validation_failed` — surfaced only after the heartbeat
attempted to provision the workspace.
**Expected behavior**
The platform should reject the invalid combination at create/update time
with a structured 422 that includes a clear remediation message, before
any heartbeat resource is consumed.
**Steps to reproduce**
1. Call `POST /api/issues` (or `PATCH /api/issues/:id`) with
`executionWorkspaceSettings: { mode: "isolated_workspace", type:
"git_worktree" }` and omit `projectId` (or set it to `null`).
2. Observe: request succeeds (200/201).
3. Assign the issue to an agent and watch it enter `blocked` with a
cryptic `workspace_validation_failed` error at dispatch.
**Related prior fix** — Refs #4844 (`fix(validator): reject static cwd
combined with git_worktree strategy`) — same validation area, different
dimension (static cwd vs. missing project).
**Paperclip version / commit**
Latest `master` (pre-this-PR).
**Deployment mode**
Standard (app-global server).
## What Changed
- **`execution-workspace-policy.ts`** — new shared
`detectWorkspaceWorktreeRequiresProject` function returning a stable
`workspace_worktree_requires_project` policy violation when an isolated
git-worktree task has no project, project workspace, or reusable
execution workspace; exports canonical remediation text used by both the
HTTP guard and the heartbeat guard.
- **`issues.ts`** — create and update paths check the new policy before
persisting; explicit pins to `isolated_workspace` / `operator_branch` +
`git_worktree` with no project are rejected with a 422 including the
policy code and remediation text.
- **`heartbeat.ts`** — pre-dispatch preflight checks the same policy for
rows that reach the heartbeat with the invalid combination (e.g. through
inheritance); such rows are marked `blocked` with a skipped wakeup
request, durable issue comment, and activity log before any heartbeat
run or adapter spawn.
- **`execution-workspace-policy.test.ts`** — focused policy-layer unit
tests for detection logic and remediation text.
- **`issues-service.test.ts`** — create/update 422 guard tests for the
new policy.
- **`heartbeat-workspace-branch-containment.test.ts`** — pre-dispatch
blocking test for inherited/ambiguous invalid rows; also fixes a cleanup
race in the existing test suite.
## Verification
```sh
pnpm exec vitest run \
server/src/__tests__/execution-workspace-policy.test.ts \
server/src/__tests__/issues-service.test.ts \
server/src/__tests__/heartbeat-workspace-branch-containment.test.ts
pnpm --filter @paperclipai/server typecheck
# Targeted regression
pnpm exec vitest run \
server/src/__tests__/heartbeat-workspace-branch-containment.test.ts \
-t "blocks projectless isolated git-worktree issues before dispatch"
```
All three test files and typecheck passed locally before this PR was
opened.
## Risks
**Low risk.** The policy detection function is pure with no side
effects. The create/update guard only triggers on explicit
`isolated_workspace` or `operator_branch` + `git_worktree` pins combined
with a missing project — it does not fire on inherited settings (handled
by the heartbeat preflight), so there is no false-positive rejection
risk for valid tasks. The heartbeat guard fires before any resource is
provisioned; the only behavioral change for already-invalid rows is that
they receive a clear `blocked` status and durable comment instead of a
late cryptic error.
## Model Used
Claude Sonnet 4.6 (`claude-sonnet-4-6`), 200k context window, tool use
enabled (agentic coding). Used to implement all server-side changes and
tests in this PR.
## 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
- [ ] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>
canary/v2026.708.0-canary.6
|
||
|
|
11177c2665 |
Fix resolved blocker wake reconciliation (#9229)
## Thinking Path > - Paperclip is an open source platform for managing AI agent companies — agents pick up issues, do work, and release checkouts in a heartbeat loop > - Issue dependency resolution is handled by `issue_blockers_resolved` wakes: when a blocking issue reaches `done`, dependent blocked issues should be woken so they can resume > - The workspace-finalize path maintained its own special-case loop to retry missed dependency wakes at run completion, duplicating logic that already exists in the shared level-triggered reconciliation backstop > - Additionally, the resolved-blocker reconciliation sweep was gated behind the broader liveness auto-recovery escalation setting — so instances that disabled auto-escalation creation also lost the baseline reconciliation sweep > - This PR routes the workspace-finalize retry through the shared backstop and decouples the reconciliation sweep from the escalation creation gate > - The benefit is simpler code (one authoritative path instead of two), and correct behaviour on instances where escalation creation is disabled ## Linked Issues or Issue Description No existing GitHub issue. Describing inline: **Bug (blocker wake reconciliation):** `issue_blockers_resolved` wakes can be missed when: 1. A `workspace_finalize` heartbeat retries dependency resolution using its own inline loop instead of the shared level-triggered backstop, making them diverge over time. 2. The `blockedByIssueIds` dependency is set (or the issue is moved to `blocked`) *after* the blocker already reached `done` — the PATCH-time wake fires on a non-blocked issue and the dependency reconciliation never catches up. 3. An assignee briefly becomes `null` between the blocker reaching `done` and the reconciliation sweep running — the sweep skips the issue and never retries. Related PRs: - Refs #8009 — adds dedup for `issue_blockers_resolved` re-fires (complementary; prevents over-firing; this PR ensures under-firing is caught) - Refs #6522 — `auto-unblock dependents with no assignee` (related no-assignee edge case) ## What Changed - **`server/src/services/heartbeat.ts`** — remove the inline dependency-wake retry loop from the `workspace_finalize` path; delegate to the shared `reconcileResolvedDependencyWakeups` helper instead - **`server/src/services/recovery/service.ts`** — split the resolved-blocker wake reconciliation sweep out from under the `liveness_escalation_auto_recovery` feature flag; the sweep runs unconditionally while escalation *creation* remains behind the flag - **`server/src/__tests__/issue-dependency-wakeups-routes.test.ts`** — regression: `blockedBy` set after blocker already done still triggers a reconciliation wake - **`server/src/__tests__/heartbeat-issue-liveness-escalation.test.ts`** — regression: assignee-null churn before reconciliation; stale skipped dependency wakes do not suppress a fresh reconciliation wake ## Verification ``` pnpm exec vitest run \ server/src/__tests__/issue-dependency-wakeups-routes.test.ts \ server/src/__tests__/heartbeat-issue-liveness-escalation.test.ts ``` 23 tests, all passing locally. `pnpm --filter @paperclipai/server typecheck` clean. ## Risks Low risk. Bounded blast radius: - The reconciliation sweep only considers non-hidden `blocked` issues with an agent assignee - Uses keyset pagination with an existing 500-candidate cap - Reuses dependency readiness/finalize gating logic unchanged - Skips issues with existing active/queued runs and pending interactions - Deduplicates against live/completed `issue_blockers_resolved` wakes (skipped/cancelled wakes intentionally do not suppress a fresh reconciliation) - Observability: healed reconciliations emit `issue.blockers_resolved_wake_emitted` activity and log the healed issue ids and source ## Model Used Claude Sonnet 4.6 (`claude-sonnet-4-6`) with tool use and extended context. Paperclip AI agent 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 - [ ] 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.708.0-canary.5 |
||
|
|
e68ee09809 |
perf(release): batch npm registry version queries (#9202)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - The release subsystem publishes the public workspace packages and also powers release-related CI validation. > - The release flow currently asks npm for package versions one package at a time in multiple places. > - That serial registry latency slows the PR Canary Dry Run path and real release invocations even though the checks are independent. > - This pull request batches npm registry version lookups with bounded concurrency and reuses the result for version calculation. > - The benefit is shorter non-build release-script time while preserving the fresh target-version existence check before publishing. ## Linked Issues or Issue Description - No public GitHub issue exists for this release-script performance cleanup. ### Problem or motivation Release validation spends avoidable time on repeated serial `npm view` calls across the public package set. The slow path affects PR release validation and real release invocations because version discovery waits on independent registry reads one at a time. ### Proposed solution Fetch package version maps concurrently with bounded parallelism, reuse that map for stable/canary version calculation, and keep a fresh parallel absence check for the target publish version. ### Alternatives considered Keeping the existing serial shell loop is simpler, but it preserves the CI latency cost. Caching the final target-version existence check was rejected because release publish safety should still query npm freshly before publishing. ### Roadmap alignment This is a small release-tooling performance improvement. It does not duplicate any planned core product work found in `ROADMAP.md`. ## What Changed - Added `scripts/release-registry-versions.mjs` to fetch npm package version maps and assert target-version absence with bounded parallelism. - Updated `scripts/release.sh` to prefetch package versions once and to batch the final target-version absence check. - Updated `next_stable_version` and `next_canary_version` to use the prefetched version map when present, with the existing per-package npm fallback preserved. - Added release-registry helper coverage and included it in `pnpm run test:release-registry`. - Hardened the release publish helper tests so their fake `pnpm`/`npm` fixture PATH is preserved under non-login shell execution. ## Verification - `node --test scripts/release-registry-versions.test.mjs` - `pnpm run test:release-registry` - `bash -n scripts/release.sh scripts/release-lib.sh` - `git diff --check` - Safety scan before push: searched changed files for common key/token/password patterns and PII markers; only benign script-name text matched (`secrets:migrate-inline-env`). - Remote PR checks on the latest head passed, including `Typecheck + Release Registry`, `Canary Dry Run`, build, tests, e2e, policy, security scans, and commitperclip review. - Greptile reviewed the latest head with Confidence Score 5/5 and no blocking issues. ## Risks - Low risk. The release version helpers keep their original npm fallback when no prefetched version map is supplied. - The existence check remains fresh and uncached before publish, but now reports all matching package/version pairs from a parallel check. - If npm has transient failures during the prefetch step, missing or failed packages still map to an empty version list, matching the old helper behavior. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex coding agent using GPT-5, with shell/tool execution in the local repository. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude <noreply@paperclip.ing>canary/v2026.708.0-canary.4 |