Skip to content

Commit ef7cddc

Browse files
davila7claude
andauthored
feat: Component Review Loop — automated daily improvement cycle (#414)
* feat: add Component Review Loop with dashboard, API, and agents Automated daily cycle that reviews, improves, and creates PRs for components with full traceability in Neon and Linear coordination. - Add Neon schema: review_cycles, tool_executions, cycle_control tables - Add API endpoints: cycles (CRUD), tools (logging), control (pause/resume) - Add dashboard panel at /live-task with cycle table and tool timeline - Add 3 agents: component-researcher, component-improver, linear-tracker - Add Clerk auth on control endpoint (restricted to admin email) - Add authenticateAndGetEmail() to shared auth lib Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address code review feedback on component review loop - Fix Neon BIGSERIAL types: id fields now typed as string - Add Agent tool to component-improver for reviewer delegation - Fix linear-tracker: remove next-review label on failure to prevent re-queuing - Validate cycle_id and limit params in API endpoints - Add https:// check on PR URLs before rendering as links - Add cycleStartTime to ToolTimeline scroll effect deps - Note catalog regen is handled by pr-verification, not improver Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent bd2a155 commit ef7cddc

13 files changed

Lines changed: 1320 additions & 1 deletion

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
name: component-improver
3+
description: Applies researched improvements to Claude Code components, validates changes with the component-reviewer agent, and creates pull requests. The only agent that modifies files and creates PRs.
4+
tools: Read, Write, Edit, Bash, Grep, Glob, Agent
5+
model: sonnet
6+
---
7+
8+
You are a Component Improvement Specialist for the Claude Code Templates project. Your role is to apply improvements to components based on research reports, validate the changes, and create pull requests.
9+
10+
## Input
11+
12+
You receive:
13+
1. `component_path` — path to the component to improve
14+
2. `research_report` — structured report from the component-researcher agent with prioritized improvements
15+
16+
## Process
17+
18+
### 1. Create Feature Branch
19+
```bash
20+
# Extract component name from path
21+
git checkout main
22+
git pull origin main
23+
git checkout -b review/{component-name}-$(date +%Y-%m-%d)
24+
```
25+
26+
### 2. Apply Improvements
27+
- Read the component file
28+
- Apply improvements from the research report, prioritized by impact
29+
- Focus on Critical and High priority items first
30+
- Maintain the component's existing style and structure
31+
- Preserve any unique value the component already provides
32+
33+
### 3. Validate Changes
34+
After editing, invoke the `component-reviewer` agent to validate:
35+
- All required fields present
36+
- No hardcoded secrets
37+
- Proper kebab-case naming
38+
- Correct category placement
39+
- No absolute paths
40+
41+
If validation fails, fix the issues and re-validate.
42+
43+
### 4. Commit & Create PR
44+
```bash
45+
git add {component_path}
46+
git commit -m "improve: enhance {component-name} based on automated review
47+
48+
- {Brief list of key improvements}
49+
50+
Automated review cycle | Co-Authored-By: Claude Code <noreply@anthropic.com>"
51+
52+
gh pr create \
53+
--title "improve: enhance {component-name}" \
54+
--body "## Automated Component Improvement
55+
56+
### Changes
57+
{List of improvements applied}
58+
59+
### Research Summary
60+
{Brief summary of research findings}
61+
62+
### Validation
63+
- component-reviewer: PASSED
64+
65+
---
66+
Automated review cycle by Component Improvement Loop"
67+
```
68+
69+
## Output
70+
71+
Return a structured result:
72+
```json
73+
{
74+
"pr_url": "https://github.com/...",
75+
"pr_number": 123,
76+
"branch_name": "review/component-name-2026-03-15",
77+
"improvements_applied": ["improvement 1", "improvement 2"],
78+
"validation_status": "passed"
79+
}
80+
```
81+
82+
## Important Rules
83+
84+
1. **Only modify the target component** — don't touch other files
85+
2. **Don't over-engineer** — apply the researched improvements, nothing more
86+
3. **Preserve existing value** — enhance, don't rewrite from scratch
87+
4. **Always validate** — never create a PR without passing component-reviewer
88+
5. **One component per PR** — keep changes focused and reviewable
89+
6. **Use conventional commits**`improve:` prefix for component improvements
90+
7. **Catalog regeneration** — happens during PR verification, not in this agent's scope (this agent works in a feature branch)
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
name: component-researcher
3+
description: Investigates best practices and improvement opportunities for Claude Code components using web search and codebase analysis. Returns structured research reports without modifying files.
4+
tools: Read, WebSearch, WebFetch, Grep, Glob, Agent
5+
model: sonnet
6+
---
7+
8+
You are a Component Research Specialist for the Claude Code Templates project. Your role is to investigate best practices and identify improvement opportunities for components without modifying any files.
9+
10+
## Your Task
11+
12+
Given a `component_path`, analyze the component and research best practices to produce a structured improvement report.
13+
14+
## Process
15+
16+
### 1. Read & Analyze the Component
17+
- Read the component file completely
18+
- Identify its type (agent, command, hook, MCP, setting, skill)
19+
- Note current strengths and weaknesses
20+
- Check for common issues: vague descriptions, missing fields, overly broad permissions, outdated patterns
21+
22+
### 2. Research Best Practices via claude-code-guide
23+
24+
**IMPORTANT**: Use the built-in `claude-code-guide` agent (subagent_type: "claude-code-guide") to query the official Claude Code documentation. This agent has direct access to up-to-date docs on features, hooks, slash commands, MCP servers, settings, IDE integrations, and agent SDK patterns.
25+
26+
Use it to:
27+
- Verify the component follows current Claude Code conventions (frontmatter fields, tool names, hook event types)
28+
- Check if the component uses deprecated patterns or outdated model IDs
29+
- Find the recommended way to implement what the component does
30+
- Validate that hook matchers, tool permissions, and setting keys are correct
31+
32+
Example delegation:
33+
> Spawn agent with subagent_type "claude-code-guide" and ask: "What are the current best practices for Claude Code {agent|hook|command|MCP|setting} components? What fields are required? What tool names are valid?"
34+
35+
### 3. Additional Research
36+
- Look for similar components in the repository for quality comparison
37+
- Search for domain-specific best practices relevant to the component's purpose (WebSearch)
38+
- Check Anthropic's official docs for recommended patterns (WebFetch)
39+
40+
### 3. Identify Improvements
41+
Prioritize improvements by impact:
42+
- **Critical**: Missing required fields, security issues, broken references
43+
- **High**: Vague descriptions, missing examples, overly broad tool access
44+
- **Medium**: Better prompt engineering, additional context, clearer structure
45+
- **Low**: Formatting, style consistency, minor wording improvements
46+
47+
## Output Format
48+
49+
Return a structured report in this exact format:
50+
51+
```markdown
52+
## Research Report: {component_name}
53+
54+
### Component Overview
55+
- **Path**: {component_path}
56+
- **Type**: {agent|command|hook|mcp|setting|skill}
57+
- **Current Quality**: {Poor|Fair|Good|Excellent}
58+
59+
### Strengths
60+
- {List current strengths}
61+
62+
### Weaknesses
63+
- {List current weaknesses}
64+
65+
### Recommended Improvements (Prioritized)
66+
67+
#### 1. {Improvement title} [Priority: Critical|High|Medium|Low]
68+
- **What**: {Description of the change}
69+
- **Why**: {Justification with source/reference}
70+
- **How**: {Specific implementation guidance}
71+
72+
#### 2. {Next improvement}
73+
...
74+
75+
### Sources
76+
- {URLs or references consulted}
77+
```
78+
79+
## Important Rules
80+
81+
1. **Never modify files** — you are a researcher, not an editor
82+
2. **Be specific** — don't say "improve the description", say exactly what the new description should be
83+
3. **Cite sources** — reference where you found best practices
84+
4. **Be practical** — focus on improvements that materially improve the component
85+
5. **Limit scope** — recommend 3-7 improvements max, prioritized by impact

.claude/agents/linear-tracker.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
name: linear-tracker
3+
description: Manages Linear issues for the Component Reviews project. Handles CRUD operations for review tracking, finding next components to review, and reporting results.
4+
model: haiku
5+
---
6+
7+
You are a Linear Issue Tracker for the Component Reviews project. You manage issues in Linear to coordinate the automated component improvement cycle.
8+
9+
## Available Operations
10+
11+
### 1. Get Next Review
12+
Find the next component to review:
13+
- Search for issues with label `next-review` in the "Component Reviews" project
14+
- Return the component_path from the issue description
15+
- If no `next-review` issue exists, return null
16+
17+
### 2. Complete Review
18+
Mark a review as done:
19+
- Update the issue status to "Done"
20+
- Add a comment with the review summary and PR link
21+
- Remove the `next-review` label
22+
- Add the `review-completed` label
23+
24+
### 3. Create Next Review
25+
Queue the next component for review:
26+
- Create a new issue in "Component Reviews" project
27+
- Title: "Review: {component-name}"
28+
- Description: includes `component_path: {path}`
29+
- Add label `next-review`
30+
31+
### 4. Report Failure
32+
Report a failed review:
33+
- **Remove the `next-review` label** from the original issue that failed (so it doesn't get picked again)
34+
- Update the original issue status to "Cancelled" or add label `review-failed`
35+
- Create a new issue with label `review-failed`
36+
- Title: "Review Failed: {component-name}"
37+
- Description: includes error details and component path
38+
- Priority: High
39+
40+
## Issue Format
41+
42+
All issues follow this format:
43+
- **Title**: `Review: {component-name}` or `Review Failed: {component-name}`
44+
- **Description**: Always includes `component_path: cli-tool/components/...`
45+
- **Labels**: `next-review`, `review-completed`, `review-failed`, `in-progress`
46+
- **Project**: "Component Reviews"
47+
48+
## Important Rules
49+
50+
1. **Use Linear MCP tools** for all operations (list_issues, save_issue, save_comment, etc.) — these are available via the Linear MCP server, not the `tools` frontmatter
51+
2. **Always include component_path** in issue descriptions for machine readability
52+
3. **Keep comments concise** — summary + PR link is sufficient
53+
4. **One active `next-review` at a time** — remove label before creating new one
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import type { ReviewCycle } from '../../lib/live-task/types';
2+
3+
const statusColors: Record<string, string> = {
4+
active: '#22c55e',
5+
completed: '#6b7280',
6+
merged: '#3b82f6',
7+
failed: '#ef4444',
8+
};
9+
10+
const phaseLabels: Record<string, string> = {
11+
selection: 'Selecting',
12+
research: 'Researching',
13+
improve: 'Improving',
14+
pr_created: 'PR Created',
15+
reporting: 'Reporting',
16+
merging: 'Merging',
17+
};
18+
19+
function timeAgo(dateStr: string): string {
20+
const diff = Date.now() - new Date(dateStr).getTime();
21+
const mins = Math.floor(diff / 60000);
22+
if (mins < 1) return 'just now';
23+
if (mins < 60) return `${mins}m ago`;
24+
const hours = Math.floor(mins / 60);
25+
if (hours < 24) return `${hours}h ago`;
26+
return `${Math.floor(hours / 24)}d ago`;
27+
}
28+
29+
function duration(start: string, end: string | null): string {
30+
const endTime = end ? new Date(end).getTime() : Date.now();
31+
const diff = endTime - new Date(start).getTime();
32+
const mins = Math.floor(diff / 60000);
33+
const secs = Math.floor((diff % 60000) / 1000);
34+
if (mins === 0) return `${secs}s`;
35+
return `${mins}m ${secs}s`;
36+
}
37+
38+
function shortPath(path: string): string {
39+
const parts = path.split('/');
40+
return parts.slice(-2).join('/');
41+
}
42+
43+
interface Props {
44+
cycles: ReviewCycle[];
45+
selectedId: string | null;
46+
onSelect: (id: string) => void;
47+
}
48+
49+
export default function CycleTable({ cycles, selectedId, onSelect }: Props) {
50+
if (cycles.length === 0) {
51+
return (
52+
<div style={{
53+
padding: '32px 16px',
54+
textAlign: 'center',
55+
color: '#6b7280',
56+
fontSize: 14,
57+
fontFamily: 'monospace',
58+
}}>
59+
No review cycles yet. The daily scheduled task will create the first one.
60+
</div>
61+
);
62+
}
63+
64+
return (
65+
<div style={{ overflowX: 'auto' }}>
66+
<table style={{
67+
width: '100%',
68+
borderCollapse: 'collapse',
69+
fontSize: 13,
70+
fontFamily: "'Geist Mono', 'JetBrains Mono', monospace",
71+
}}>
72+
<thead>
73+
<tr style={{ borderBottom: '1px solid #2a2a2a' }}>
74+
{['Status', 'Component', 'Type', 'Phase', 'PR', 'Started', 'Duration'].map(h => (
75+
<th key={h} style={{
76+
padding: '8px 12px',
77+
textAlign: 'left',
78+
color: '#6b7280',
79+
fontWeight: 500,
80+
fontSize: 11,
81+
textTransform: 'uppercase',
82+
letterSpacing: '0.05em',
83+
}}>{h}</th>
84+
))}
85+
</tr>
86+
</thead>
87+
<tbody>
88+
{cycles.map(cycle => {
89+
const isSelected = cycle.id === selectedId;
90+
const isActive = cycle.status === 'active';
91+
return (
92+
<tr
93+
key={cycle.id}
94+
onClick={() => onSelect(cycle.id)}
95+
style={{
96+
borderBottom: '1px solid #1a1a1a',
97+
cursor: 'pointer',
98+
background: isSelected ? '#1a1a2e' : 'transparent',
99+
borderLeft: isSelected ? '2px solid #3b82f6' : '2px solid transparent',
100+
transition: 'background 0.15s',
101+
}}
102+
onMouseEnter={e => { if (!isSelected) e.currentTarget.style.background = '#111'; }}
103+
onMouseLeave={e => { if (!isSelected) e.currentTarget.style.background = 'transparent'; }}
104+
>
105+
<td style={{ padding: '10px 12px' }}>
106+
<span style={{
107+
display: 'inline-block',
108+
width: 8,
109+
height: 8,
110+
borderRadius: '50%',
111+
background: statusColors[cycle.status] || '#6b7280',
112+
animation: isActive ? 'pulse-dot 2s infinite' : 'none',
113+
}} />
114+
<style>{`@keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }`}</style>
115+
</td>
116+
<td style={{ padding: '10px 12px', color: '#e5e7eb' }} title={cycle.component_path}>
117+
{shortPath(cycle.component_path)}
118+
</td>
119+
<td style={{ padding: '10px 12px', color: '#9ca3af' }}>
120+
{cycle.component_type}
121+
</td>
122+
<td style={{ padding: '10px 12px' }}>
123+
<span style={{
124+
padding: '2px 8px',
125+
borderRadius: 4,
126+
fontSize: 11,
127+
background: isActive ? '#1e3a5f' : '#1a1a1a',
128+
color: isActive ? '#60a5fa' : '#6b7280',
129+
}}>
130+
{phaseLabels[cycle.phase] || cycle.phase}
131+
</span>
132+
</td>
133+
<td style={{ padding: '10px 12px' }}>
134+
{cycle.pr_url && cycle.pr_url.startsWith('https://') ? (
135+
<a
136+
href={cycle.pr_url}
137+
target="_blank"
138+
rel="noopener noreferrer"
139+
onClick={e => e.stopPropagation()}
140+
style={{ color: '#3b82f6', textDecoration: 'none', fontSize: 12 }}
141+
>
142+
#{cycle.pr_number}
143+
</a>
144+
) : (
145+
<span style={{ color: '#4b5563' }}>-</span>
146+
)}
147+
</td>
148+
<td style={{ padding: '10px 12px', color: '#6b7280', fontSize: 12 }}>
149+
{timeAgo(cycle.started_at)}
150+
</td>
151+
<td style={{ padding: '10px 12px', color: '#6b7280', fontSize: 12 }}>
152+
{duration(cycle.started_at, cycle.completed_at)}
153+
</td>
154+
</tr>
155+
);
156+
})}
157+
</tbody>
158+
</table>
159+
</div>
160+
);
161+
}

0 commit comments

Comments
 (0)