| name | linear-quality-audit |
| description | Find problematic tickets with member attribution - missing labels, assignees, projects, poor descriptions. |
Linear Quality Audit
Usage
linear-quality-audit
Run quality audit on Linear board
Process
1. Load Context
board = read('../data/board.json')
excludedTeams = board.settings.team_exclusions.quality_audits
2. Find Problems (Filter-First for 100% Coverage)
Run targeted queries to find ALL problematic tickets:
// Get tickets missing team labels
missing_team = list_issues({
state: "!Backlog,!Done,!Canceled",
limit: 250
// Filter: tickets WITHOUT any team label (Backend Team, Mobile Team, WebDev Team)
})
// Get tickets missing platform labels
missing_platform = list_issues({
state: "!Backlog,!Done,!Canceled",
limit: 250
// Filter: tickets WITHOUT platform labels (Web/Desktop, Mobile/Android, etc.)
})
// Get tickets missing assignees (when required)
missing_assignee = list_issues({
assignee: null,
state: "In Progress,In Review,Ready for QA,In QA,Ready for Design QC",
limit: 250
})
// Get tickets missing projects (when required)
missing_project = list_issues({
project: null,
state: "!Backlog,!Done,!Canceled",
limit: 250
})
Then get recent activity to catch fresh tickets:
recently_created = list_issues({
limit: 250,
orderBy: "createdAt"
})
recently_updated = list_issues({
limit: 250,
orderBy: "updatedAt"
})
// Detect stale tickets (now included in quality audit)
staleThresholdDays = board.settings.stale_threshold_days || 14
stale_14_15 = list_issues({
state: "In Progress,In Review,Ready for QA,In QA,Ready for Design QC",
updatedBefore: now() - 14d,
updatedAfter: now() - 15d,
limit: 250
})
stale_15_30 = list_issues({
state: "In Progress,In Review,Ready for QA,In QA,Ready for Design QC",
updatedBefore: now() - 15d,
updatedAfter: now() - 30d,
limit: 250
})
stale_30_plus = list_issues({
state: "In Progress,In Review,Ready for QA,In QA,Ready for Design QC",
updatedBefore: now() - 30d,
limit: 250
})
3. Merge & Deduplicate
all_tickets = merge_by_id([
missing_team,
missing_platform,
missing_assignee,
missing_project,
recently_created,
recently_updated,
stale_14_15,
stale_15_30,
stale_30_plus
])
// Filter out excluded teams
filtered_tickets = all_tickets.filter(t => !excludedTeams.includes(t.team))
4. Categorize Problems
For each unique ticket, check:
Determine Reporting Team:
- Check for "Backend Team", "Mobile Team", or "WebDev Team" labels → Engineering subteam
- Otherwise use Linear team field → Standalone team
- Skip if team in excludedTeams
Missing Labels:
- No team label (Backend Team, WebDev Team, Mobile Team)
- No platform label (for Bugs/Features)
- No feature/service label (for Bugs/Features)
Missing Assignee:
- No assignee AND status ≠ "Backlog"
Missing Project:
- No project AND status ≠ "Backlog"
- Skip if team excluded from project requirements
Poor Quality:
- Empty/short description (<20 chars)
- Placeholder text ("TBD", "TODO", "fix this")
- Bugs: No repro steps or context
- Features: No acceptance criteria
Stale (by age bucket):
- 14–15 days
- 15–30 days
30 days
Use LLM to judge quality for ambiguous cases.
5. Resolve Unknowns
If creator/assignee not in board.json:
- Use
resolveUser()helper - See
../utils/sync-helpers.md
6. Group by Creator
Group problems by createdBy user, then by problem type.
7. Generate Report
# Linear Quality Audit
**Generated:** [timestamp]
**Audited:** [X] unique tickets (deduped from [Y] total queries)
**Problems:** [Z] tickets ([W]%)
**Excluded Teams:** [list]
## Query Summary
Targeted filters:
• Missing team labels: X tickets
• Missing platform labels: X tickets
• Missing assignees: X tickets
• Missing projects: X tickets
• Recently created: 250 tickets
• Recently updated: 250 tickets
After merge & dedup: X unique tickets analyzed
## Summary
| Problem | Count | % |
|---------|-------|---|
| Missing Labels | X | Y% |
| Missing Assignee | X | Y% |
| Missing Project | X | Y% |
| Poor Quality | X | Y% |
| Stale Tickets | X | Y% |
## Attribution by Creator
### [Name] - X quality issues
**Missing Labels (X):**
- TICKET-ID: Title - Missing: [specific]
**No Assignee (X):**
- TICKET-ID: Title - Status: [status]
**No Project (X):**
- TICKET-ID: Title
**Poor Quality (X):**
- TICKET-ID: Title - [reason]
## Stale Tickets
| Bucket | Count |
|--------|-------|
| >30 days | X |
| 15–30 days | X |
| 14–15 days | X |
## Actions
**Most Common Issues:**
1. [problem] - X tickets
2. [problem] - X tickets
**Needs Most Fixes:**
1. [name] - X tickets
2. [name] - X tickets
**Next Steps:**
1. Run linear-organise for auto-fixes
2. Share report for accountability
3. Follow up with top creators
8. Save & Cleanup
If unknown_cache modified: saveUnknownCache()
Offer to save report (user specifies location).
Rules
CRITICAL:
- Filter-first approach: Query for specific problems, don't analyze everything
- 100% coverage: Targeted filters catch ALL problematic tickets
- Recency check: Always check last 250 created + updated to catch fresh issues
- Merge & dedupe: Combine all queries by issue ID to avoid duplicates
- Skip excluded teams: AI & Research entirely from all checks
- DevOps different standards: Infrastructure work doesn't need all labels/projects
- QA bug tickets expected incomplete initially: QA (Anurag, Arti) report bugs quickly - engineers add labels later. Note missing labels but don't flag harshly
- Backlog tickets can lack assignee/project
- Be specific: "Missing: Team label, Platform label"
- Show ticket ID + TITLE not just ID
- Track creation date for context
- Include ticket URLs for easy fixing
- Location agnostic - user chooses save path
- Show query breakdown in report for transparency
Example Session
User: Use linear-quality-audit skill
Claude: Loading board context from data/board.json...
Running targeted queries to find problematic tickets...
• Missing team labels: 1 ticket
• Missing platform labels: 3 tickets
• Missing assignees: 2 tickets
• Missing projects: 1 ticket
• Recently created: 250 tickets
• Recently updated: 250 tickets
Analyzing 52 unique tickets (deduped)...
# Linear Quality Audit
**Generated:** 2025-11-05 10:30 AM
**Audited:** 52 unique tickets (deduped from 507 total queries)
**Problems:** 5 tickets (9.6%)
**Excluded Teams:** AI & Research
## Summary
| Problem | Count | % |
|---------|-------|---|
| Missing Labels | 3 | 60% |
| Missing Assignee | 1 | 20% |
| Missing Project | 1 | 20% |
## Attribution by Creator
### Nikhil Vaish - 2 quality issues
**Missing Labels (2):**
- ENG-1401: Selected address indicator - Missing: Platform label
- ENG-1520: Redis migration - Missing: Team label
### John Doe - 1 quality issue
**Missing Assignee (1):**
- ENG-1522: Fix login bug - Status: In Progress
Where would you like to save this report?