feat(pipeline): render issue dependency DAG on per-issue Monitor page #251
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!251
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "dev/234"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
GET /issues/deps?repo=…&number=N&depth=kendpoint with 30 s server-side cache; BFS in both directions (blockers + dependents) up to depth 1–5, backed by the existinggetIssueBlockers/getIssueBlockswrappersIssueDepsGraph/IssueDepsNode/IssueDepsEdgeshared types in@claude-hooks/shared<DependencyGraph>component on the per-issue Monitor route — three swim-lanes (blockers → focal → dependents), click-navigates, hover tooltip⬡ Depsexpand toggle on each pipeline list row; lazy-fetches the graph only when expanded, sharing the TanStack Query cache with the detail pagebuildIssueDepsGraph: A→B→C chain, isolated focal, depth clampingCloses #234
Test plan
bun test apps/server/src/deps.test.ts— 61 tests pass (includes 3 newbuildIssueDepsGraphcases)GET /issues/deps?repo=charles/claude-hooks&number=234&depth=2returns a valid JSON DAG/app/monitor/issue/charles/claude-hooks/234— dependency panel renders below the pipeline graph⬡ Depson a pipeline list row — inline panel expands and shows the graphbun x playwright test apps/web/e2e/monitor.spec.ts🤖 Generated with Claude Code
055fb2e3575027360bb4Biome flags inline-safe JSX as format errors when they are spread across multiple lines but fit on one line within the 120-char limit: - NodeCard: {node.assignee && (...)} → inline (101 vis) - NodeCard: <span key={l}>{l}</span> in label map → single line (117 vis) - NodeCard: {node.labels.length > 3 && (...)} → inline (115 vis) - DependencyGraph: <h2>Dependencies</h2> → single line (112 vis) - DependencyGraph: {blockers.map((n) => (...))} → inline arrow (103 vis) - DependencyGraph: {dependents.map((n) => (...))} → inline arrow (105 vis) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>50a230de1e478f17b76c478f17b76c9d6ed8ac809d6ed8ac8067fd266959Review — APPROVED
CI is green (run #1924, sha
67fd266). All acceptance criteria from issue #234 are met. The implementation is solid — clean BFS traversal, correct shared types, well-tested server logic, and the UI components are properly wired up.Two minor findings, neither blocks merge:
1.
DepsBadgeis exported but never usedFile:
apps/web/src/components/dependency-graph.tsxDepsBadge(exported at the bottom of the file) is designed to show inline blocker/dependent counts (⬆N ⬇M) in the pipeline list row. However,pipeline-list.tsxnever imports it — the row uses a plain⬡ Depstoggle button instead. The badge is dead-exported code.This is fine if
DepsBadgeis scaffolding for a future "show counts without fetching" path (it requires explicitblockerCount/dependentCountprops, whichIssuePipelinedoesn't carry today). If so, a short comment saying it's reserved for future use would clarify intent. If it's not needed, it can be removed to keep the exported API surface clean.2.
_depsCachenever evicts stale entriesFile:
apps/server/src/deps.ts(the_depsCacheMap at module level)The 30 s TTL is checked on read, but entries are never removed from the Map — they accumulate indefinitely. For a long-running service with many repo/issue/depth combinations this will slowly grow in memory. The existing
_pipelineCacheinpipeline.tshas the same pattern, so this is consistent and unlikely to be a practical problem at current ops volume. Worth noting for a future sweeper pass.Everything else looks correct:
buildIssueDepsGraphcache key correctly includes(repo, focal, depth). ✓handleIssueDepsvalidates required params, guards against non-finite focal, surfaces 400/503/502 cleanly. ✓DependencyGraphthree swim-lane layout (blockers → focal → dependents) matches the spec. ✓PipelineRowlazy-fetches the graph only when the expand toggle is clicked (enabled: depsExpanded). ✓