sc-research 1.0.13 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,57 +1,21 @@
1
1
  ---
2
2
  name: social_media_discovery
3
- description: Analyze existing Reddit/X raw data to find emerging or viral themes and generate `classified_discovery.json` with strict `DiscoveryData` output.
3
+ description: Analysis-only worker. Reads existing raw Reddit/X data to find emerging or viral themes and generates `classified_discovery.json` with strict `DiscoveryData` output.
4
4
  ---
5
5
 
6
6
  # Social Media Discovery Skill
7
7
 
8
- This worker clusters noisy social discussions into trend themes that can be visualized.
8
+ This worker clusters noisy social discussions into trend themes that can be visualized. It performs **analysis only** — fetching is handled by the orchestrator via `social_media_fetch`.
9
9
 
10
- ## Required Inputs
10
+ ## Prerequisites
11
11
 
12
- Use existing raw files only:
12
+ The following files must already exist (produced by `social_media_fetch`):
13
13
 
14
- - `reddit_data.json`
15
- - `x_data.json`
14
+ - `reddit_data.json` and/or `x_data.json`
16
15
 
17
- At least one valid source file must exist.
16
+ At least one valid source file must be present. If both are missing, **stop and report failure** — do not attempt to fetch data.
18
17
 
19
- ## Command Execution Flow
20
-
21
- Use this sequence when running discovery end-to-end:
22
-
23
- 1. Fetch or refresh discovery raw data (outside this worker):
24
-
25
- - Broad weekly discovery feed: `sc-research research:deep "DISCOVERY_WEEKLY" --mode=discovery`
26
- - Topic-focused discovery: `sc-research research:deep "TOPIC" --mode=discovery`
27
- - Optional filters: `--source=reddit|x|both --from=YYYY-MM-DD --to=YYYY-MM-DD`
28
-
29
- 2. Run this `social_media_discovery` worker to analyze existing raw files and produce `classified_discovery.json`.
30
- 3. Optional visualization step:
31
-
32
- - `sc-research visualize`
33
-
34
- If raw files are missing, stale, or mismatched for the requested topic/date range, instruct the caller to run step 1 first.
35
-
36
- ## Discovery Fetch Behavior (Code-Aligned)
37
-
38
- When `--mode=discovery` is used, runtime behavior differs by topic:
39
-
40
- 1. If topic is exactly `DISCOVERY_WEEKLY` and Reddit is enabled:
41
-
42
- - Fetches Reddit trending posts from `r/popular/top` with `t=week` and limit `25`.
43
-
44
- 2. For other topics in discovery mode and Reddit enabled:
45
-
46
- - Maps topic to candidate subreddits first.
47
- - Per subreddit, uses either top posts (`week`, limit `5`) or subreddit search (`week`, limit `5`) based on topic/subreddit match.
48
- - If mapping returns no subreddits, falls back to legacy Reddit keyword-thread flow.
49
-
50
- 3. X source behavior:
51
-
52
- - X fetch still runs through normal X search flow (`maxItems` based on depth), even in discovery mode.
53
-
54
- This skill consumes the resulting `reddit_data.json` / `x_data.json`; it does not perform fetching itself.
18
+ **Note on discovery data**: For best results, the orchestrator should have fetched with `--mode=discovery`. This skill analyzes whatever raw data exists — it does not control how data was fetched.
55
19
 
56
20
  ## Step 1: Preflight Validation
57
21
 
@@ -112,6 +76,54 @@ Save strict JSON to:
112
76
 
113
77
  - `classified_discovery.json`
114
78
 
