mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 10:48:12 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The issue/task orchestration subsystem tracks parent–child and blocker–dependent relationships, forming a directed acyclic (in intention) subtree below each root issue > - Agents and operators have no lightweight way to inspect the dependency and wake state across an entire issue subtree — they must walk the tree issue-by-issue, making multiple round-trips with full object fetches > - A bounded, read-only subtree diagnostic endpoint lets callers understand the health of an entire work tree (which nodes are blocked, which are cycling, which have pending wakes) from a single authenticated request > - This pull request adds `GET /api/issues/:id/diagnostics/subtree`, a depth/node/per-node capped traversal that reuses the blocker and wake projection helpers from the companion blocker and wake diagnostics endpoints (see Refs #9114, #9133) > - The benefit is that platform operators, monitoring, and coaching tooling can surface \"why is this subtree stalled?\" across all nodes without database access or unbounded graph walks, using only data the caller already has read permission for ## Linked Issues or Issue Description Refs #9114 (companion blocker diagnostics endpoint — blocker projection helpers reused here) Refs #9133 (companion wake diagnostics endpoint — wake projection helpers reused here) ## What Changed - **New route** `GET /api/issues/:id/diagnostics/subtree` in `server/src/routes/issues.ts`: returns a bounded subtree traversal rooted at `:id`, with depth/node/per-node caps and explicit truncation flags - **Cycle-safe traversal**: visited-node set prevents infinite loops on any accidental cycle in the ancestry graph - **Per-node authorization**: each subtree node is individually filtered through `assertIssueReadAllowed`; unauthorized nodes are omitted from the response and do not influence aggregate counts - **Blocker and wake reuse**: per-node blocker rows and wake events are projected through the same helpers as #9114 and #9133 — raw wake payloads, raw errors, activity details, and trigger detail fields are stripped - **Low-trust filtering**: the `mention-scoped` low-trust path redacts node/blocker identifiers for unauthorized actors, consistent with #9133 - **Truncation reporting**: response includes `depthTruncated`, `nodeTruncated`, and per-node `blockersTruncated`/`wakesTruncated` flags when caps are hit - **Shared types** in `@paperclipai/shared`: `IssueSubtreeDiagnosticsResponse` and supporting node/blocker/wake types exported from the shared package - **OpenAPI tag registration** for the new route - **API reference docs** in `skills/paperclip/references/api-reference.md` - **Test coverage** (`server/src/__tests__/issue-subtree-diagnostics-routes.test.ts`, embedded Postgres): happy path, quiet singleton (no children/blockers), node cap truncation, mention-scoped low-trust filtering, cross-company denial ## Verification ```bash # Subtree diagnostics tests only pnpm exec vitest run server/src/__tests__/issue-subtree-diagnostics-routes.test.ts # Full diagnostics suite (blocker + wake + subtree) pnpm exec vitest run server/src/__tests__/issue-blocker-diagnostics-routes.test.ts server/src/__tests__/issue-wake-diagnostics-routes.test.ts server/src/__tests__/issue-subtree-diagnostics-routes.test.ts # Type-check shared and server packages pnpm --filter @paperclipai/shared typecheck pnpm --filter @paperclipai/server typecheck # Whitespace / diff check git diff --check ``` All commands passed locally (5 subtree tests, 17 total across the three diagnostics test files). ## Risks - **No schema or migration changes** — read-only projection over existing relations; no DDL risk - **Bounded traversal** — depth, node count, and per-node blocker/wake caps prevent unbounded graph walks; truncation is reported explicitly in the response - **Auth boundary** — root issue read is company-scoped and checked before the subtree is built; each subtree node is individually authorized; cross-company access is denied at `assertCompanyAccess` - **No raw payloads** — raw wake payload, raw error, activity details, and trigger detail fields are stripped from all nodes, consistent with the companion endpoints - Low overall risk; the endpoint is additive and read-only ## Model Used - **Provider:** Anthropic - **Model:** Claude Sonnet 4.6 (`claude-sonnet-4-6`) - **Tool use:** yes (file reads, edits, bash execution, Paperclip API calls) - **Reasoning mode:** standard (no extended thinking) ## 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: Paperclip <noreply@paperclip.ing>