Bug Clustering Process
Step-by-step procedure for transforming raw XPost objects into structured, clustered bug candidates with PII redaction and reliability scoring.
Overview
Loaded by the bug-clusterer agent inside the x-bug-triage plugin. Transforms raw XPost records ingested from X/Twitter into structured BugCandidate rows, deduplicates near-identical candidates, classifies each candidate into one of 12 bug families, redacts six categories of PII, scores reporter reliability across four dimensions, and groups results into bug clusters by deterministic signature. The output feeds the downstream repo-scanning, owner-routing, and triage-display stages.
Prerequisites
- Database initialized via
lib/db.ts schema migrations
config/cluster-matching-thresholds.json present (controls dedup + cluster overlap thresholds)
config/approved-accounts.json present (drives reporter category tagging)
- Raw
XPost[] array passed in by the orchestrator (not fetched here)
Instructions
Step 1: Parse
For each XPost, produce a BugCandidate with all 33 fields using lib/parser.ts:
- Extract product_surface, feature_area, symptoms, error_strings, repro_hints
- Extract urls, media_keys, language, conversation references
- Determine source_type (mention, reply, quote_post, search_hit)
Step 1.5: Deduplicate
Before classification, run content-similarity deduplication using lib/dedupe.ts:
- Call
deduplicateCandidates() with parsed candidates and the candidate_dedup.hybrid_similarity_threshold from config/cluster-matching-thresholds.json (default 0.70)
- Uses char-trigram + token-Jaccard hybrid similarity
- Does NOT remove posts — tags them as duplicate groups with a canonical post (highest engagement)
- Only canonical posts and non-duplicates (
forward_ids) proceed to classification
- Log dedup stats in the form: "N posts (M unique, K duplicate groups)" with N/M/K replaced by integer counts
Step 2: Classify
Run lib/classifier.ts on each candidate:
- Assign one of 12 classifications with confidence score (0.0-1.0) and rationale
- Sarcastic bug reports get classified separately — still treated as signal
Step 3: Redact PII
Run lib/redactor.ts on each candidate:
- Detect 6 PII types: email, API key, phone, account ID, media flag, URL token
- Replace with [REDACTED:type] tags
- Set pii_flags array and raw_text_storage_policy
Step 4: Score Reliability
Run lib/reporter-scorer.ts on each candidate:
- 4 dimensions: report quality, independence, account authenticity, historical accuracy
- Composite reporter_reliability_score (0.0-1.0)
Step 5: Tag Reporter Category
Match author against approved_accounts config:
- Categories: public, internal, partner, tester
Step 6: Cluster
Using lib/clusterer.ts and lib/signatures.ts:
- Generate deterministic bug signature from error_strings + symptoms + feature_area
- Match against active_clusters at >=70% signature overlap
- Family-first guard: different ClusterFamilies NEVER cluster together
- New match: create cluster (initial severity "low")
- Existing match: update report_count, last_seen, sub_status
- Resolved match: reopen with sub_status "regression_reopened"
- Suppressed match: skip, log to audit
Step 7: Persist
- Insert candidates to DB via
lib/db.ts
- Insert/update clusters and cluster_posts junction
- Write audit events for each classification, redaction, and cluster action
Output
bug_candidates rows with classification, PII flags, and reporter reliability scores
bug_clusters rows (new or updated) with severity, sub_status, and report_count
cluster_posts junction rows linking candidates to clusters
- Audit-event rows recording every classification, redaction, and cluster action
Error Handling
- Parser failure on a single XPost: log + skip, continue with remaining posts (degraded mode)
- Classification confidence below threshold: still recorded, flagged for human review
- Cluster signature collision across families: hard-blocked by the family-first guard — never cross-clusters
- Persist failure mid-batch: rollback uncommitted writes for that batch only; preserve already-committed work
Examples
The bug-clusterer agent invokes this skill after the X/Twitter ingest phase completes. A typical batch processes 50–500 candidates per run, producing 5–30 clusters depending on overlap. Sample audit log line: "127 posts (89 unique, 14 duplicate groups, 6 new clusters, 8 cluster updates)".
Resources
Load evidence tier definitions for proper cluster evidence assessment:
!cat skills/x-bug-triage/references/evidence-policy.md
Load data model reference for BugCandidate fields and cluster schemas:
!cat skills/x-bug-triage/references/schemas.md
Source: jeremylongshore/claude-code-plugins-plus-skills → plugins/mcp/x-bug-triage/skills/bug-clustering/SKILL.md
1---
2name: bug-clustering
3description: "| Internal process for the bug-clusterer agent. Defines the step-by-step procedure for parsing, classifying, redacting, scoring, and clustering bug candidates from raw X/Twitter posts. Not user-invocable — loaded by the bug-clusterer agent through its skills frontmatter."
4allowed-tools: "Read, Bash(cat:*), Grep, Glob"
5model: "inherit"
6category: data-science-and-ml
7source_repo: jeremylongshore/claude-code-plugins-plus-skills
8source_path: "plugins/mcp/x-bug-triage/skills/bug-clustering/SKILL.md"
9source_url: https://github.com/jeremylongshore/claude-code-plugins-plus-skills/blob/HEAD/plugins/mcp/x-bug-triage/skills/bug-clustering/SKILL.md
10---
11
12
13# Bug Clustering Process
14
15Step-by-step procedure for transforming raw XPost objects into structured, clustered bug candidates with PII redaction and reliability scoring.
16
17## Overview
18
19Loaded by the `bug-clusterer` agent inside the `x-bug-triage` plugin. Transforms raw `XPost` records ingested from X/Twitter into structured `BugCandidate` rows, deduplicates near-identical candidates, classifies each candidate into one of 12 bug families, redacts six categories of PII, scores reporter reliability across four dimensions, and groups results into bug clusters by deterministic signature. The output feeds the downstream repo-scanning, owner-routing, and triage-display stages.
20
21## Prerequisites
22
23- Database initialized via `lib/db.ts` schema migrations
24- `config/cluster-matching-thresholds.json` present (controls dedup + cluster overlap thresholds)
25- `config/approved-accounts.json` present (drives reporter category tagging)
26- Raw `XPost[]` array passed in by the orchestrator (not fetched here)
27
28## Instructions
29
30### Step 1: Parse
31
32For each XPost, produce a BugCandidate with all 33 fields using `lib/parser.ts`:
33- Extract product_surface, feature_area, symptoms, error_strings, repro_hints
34- Extract urls, media_keys, language, conversation references
35- Determine source_type (mention, reply, quote_post, search_hit)
36
37### Step 1.5: Deduplicate
38
39Before classification, run content-similarity deduplication using `lib/dedupe.ts`:
40- Call `deduplicateCandidates()` with parsed candidates and the `candidate_dedup.hybrid_similarity_threshold` from `config/cluster-matching-thresholds.json` (default 0.70)
41- Uses char-trigram + token-Jaccard hybrid similarity
42- Does NOT remove posts — tags them as duplicate groups with a canonical post (highest engagement)
43- Only canonical posts and non-duplicates (`forward_ids`) proceed to classification
44- Log dedup stats in the form: "N posts (M unique, K duplicate groups)" with N/M/K replaced by integer counts
45
46### Step 2: Classify
47
48Run `lib/classifier.ts` on each candidate:
49- Assign one of 12 classifications with confidence score (0.0-1.0) and rationale
50- Sarcastic bug reports get classified separately — still treated as signal
51
52### Step 3: Redact PII
53
54Run `lib/redactor.ts` on each candidate:
55- Detect 6 PII types: email, API key, phone, account ID, media flag, URL token
56- Replace with [REDACTED:type] tags
57- Set pii_flags array and raw_text_storage_policy
58
59### Step 4: Score Reliability
60
61Run `lib/reporter-scorer.ts` on each candidate:
62- 4 dimensions: report quality, independence, account authenticity, historical accuracy
63- Composite reporter_reliability_score (0.0-1.0)
64
65### Step 5: Tag Reporter Category
66
67Match author against approved_accounts config:
68- Categories: public, internal, partner, tester
69
70### Step 6: Cluster
71
72Using `lib/clusterer.ts` and `lib/signatures.ts`:
73- Generate deterministic bug signature from error_strings + symptoms + feature_area
74- Match against active_clusters at >=70% signature overlap
75- Family-first guard: different ClusterFamilies NEVER cluster together
76- New match: create cluster (initial severity "low")
77- Existing match: update report_count, last_seen, sub_status
78- Resolved match: reopen with sub_status "regression_reopened"
79- Suppressed match: skip, log to audit
80
81### Step 7: Persist
82
83- Insert candidates to DB via `lib/db.ts`
84- Insert/update clusters and cluster_posts junction
85- Write audit events for each classification, redaction, and cluster action
86
87## Output
88
89- `bug_candidates` rows with classification, PII flags, and reporter reliability scores
90- `bug_clusters` rows (new or updated) with severity, sub_status, and report_count
91- `cluster_posts` junction rows linking candidates to clusters
92- Audit-event rows recording every classification, redaction, and cluster action
93
94## Error Handling
95
96- Parser failure on a single XPost: log + skip, continue with remaining posts (degraded mode)
97- Classification confidence below threshold: still recorded, flagged for human review
98- Cluster signature collision across families: hard-blocked by the family-first guard — never cross-clusters
99- Persist failure mid-batch: rollback uncommitted writes for that batch only; preserve already-committed work
100
101## Examples
102
103The bug-clusterer agent invokes this skill after the X/Twitter ingest phase completes. A typical batch processes 50–500 candidates per run, producing 5–30 clusters depending on overlap. Sample audit log line: "127 posts (89 unique, 14 duplicate groups, 6 new clusters, 8 cluster updates)".
104
105## Resources
106
107Load evidence tier definitions for proper cluster evidence assessment:
108
109```
110!cat skills/x-bug-triage/references/evidence-policy.md
111```
112
113Load data model reference for BugCandidate fields and cluster schemas:
114
115```
116!cat skills/x-bug-triage/references/schemas.md
117```
118
119---
120
121**Source:** [`jeremylongshore/claude-code-plugins-plus-skills`](https://github.com/jeremylongshore/claude-code-plugins-plus-skills) → `plugins/mcp/x-bug-triage/skills/bug-clustering/SKILL.md`