79
+ ## Output Type Contract
80
+
81
+ Your output MUST match this exact shape. The dashboard detects discovery data by checking for `trending_topics` (array). Missing this field = broken tab.
82
+
83
+ **WARNING**: Discovery uses DIFFERENT enum casing than other skills. Everything is **lowercase** here.
84
+
85
+ ```json
86
+ {
87
+ "topic": "AI tools 2025",
88
+ "period": "2025-01-01 to 2025-01-31",
89
+ "total_posts_analyzed": 156,
90
+ "trending_topics": [
91
+ {
92
+ "id": "local-llm-hosting",
93
+ "topic_name": "Local LLM Hosting",
94
+ "description": "Growing interest in running language models locally using consumer hardware",
95
+ "category": "Technology",
96
+ "engagement_score": 4500,
97
+ "sentiment": "positive",
98
+ "key_posts": [
99
+ {
100
+ "title": "I got Llama 3 running on my M3 MacBook and it's incredible",
101
+ "url": "https://reddit.com/r/LocalLLaMA/comments/mno345",
102
+ "platform": "reddit",
103
+ "engagement": 2100
104
+ }
105
+ ],
106
+ "highlight_comments": [
107
+ {
108
+ "text": "The performance gains with quantization are impressive",
109
+ "author": "u/ml_enthusiast",
110
+ "link": "https://reddit.com/r/LocalLLaMA/comments/mno345/comment/abc",
111
+ "platform": "reddit"
112
+ }
113
+ ]
114
+ }
115
+ ]
116
+ }
117
+ ```
118
+
119
+ ### Enum Rules for Discovery (ALL LOWERCASE)
120
+
121
+ Discovery is the **only** classified type that uses lowercase sentiment values. Do NOT copy Title Case from rank/sentiment/controversy.
122
+
123
+ - `sentiment` on DiscoveryTopic: **lowercase** — `"positive"`, `"negative"`, `"neutral"`, `"mixed"`. NEVER use `"Positive"`, `"Mixed"`, or `"Very Positive"`.
124
+ - `platform` on key_posts and highlight_comments: **lowercase** — `"reddit"`, `"x"`. NEVER use `"Reddit"`, `"X"`, or `"twitter"`.
125
+ - `id`: use a **slug-like** identifier (e.g., `"local-llm-hosting"`), not a UUID or number.
126
+
115
127
  ## Final Validation Checklist
116
128
 
117
129
  - JSON parse succeeds.
@@ -1,61 +1,83 @@
1
1
  ---
2
2
  name: social_media_fetch
3
- description: Worker skill that fetches raw discussion data from Reddit and X into `reddit_data.json` and `x_data.json`. Use before running rank, sentiment, trend, controversy, or discovery analysis.
3
+ description: The sole data-fetching authority for the research pipeline. Handles CLI execution, data freshness checks, and output validation. Always called by the orchestrator never by worker skills directly.
4
4
  ---
5
5
 
6
6
  # Social Media Fetch Skill
7
7
 
8
- This worker is the data-ingestion step for the pipeline. It fetches raw social data only and does not classify or analyze it.
8
+ This is the **only** skill that runs `sc-research research` CLI commands. No other skill or command should execute fetch commands. The orchestrator delegates here; worker skills consume the output.
9
9
 
10
- ## Inputs and Outputs
10
+ ## Inputs (provided by orchestrator)
11
11
 
12
- - **Input**: User topic and optional filters (`source`, `from/to`, `mode`)
13
- - **Output files** (project root):
14
- - `reddit_data.json`
15
- - `x_data.json`
12
+ The orchestrator will specify:
13
+
14
+ - **topic**: the search query string
15
+ - **depth**: `quick` or `deep`
16
+ - **mode**: `research` (default) or `discovery`
17
+ - **source** (optional): `reddit`, `x`, or omit for all available
18
+ - **date range** (optional): `from` / `to` as `YYYY-MM-DD`
19
+
20
+ ## Outputs
21
+
22
+ - `reddit_data.json` (project root)
23
+ - `x_data.json` (project root)
16
24
 
17
25
  At least one output file must be produced for a successful fetch.
18
26
 
19
- ## Command Execution Flow
27
+ ---
20
28
 
21
- Run one of these commands based on requested depth:
29
+ ## Step 1: Check Data Freshness
22
30
 
23
- - Quick fetch: `sc-research research "TOPIC"`
24
- - Deep fetch: `sc-research research:deep "TOPIC"`
25
- - Discovery fetch: `sc-research research:deep "TOPIC" --mode=discovery`
31
+ Before running a new fetch, check whether existing raw files can be reused:
26
32
 
27
- Then validate outputs (`reddit_data.json` / `x_data.json`) before handing off to analysis workers.
33
+ 1. Does `reddit_data.json` or `x_data.json` exist?
34
+ 2. Is the file valid JSON with a top-level `items` array?
35
+ 3. Does the `query` field match the current topic (same or equivalent intent)?
36
+ 4. Does the `dateRange` match the requested window (if provided)?
37
+ 5. Does the source scope match (e.g., if user asked for Reddit-only, is Reddit data present)?
28
38
 
29
- ## Step 1: Choose Fetch Mode
39
+ **If all checks pass** skip fetch, use existing data and report "Using cached data."
40
+ **If any check fails** → proceed with fresh fetch.
30
41
 
31
- - **Quick mode** (faster, lighter coverage):
32
- - `sc-research research "TOPIC"`
33
- - **Deep mode** (default for analysis workflows):
34
- - `sc-research research:deep "TOPIC"`
35
- - **Discovery mode** (theme clustering data):
36
- - `sc-research research:deep "TOPIC" --mode=discovery`
42
+ ## Step 2: Build CLI Command
37
43
 
38
- ## Step 2: Build Command with Optional Flags
44
+ Construct the command based on inputs:
39
45
 
40
- Use flags only when requested:
46
+ **Standard analysis routes:**
41
47
 
42
- - `--source=reddit|x|both`
43
- - `--from=YYYY-MM-DD --to=YYYY-MM-DD`
44
- - `--mode=discovery`
48
+ ```bash
49
+ sc-research research:deep "TOPIC"
50
+ ```
51
+
52
+ **Quick-answer route:**
45
53
 
46
- When `--source` is omitted, runtime attempts all enabled sources (based on available API keys). A source without its required key is skipped.
54
+ ```bash
55
+ sc-research research "TOPIC" --source=reddit
56
+ ```
47
57
 
48
- Examples:
58
+ **Discovery route (broad weekly):**
49
59
 
50
60
  ```bash
51
- sc-research research:deep "wireless earbuds"
52
- sc-research research:deep "wireless earbuds" --source=reddit --from=2025-01-01 --to=2025-12-31
53
- sc-research research:deep "wireless earbuds" --mode=discovery --source=both
61
+ sc-research research:deep "DISCOVERY_WEEKLY" --mode=discovery
54
62
  ```
55
63
 
56
- ## Step 3: Validate Fetch Results
64
+ **Discovery route (topic-focused):**
65
+
66
+ ```bash
67
+ sc-research research:deep "TOPIC" --mode=discovery
68
+ ```
57
69
 
58
- After running the command, verify each produced source file:
70
+ Append optional flags only when provided by the orchestrator:
71
+
72
+ - `--source=reddit|x|both`
73
+ - `--from=YYYY-MM-DD --to=YYYY-MM-DD`
74
+ - `--mode=discovery`
75
+
76
+ When `--source` is omitted, runtime uses all sources whose API keys are available.
77
+
78
+ ## Step 3: Execute and Validate
79
+
80
+ Run the constructed command, then validate each produced file:
59
81
 
60
82
  1. File exists.
61
83
  2. JSON is parseable.
@@ -65,30 +87,40 @@ After running the command, verify each produced source file:
65
87
 
66
88
  If a source was explicitly requested but its file is missing or malformed, report the failure clearly.
67
89
 
68
- ## Step 4: Return a Fetch Summary
90
+ ## Step 4: Return Fetch Summary
69
91
 
70
- Return:
92
+ Return to the orchestrator:
71
93
 
72
94
  - topic
73
- - selected mode
74
- - selected sources
95
+ - mode used (`research` / `discovery`)
96
+ - sources fetched
75
97
  - date range used
76
98
  - item count per source
77
- - any missing-source or partial-result warnings
99
+ - any warnings (missing source, partial results, cached data reuse)
78
100
 
79
- ## Critical Rules
101
+ ---
102
+
103
+ ## Discovery Fetch Behavior (runtime details)
104
+
105
+ When `--mode=discovery` is used, runtime behavior differs by topic:
80
106
 
81
- 1. **No analysis here**: do not rank/classify in this skill.
82
- 2. **No fabricated data**: do not create synthetic posts to fill gaps.
83
- 3. **Prefer deep mode for analysis pipelines**: quick mode is for explicit quick-answer requests.
84
- 4. **Fail loudly on malformed output**: do not continue as if fetch succeeded when validation fails.
107
+ 1. Topic is exactly `DISCOVERY_WEEKLY` with Reddit enabled → fetches `r/popular/top` with `t=week`, limit `25`.
108
+ 2. Other topics in discovery mode with Reddit enabled → maps topic to candidate subreddits, then fetches top posts or searches per subreddit.
109
+ 3. X source runs normal X search flow regardless of discovery mode.
85
110
 
86
111
  ## Error Handling
87
112
 
88
- | Scenario | Symptom | Action |
89
- | ---------------------------------- | ------------------------------------------ | -------------------------------------------------------- |
90
- | Missing `OPENAI_API_KEY` | Auth failure on Reddit fetch | Set valid `OPENAI_API_KEY` in `.sc-research` |
91
- | Missing `XAI_API_KEY` | X file missing/empty while Reddit succeeds | Set `XAI_API_KEY` in `.sc-research` to enable X fetching |
92
- | No relevant results | `items` is empty | Broaden topic keywords and retry |
93
- | Rate limit / transient API failure | Timeout or provider error | Wait, then retry once with same parameters |
94
- | Malformed output | JSON parse failure or missing `items` | Re-run fetch; if repeated, report failure explicitly |
113
+ | Scenario | Symptom | Action |
114
+ | ---------------------------------- | ------------------------------------- | ---------------------------------------------------- |
115
+ | Missing `OPENAI_API_KEY` | Auth failure on Reddit fetch | Set valid `OPENAI_API_KEY` in `.sc-research` |
116
+ | Missing `XAI_API_KEY` | X file missing while Reddit succeeds | Set `XAI_API_KEY` in `.sc-research` to enable X |
117
+ | No relevant results | `items` is empty | Broaden topic keywords and retry |
118
+ | Rate limit / transient API failure | Timeout or provider error | Wait, then retry once with same parameters |
119
+ | Malformed output | JSON parse failure or missing `items` | Re-run fetch; if repeated, report failure explicitly |
120
+
121
+ ## Critical Rules
122
+
123
+ 1. **No analysis here** — do not rank, classify, or generate classified files.
124
+ 2. **No fabricated data** — do not create synthetic posts.
125
+ 3. **This is the only fetch point** — worker skills must never run fetch commands.
126
+ 4. **Fail loudly** — do not continue as if fetch succeeded when validation fails.
@@ -1,33 +1,19 @@
1
1
  ---
2
2
  name: social_media_rank
3
- description: Analyze existing Reddit/X raw data and generate `classified_rank.json` using the strict `ClassifiedData` schema. Use for ranking, best-of, compare, or recommendation requests.
3
+ description: Analysis-only worker. Reads existing raw Reddit/X data and generates `classified_rank.json` using the strict `ClassifiedData` schema. Use for ranking, best-of, compare, or recommendation requests.
4
4
  ---
5
5
 
6
6
  # Social Media Ranking Skill
7
7
 
8
- This worker converts raw discussion data into a ranked report suitable for the dashboard.
8
+ This worker converts raw discussion data into a ranked report suitable for the dashboard. It performs **analysis only** — fetching is handled by the orchestrator via `social_media_fetch`.
9
9
 
10
- ## Required Inputs
10
+ ## Prerequisites
11
11
 
12
- Use existing files only:
12
+ The following files must already exist (produced by `social_media_fetch`):
13
13
 
14
- - `reddit_data.json`
15
- - `x_data.json`
14
+ - `reddit_data.json` and/or `x_data.json`
16
15
 
17
- At least one valid source file must exist.
18
-
19
- ## Command Execution Flow
20
-
21
- Use this sequence for ranking:
22
-
23
- 1. Fetch or refresh raw data (outside this worker):
24
- - `sc-research research:deep "TOPIC"`
25
- - Optional filters: `--source=reddit|x|both --from=YYYY-MM-DD --to=YYYY-MM-DD`
26
- 2. Run this `social_media_rank` worker to generate `classified_rank.json`.
27
- 3. Optional visualization:
28
- - `sc-research visualize`
29
-
30
- If raw files are missing, stale, or mismatched for the requested topic/date range, run step 1 first.
16
+ At least one valid source file must be present. If both are missing, **stop and report failure** — do not attempt to fetch data.
31
17
 
32
18
  ## Step 1: Preflight Validation
33
19
 
@@ -91,6 +77,49 @@ Required top-level fields:
91
77
  - `products`
92
78
  - `key_insights`
93
79
 
80
+ ## Output Type Contract
81
+
82
+ Your output MUST match this exact shape. The dashboard detects rank data by checking for `products` (array) + `key_insights` (array). Missing either field = broken tab.
83
+
84
+ ```json
85
+ {
86
+ "topic": "best wireless earbuds 2025",
87
+ "products": [
88
+ {
89
+ "rank": 1,
90
+ "name": "Sony WF-1000XM5",
91
+ "sentiment": "Very Positive",
92
+ "mentions": 42,
93
+ "estimated_engagement_score": 8750,
94
+ "consensus": "Widely praised for ANC quality and sound clarity",
95
+ "pros": [
96
+ "Best-in-class ANC",
97
+ "Excellent sound quality",
98
+ "Comfortable fit"
99
+ ],
100
+ "cons": ["Premium price", "Average battery life"],
101
+ "highlight_quotes": [
102
+ {
103
+ "text": "The XM5s completely changed how I listen to music",
104
+ "author": "u/audiophile_reviews",
105
+ "link": "https://reddit.com/r/headphones/comments/abc123",
106
+ "context": "pro"
107
+ }
108
+ ]
109
+ }
110
+ ],
111
+ "key_insights": [
112
+ "Sony and Apple dominate recommendations with 70% of mentions",
113
+ "ANC quality is the most-discussed factor across all posts"
114
+ ]
115
+ }
116
+ ```
117
+
118
+ ### Enum Rules for Rank
119
+
120
+ - `sentiment` on Product: **Title Case** — `"Very Positive"`, `"Positive"`, `"Mixed"`, `"Negative"`. NEVER use `"positive"` or `"neutral"`.
121
+ - `context` on quotes: **lowercase** — `"pro"`, `"con"`, `"general"`. NEVER use `"Pro"` or `"Con"`.
122
+
94
123
  ## Final Validation Checklist
95
124
 
96
125
  - JSON is parseable.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: social_media_schema
3
- description: Reference-only skill that defines canonical JSON schemas for classified output files.
3
+ description: Reference-only skill that defines canonical JSON schemas for classified output files. Includes enum warnings and dashboard detection rules.
4
4
  ---
5
5
 
6
6
  # Social Media Schema Reference
@@ -13,7 +13,7 @@ Use this file as the canonical schema source for all classified outputs:
13
13
  - `classified_controversy.json`
14
14
  - `classified_discovery.json`
15
15
 
16
- If another skill instruction conflicts with this file, this file wins.
16
+ If another skill instruction conflicts with this file, **this file wins**.
17
17
 
18
18
  ## Command Execution Note
19
19
 
@@ -22,20 +22,91 @@ This is a reference-only skill. There is no direct CLI command to run this skill
22
22
  - Use it by reading this schema before writing any `classified_*.json` output.
23
23
  - Runnable commands belong to fetch/analysis/visualize skills (for example `sc-research research:deep "TOPIC"` and `sc-research visualize`).
24
24
 
25
+ ---
26
+
27
+ ## Dashboard Detection Rules
28
+
29
+ The web dashboard auto-detects which classified type a JSON file contains by checking for **unique field signatures**. If required fields are missing or misnamed, that tab will not appear.
30
+
31
+ | Classified Type | Detection Rule (fields checked) | Dashboard Tab |
32
+ | --------------- | ----------------------------------------------------------- | ------------------- |
33
+ | **rank** | `products` (array) AND `key_insights` (array) | Product Rankings |
34
+ | **sentiment** | `distribution` (object) AND `by_source` (object) | Sentiment Analysis |
35
+ | **trend** | `date_range` (object) AND `timeline` (array) | Trend Timeline |
36
+ | **controversy** | `overall_divisiveness` (string) AND `controversies` (array) | Controversy Map |
37
+ | **discovery** | `trending_topics` (array) | Discovery Dashboard |
38
+
39
+ **These field names are non-negotiable.** Renaming, omitting, or nesting them differently will break dashboard detection.
40
+
41
+ ---
42
+
43
+ ## Enum Value Warnings
44
+
45
+ ### SentimentLabel (Title Case — used in rank, sentiment, controversy contexts)
46
+
47
+ ```
48
+ CORRECT: "Very Positive", "Positive", "Mixed", "Negative"
49
+ WRONG: "very positive", "very_positive", "POSITIVE", "positive", "neutral"
50
+ ```
51
+
52
+ `"neutral"` is NOT a valid SentimentLabel. Use `"Mixed"` instead.
53
+
54
+ ### Divisiveness (Title Case — used in controversy)
55
+
56
+ ```
57
+ CORRECT: "Low", "Medium", "High"
58
+ WRONG: "low", "medium", "high", "LOW", "MEDIUM", "HIGH"
59
+ ```
60
+
61
+ ### Discovery sentiment (lowercase — DIFFERENT from SentimentLabel)
62
+
63
+ ```
64
+ CORRECT: "positive", "negative", "neutral", "mixed"
65
+ WRONG: "Positive", "Negative", "Neutral", "Mixed", "Very Positive"
66
+ ```
67
+
68
+ Discovery is the ONLY type that uses lowercase sentiment and includes `"neutral"`.
69
+
70
+ ### Discovery platform (lowercase)
71
+
72
+ ```
73
+ CORRECT: "reddit", "x"
74
+ WRONG: "Reddit", "X", "twitter", "Twitter"
75
+ ```
76
+
77
+ ### Key Moment significance (lowercase — used in trend)
78
+
79
+ ```
80
+ CORRECT: "high", "medium", "low"
81
+ WRONG: "High", "Medium", "Low"
82
+ ```
83
+
84
+ ### Quote context (lowercase — used in rank)
85
+
86
+ ```
87
+ CORRECT: "pro", "con", "general"
88
+ WRONG: "Pro", "Con", "General"
89
+ ```
90
+
91
+ ---
92
+
25
93
  ## Canonical Type Definitions
26
94
 
27
95
  ```typescript
96
+ // === RANK (classified_rank.json) ===
97
+ // Dashboard detects via: products + key_insights
98
+
28
99
  export interface ClassifiedData {
29
100
  topic: string;
30
101
  source_file?: string;
31
- products: Product[];
32
- key_insights: string[];
102
+ products: Product[]; // REQUIRED for dashboard detection
103
+ key_insights: string[]; // REQUIRED for dashboard detection
33
104
  }
34
105
 
35
106
  export interface Product {
36
107
  rank: number;
37
108
  name: string;
38
- sentiment: SentimentLabel;
109
+ sentiment: SentimentLabel; // Title Case: "Positive", "Mixed", etc.
39
110
  mentions: number;
40
111
  estimated_engagement_score: number;
41
112
  consensus: string;
@@ -45,7 +116,7 @@ export interface Product {
45
116
  text: string;
46
117
  author: string;
47
118
  link: string;
48
- context?: "pro" | "con" | "general";
119
+ context?: "pro" | "con" | "general"; // lowercase
49
120
  }>;
50
121
  }
51
122
 
@@ -55,16 +126,21 @@ export type SentimentLabel =
55
126
  | "Mixed"
56
127
  | "Very Positive";
57
128
 
129
+ // === SENTIMENT (classified_sentiment.json) ===
130
+ // Dashboard detects via: distribution + by_source
131
+
58
132
  export interface SentimentData {
59
133
  topic: string;
60
134
  overall_mood: SentimentLabel;
61
135
  distribution: {
62
- very_positive: number;
136
+ // REQUIRED for dashboard detection
137
+ very_positive: number; // snake_case keys, not camelCase
63
138
  positive: number;
64
139
  mixed: number;
65
140
  negative: number;
66
141
  };
67
142
  by_source: {
143
+ // REQUIRED for dashboard detection
68
144
  reddit: SourceSentiment;
69
145
  x: SourceSentiment;
70
146
  };
@@ -87,23 +163,27 @@ export interface ProductSentiment {
87
163
  text: string;
88
164
  author: string;
89
165
  link: string;
90
- sentiment: SentimentLabel;
166
+ sentiment: SentimentLabel; // Title Case
91
167
  }>;
92
168
  }
93
169
 
170
+ // === TREND (classified_trend.json) ===
171
+ // Dashboard detects via: date_range + timeline
172
+
94
173
  export interface TrendData {
95
174
  topic: string;
96
175
  date_range: {
176
+ // REQUIRED for dashboard detection
97
177
  from: string;
98
178
  to: string;
99
179
  };
100
180
  granularity?: "day" | "week" | "month";
101
- timeline: TimelinePoint[];
181
+ timeline: TimelinePoint[]; // REQUIRED for dashboard detection
102
182
  key_moments: KeyMoment[];
103
183
  }
104
184
 
105
185
  export interface TimelinePoint {
106
- period: string;
186
+ period: string; // Format depends on granularity (see worker skill)
107
187
  post_count: number;
108
188
  total_engagement: number;
109
189
  reddit_posts: number;
@@ -113,20 +193,23 @@ export interface TimelinePoint {
113
193
  export interface KeyMoment {
114
194
  date: string;
115
195
  event: string;
116
- significance: "high" | "medium" | "low";
196
+ significance: "high" | "medium" | "low"; // lowercase
117
197
  url?: string;
118
198
  }
119
199
 
200
+ // === CONTROVERSY (classified_controversy.json) ===
201
+ // Dashboard detects via: overall_divisiveness + controversies
202
+
120
203
  export interface ControversyData {
121
204
  topic: string;
122
- overall_divisiveness: "Low" | "Medium" | "High";
123
- controversies: Controversy[];
205
+ overall_divisiveness: "Low" | "Medium" | "High"; // REQUIRED + Title Case
206
+ controversies: Controversy[]; // REQUIRED for dashboard detection
124
207
  }
125
208
 
126
209
  export interface Controversy {
127
210
  topic: string;
128
- heat_score: number;
129
- divisiveness: "Low" | "Medium" | "High";
211
+ heat_score: number; // 0-100
212
+ divisiveness: "Low" | "Medium" | "High"; // Title Case
130
213
  side_a: ControversySide;
131
214
  side_b: ControversySide;
132
215
  }
@@ -141,11 +224,14 @@ export interface ControversySide {
141
224
  }>;
142
225
  }
143
226
 
227
+ // === DISCOVERY (classified_discovery.json) ===
228
+ // Dashboard detects via: trending_topics
229
+
144
230
  export interface DiscoveryData {
145
231
  topic: string;
146
232
  period: string;
147
233
  total_posts_analyzed: number;
148
- trending_topics: DiscoveryTopic[];
234
+ trending_topics: DiscoveryTopic[]; // REQUIRED for dashboard detection
149
235
  }
150
236
 
151
237
  export interface DiscoveryTopic {
@@ -154,20 +240,20 @@ export interface DiscoveryTopic {
154
240
  description: string;
155
241
  category: string;
156
242
  engagement_score: number;
157
- sentiment: "positive" | "negative" | "neutral" | "mixed";
243
+ sentiment: "positive" | "negative" | "neutral" | "mixed"; // lowercase!
158
244
  key_posts: KeyPost[];
159
245
  highlight_comments: Array<{
160
246
  text: string;
161
247
  author: string;
162
248
  link: string;
163
- platform: "reddit" | "x";
249
+ platform: "reddit" | "x"; // lowercase
164
250
  }>;
165
251
  }
166
252
 
167
253
  export interface KeyPost {
168
254
  title: string;
169
255
  url: string;
170
- platform: "reddit" | "x";
256
+ platform: "reddit" | "x"; // lowercase
171
257
  engagement: number;
172
258
  thumbnail?: string;
173
259
  }