signal-forge
Intent
First stage of the AnimeLegends generative pipeline. Ingests trending anime topics from configured sources (Reddit anime communities, AniList trending), applies a weighted 4-axis scoring rubric (engagement 35%, brand-fit 30%, controversy 20%, recency 15%), strips any copyrighted character names or franchise references via legal firewall, assigns appropriate channel (PowerScaling/Philosophy/LoreDrop/TrainingArc/LegendsLabs) and mascot trinity (Mira/Kage/Akashi), and produces a validated SignalManifest JSON that feeds downstream to concept-forge.
Inputs
What this skill expects to receive:
interface SignalForgeInput {
source: "url" | "manual" | "ingest"; // input type
topic?: string; // manual topic string if source=manual
url?: string; // Reddit/AniList URL if source=url
override_legal?: boolean; // bypass legal firewall (default: false, requires explicit flag)
}
Source of input: user prompt via /from-signal command, or automatic ingest from configured Reddit/AniList monitors (if configured).
Outputs
What this skill produces:
interface SignalManifest {
signal_id: string; // UUID v4
topic_raw: string; // original topic before legal pass
topic_clean: string; // sanitized topic (copyrighted refs stripped)
source: string; // "reddit" | "anilist" | "manual"
source_url?: string; // original URL if from reddit/anilist
scores: {
engagement: number; // 0-100
brand_fit: number; // 0-100
controversy: number; // 0-100
recency: number; // 0-100, 48h half-life
weighted_total: number; // composite score
};
channel: string; // PowerScaling | Philosophy | LoreDrop | TrainingArc | LegendsLabs
mascots: string[]; // ["MIRA", "KAGE", "AKASHI"] trinity in assigned order
status: "accept" | "defer" | "reject";
legal_flags: string[]; // detected copyrighted refs (empty if clean)
timestamp: string; // ISO 8601
}
Where the output goes: passed to concept-forge as input, logged to grimoire-keeper, saved to signals/ directory if configured.
Core logic / rules
Source resolution — Determine input source: if source=url, extract topic from Reddit post title or AniList entry; if source=manual, use provided topic string directly; if source=ingest, poll configured monitors (Reddit r/anime, r/OnePiece, r/JujutsuKaisen, AniList trending API) every 30 minutes and queue top 5 new entries.
Legal firewall (pre-scoring) — Before scoring, scan topic_raw against the copyrighted reference database (character names from Shonen Jump, Studio Ghibli, Trigger, Ufotable, Mappa franchises). If match found: replace with [redacted character] or [redacted series] in topic_clean, log to legal_flags array. If override_legal=true (manual only), skip this step but still log detected refs.
4-axis scoring — Compute weighted scores:
Engagement (35%) : Reddit upvotes / 1000, AniList favorites / 10000, manual topics default to 50.
Brand-fit (30%) : keyword match against AnimeLegends brand pillars (training arcs, power systems, philosophy, lore depth) — score 0-100 via keyword density.
Controversy (20%) : Reddit comment velocity (comments/hour in first 6h), AniList discussion threads — higher = better. Manual topics default to 40.
Recency (15%) : exponential decay with 48h half-life. Topics >96h old score <10.
Weighted total : (engagement * 0.35) + (brand_fit * 0.30) + (controversy * 0.20) + (recency * 0.15).
Channel assignment — Map topic to sub-channel via keyword heuristics:
PowerScaling: "power level", "strongest", "vs", "battle"
Philosophy: "meaning", "theme", "philosophy", "symbolism"
LoreDrop: "explained", "lore", "theory", "timeline"
TrainingArc: "training", "growth", "journey", "development"
LegendsLabs: "animation", "sakuga", "production", "studio"
Default: Philosophy if no strong match.
Mascot trinity assignment — Assign mascot order based on channel:
PowerScaling: Akashi leads (closes with power judgment), Kage measures, Mira opens curiosity.
Philosophy: Mira leads (opens with wonder), Kage probes, Akashi synthesizes.
LoreDrop: Kage leads (analytical), Mira contextualizes, Akashi delivers verdict.
TrainingArc: Mira leads (warm journey framing), Akashi challenges, Kage measures progress.
LegendsLabs: Akashi leads (expertise assertion), Kage dissects, Mira humanizes.
Accept/defer/reject — Set status based on weighted_total: ≥60 = accept, 40-59 = defer (low priority queue), <40 = reject. Deferred topics resurface if engagement spikes within 48h.
Manifest generation — Populate SignalManifest with all fields, generate UUID for signal_id, set timestamp to ISO 8601 UTC.
Grimoire logging — Log invocation to grimoire-keeper with stage="signal-forge", input_id=null (first stage), output_id=signal_id, decision=status, rationale (one-line: why accepted/deferred/rejected), duration_ms.
Worked examples
Example 1: Reddit trending topic (accepted)
Input:
{
"source": "url",
"url": "https://reddit.com/r/anime/comments/xyz/why_gojos_domain_is_philosophically_perfect"
}
Output:
{
"signal_id": "550e8400-e29b-41d4-a716-446655440000",
"topic_raw": "Why Gojo's Domain is philosophically perfect",
"topic_clean": "Why [redacted character]'s Domain is philosophically perfect",
"source": "reddit",
"source_url": "https://reddit.com/r/anime/comments/xyz/why_gojos_domain_is_philosophically_perfect",
"scores": {
"engagement": 78,
"brand_fit": 92,
"controversy": 65,
"recency": 95,
"weighted_total": 81.65
},
"channel": "Philosophy",
"mascots": ["MIRA", "KAGE", "AKASHI"],
"status": "accept",
"legal_flags": ["Gojo (Jujutsu Kaisen)"],
"timestamp": "2026-08-16T09:15:00Z"
}
Why this output: High brand-fit (philosophy keyword), strong engagement, recent post. Legal firewall stripped "Gojo" (copyrighted Jujutsu Kaisen character). Philosophy channel assigned → Mira leads trinity.
Example 2: Manual topic (deferred)
Input:
{
"source": "manual",
"topic": "Best animation studios ranked by sakuga quality"
}
Output:
{
"signal_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"topic_raw": "Best animation studios ranked by sakuga quality",
"topic_clean": "Best animation studios ranked by sakuga quality",
"source": "manual",
"scores": {
"engagement": 50,
"brand_fit": 70,
"controversy": 40,
"recency": 50,
"weighted_total": 52.5
},
"channel": "LegendsLabs",
"mascots": ["AKASHI", "KAGE", "MIRA"],
"status": "defer",
"legal_flags": [],
"timestamp": "2026-08-16T09:20:00Z"
}
Why this output: Manual topics default to mid-range engagement/controversy/recency. Brand-fit moderate (sakuga/animation match). Weighted total 52.5 → defer status (40-59 range). LegendsLabs channel → Akashi leads.
Example 3: Stale low-engagement topic (rejected)
Input:
{
"source": "url",
"url": "https://anilist.co/anime/12345/discussions/old-minor-character-discussion"
}
Output:
{
"signal_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"topic_raw": "Old minor character discussion from 2024",
"topic_clean": "Old minor character discussion from 2024",
"source": "anilist",
"source_url": "https://anilist.co/anime/12345/discussions/old-minor-character-discussion",
"scores": {
"engagement": 15,
"brand_fit": 25,
"controversy": 10,
"recency": 5,
"weighted_total": 14.75
},
"channel": "Philosophy",
"mascots": ["MIRA", "KAGE", "AKASHI"],
"status": "reject",
"legal_flags": [],
"timestamp": "2026-08-16T09:25:00Z"
}
Why this output: Topic is >96h old (recency score 5), low engagement (15), weak brand-fit. Weighted total 14.75 < 40 → reject. Not queued for downstream processing.
Failure modes
No configured ingest sources — If source=ingest but Reddit API keys or AniList access is not configured, log error to Grimoire with status="error", return empty manifest, and notify user that manual topic input is required.
URL fetch timeout — If Reddit/AniList URL fetch times out (>10s), retry once after 2s delay. If second attempt fails, log error, set status="defer", and queue for retry in 30 minutes.
Legal firewall too aggressive — If topic is reduced to <5 words after stripping copyrighted refs (e.g., "Why [redacted] is [redacted]"), set status="reject", log to Grimoire with rationale="topic_too_vague_after_legal_pass", do not proceed downstream.
All scores zero — If engagement, brand-fit, controversy, recency all compute to 0 (malformed input), set status="reject", log rationale="insufficient_signal_data".
Missing topic — If source=manual but topic field is empty or null, return error: "Manual source requires non-empty topic string".
Grimoire logging contract
Every invocation of this skill logs via grimoire-keeper. Fields logged:
stage: "signal-forge"
input_id: null (first stage, no upstream manifest)
output_id: signal_id from generated SignalManifest
decision: "accept" | "defer" | "reject" | "error"
rationale: one-line explanation (e.g., "high_engagement_philosophy_topic", "stale_low_engagement", "legal_firewall_blocked")
cost_usd: 0.00 (no paid API calls at this stage)
duration_ms: elapsed time from input receipt to manifest generation
legal_flags: array of detected copyrighted references (empty if none)
Legal firewall
This skill enforces strict copyright filtering on all external content.
Copyrighted reference database
Maintained in brand/never-say.md (not in this repo — see AnimeLegends studio monorepo). Database includes:
Character names from Shonen Jump franchises (Naruto, One Piece, Bleach, Jujutsu Kaisen, My Hero Academia, Dragon Ball, etc.)
Studio Ghibli, Trigger, Ufotable, Mappa character and series names
Franchise-specific terminology (e.g., "Sharingan", "Hollow", "Quirk", "Stand", "Bankai")
Replacement behavior
Character name → [redacted character]
Series name → [redacted series]
Franchise term → [generic equivalent] (e.g., "Sharingan" → "special eye technique")
Override
Manual topics can set override_legal=true to bypass substitution (e.g., for fair-use commentary), but detected refs are still logged to legal_flags array for audit trail.
AnimeLegends original IP
The following are AnimeLegends original characters and are NEVER filtered:
AKASHI — wisdom keeper, deep reverb voice
KAGE — shadow analyst, metallic clarity
MIRA — wonder guide, warm curious tone
Quality gates
Output SignalManifest has all required fields (signal_id, topic_raw, topic_clean, source, scores, channel, mascots, status, legal_flags, timestamp)
signal_id is valid UUID v4
topic_clean is non-empty and ≥5 words after legal pass
scores.weighted_total is correctly computed: (engagement * 0.35) + (brand_fit * 0.30) + (controversy * 0.20) + (recency * 0.15)
status matches weighted_total thresholds: ≥60 accept, 40-59 defer, <40 reject
channel is one of: PowerScaling, Philosophy, LoreDrop, TrainingArc, LegendsLabs
mascots array has exactly 3 elements from {MIRA, KAGE, AKASHI}
legal_flags array populated if copyrighted refs detected
Grimoire log entry created with all required fields
No copyrighted character names in topic_clean unless override_legal=true
Changelog
0.1.0 — 2026-08-16
Initial release
4-axis scoring rubric (engagement 35%, brand-fit 30%, controversy 20%, recency 15%)
Legal firewall with copyrighted reference stripping
Channel and mascot assignment logic
Accept/defer/reject status based on weighted score thresholds
Grimoire logging integration
1 --- 2 name: signal-forge 3 description: Ingests trending topics, applies 4-axis scoring (engagement 35% · brand-fit 30% · controversy 20% · recency 15%), strips copyrighted references, routes to channel + mascot assignment, produces SignalManifest. 4 --- 5 6 # signal-forge 7 8 ## Intent 9 10 First stage of the AnimeLegends generative pipeline. Ingests trending anime topics from configured sources (Reddit anime communities, AniList trending), applies a weighted 4-axis scoring rubric (engagement 35%, brand-fit 30%, controversy 20%, recency 15%), strips any copyrighted character names or franchise references via legal firewall, assigns appropriate channel (PowerScaling/Philosophy/LoreDrop/TrainingArc/LegendsLabs) and mascot trinity (Mira/Kage/Akashi), and produces a validated `SignalManifest` JSON that feeds downstream to `concept-forge`. 11 12 ## Inputs 13 14 What this skill expects to receive: 15 16 ```typescript 17 interface SignalForgeInput { 18 source: "url" | "manual" | "ingest"; // input type 19 topic?: string; // manual topic string if source=manual 20 url?: string; // Reddit/AniList URL if source=url 21 override_legal?: boolean; // bypass legal firewall (default: false, requires explicit flag) 22 } 23 ``` 24 25 Source of input: user prompt via `/from-signal` command, or automatic ingest from configured Reddit/AniList monitors (if configured). 26 27 ## Outputs 28 29 What this skill produces: 30 31 ```typescript 32 interface SignalManifest { 33 signal_id: string; // UUID v4 34 topic_raw: string; // original topic before legal pass 35 topic_clean: string; // sanitized topic (copyrighted refs stripped) 36 source: string; // "reddit" | "anilist" | "manual" 37 source_url?: string; // original URL if from reddit/anilist 38 scores: { 39 engagement: number; // 0-100 40 brand_fit: number; // 0-100 41 controversy: number; // 0-100 42 recency: number; // 0-100, 48h half-life 43 weighted_total: number; // composite score 44 }; 45 channel: string; // PowerScaling | Philosophy | LoreDrop | TrainingArc | LegendsLabs 46 mascots: string[]; // ["MIRA", "KAGE", "AKASHI"] trinity in assigned order 47 status: "accept" | "defer" | "reject"; 48 legal_flags: string[]; // detected copyrighted refs (empty if clean) 49 timestamp: string; // ISO 8601 50 } 51 ``` 52 53 Where the output goes: passed to `concept-forge` as input, logged to `grimoire-keeper`, saved to `signals/` directory if configured. 54 55 ## Core logic / rules 56 57 1. **Source resolution** — Determine input source: if `source=url`, extract topic from Reddit post title or AniList entry; if `source=manual`, use provided `topic` string directly; if `source=ingest`, poll configured monitors (Reddit r/anime, r/OnePiece, r/JujutsuKaisen, AniList trending API) every 30 minutes and queue top 5 new entries. 58 59 2. **Legal firewall (pre-scoring)** — Before scoring, scan `topic_raw` against the copyrighted reference database (character names from Shonen Jump, Studio Ghibli, Trigger, Ufotable, Mappa franchises). If match found: replace with `[redacted character]` or `[redacted series]` in `topic_clean`, log to `legal_flags` array. If `override_legal=true` (manual only), skip this step but still log detected refs. 60 61 3. **4-axis scoring** — Compute weighted scores: 62 - **Engagement (35%)**: Reddit upvotes / 1000, AniList favorites / 10000, manual topics default to 50. 63 - **Brand-fit (30%)**: keyword match against AnimeLegends brand pillars (training arcs, power systems, philosophy, lore depth) — score 0-100 via keyword density. 64 - **Controversy (20%)**: Reddit comment velocity (comments/hour in first 6h), AniList discussion threads — higher = better. Manual topics default to 40. 65 - **Recency (15%)**: exponential decay with 48h half-life. Topics >96h old score <10. 66 - **Weighted total**: `(engagement * 0.35) + (brand_fit * 0.30) + (controversy * 0.20) + (recency * 0.15)`. 67 68 4. **Channel assignment** — Map topic to sub-channel via keyword heuristics: 69 - PowerScaling: "power level", "strongest", "vs", "battle" 70 - Philosophy: "meaning", "theme", "philosophy", "symbolism" 71 - LoreDrop: "explained", "lore", "theory", "timeline" 72 - TrainingArc: "training", "growth", "journey", "development" 73 - LegendsLabs: "animation", "sakuga", "production", "studio" 74 - Default: Philosophy if no strong match. 75 76 5. **Mascot trinity assignment** — Assign mascot order based on channel: 77 - PowerScaling: Akashi leads (closes with power judgment), Kage measures, Mira opens curiosity. 78 - Philosophy: Mira leads (opens with wonder), Kage probes, Akashi synthesizes. 79 - LoreDrop: Kage leads (analytical), Mira contextualizes, Akashi delivers verdict. 80 - TrainingArc: Mira leads (warm journey framing), Akashi challenges, Kage measures progress. 81 - LegendsLabs: Akashi leads (expertise assertion), Kage dissects, Mira humanizes. 82 83 6. **Accept/defer/reject** — Set `status` based on weighted_total: ≥60 = accept, 40-59 = defer (low priority queue), <40 = reject. Deferred topics resurface if engagement spikes within 48h. 84 85 7. **Manifest generation** — Populate `SignalManifest` with all fields, generate UUID for `signal_id`, set `timestamp` to ISO 8601 UTC. 86 87 8. **Grimoire logging** — Log invocation to `grimoire-keeper` with `stage="signal-forge"`, `input_id=null` (first stage), `output_id=signal_id`, `decision=status`, `rationale` (one-line: why accepted/deferred/rejected), `duration_ms`. 88 89 ## Worked examples 90 91 ### Example 1: Reddit trending topic (accepted) 92 93 **Input:** 94 95 ```json 96 { 97 "source": "url", 98 "url": "https://reddit.com/r/anime/comments/xyz/why_gojos_domain_is_philosophically_perfect" 99 } 100 ``` 101 102 **Output:** 103 104 ```json 105 { 106 "signal_id": "550e8400-e29b-41d4-a716-446655440000", 107 "topic_raw": "Why Gojo's Domain is philosophically perfect", 108 "topic_clean": "Why [redacted character]'s Domain is philosophically perfect", 109 "source": "reddit", 110 "source_url": "https://reddit.com/r/anime/comments/xyz/why_gojos_domain_is_philosophically_perfect", 111 "scores": { 112 "engagement": 78, 113 "brand_fit": 92, 114 "controversy": 65, 115 "recency": 95, 116 "weighted_total": 81.65 117 }, 118 "channel": "Philosophy", 119 "mascots": ["MIRA", "KAGE", "AKASHI"], 120 "status": "accept", 121 "legal_flags": ["Gojo (Jujutsu Kaisen)"], 122 "timestamp": "2026-08-16T09:15:00Z" 123 } 124 ``` 125 126 **Why this output:** High brand-fit (philosophy keyword), strong engagement, recent post. Legal firewall stripped "Gojo" (copyrighted Jujutsu Kaisen character). Philosophy channel assigned → Mira leads trinity. 127 128 ### Example 2: Manual topic (deferred) 129 130 **Input:** 131 132 ```json 133 { 134 "source": "manual", 135 "topic": "Best animation studios ranked by sakuga quality" 136 } 137 ``` 138 139 **Output:** 140 141 ```json 142 { 143 "signal_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", 144 "topic_raw": "Best animation studios ranked by sakuga quality", 145 "topic_clean": "Best animation studios ranked by sakuga quality", 146 "source": "manual", 147 "scores": { 148 "engagement": 50, 149 "brand_fit": 70, 150 "controversy": 40, 151 "recency": 50, 152 "weighted_total": 52.5 153 }, 154 "channel": "LegendsLabs", 155 "mascots": ["AKASHI", "KAGE", "MIRA"], 156 "status": "defer", 157 "legal_flags": [], 158 "timestamp": "2026-08-16T09:20:00Z" 159 } 160 ``` 161 162 **Why this output:** Manual topics default to mid-range engagement/controversy/recency. Brand-fit moderate (sakuga/animation match). Weighted total 52.5 → defer status (40-59 range). LegendsLabs channel → Akashi leads. 163 164 ### Example 3: Stale low-engagement topic (rejected) 165 166 **Input:** 167 168 ```json 169 { 170 "source": "url", 171 "url": "https://anilist.co/anime/12345/discussions/old-minor-character-discussion" 172 } 173 ``` 174 175 **Output:** 176 177 ```json 178 { 179 "signal_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", 180 "topic_raw": "Old minor character discussion from 2024", 181 "topic_clean": "Old minor character discussion from 2024", 182 "source": "anilist", 183 "source_url": "https://anilist.co/anime/12345/discussions/old-minor-character-discussion", 184 "scores": { 185 "engagement": 15, 186 "brand_fit": 25, 187 "controversy": 10, 188 "recency": 5, 189 "weighted_total": 14.75 190 }, 191 "channel": "Philosophy", 192 "mascots": ["MIRA", "KAGE", "AKASHI"], 193 "status": "reject", 194 "legal_flags": [], 195 "timestamp": "2026-08-16T09:25:00Z" 196 } 197 ``` 198 199 **Why this output:** Topic is >96h old (recency score 5), low engagement (15), weak brand-fit. Weighted total 14.75 < 40 → reject. Not queued for downstream processing. 200 201 ## Failure modes 202 203 - **No configured ingest sources** — If `source=ingest` but Reddit API keys or AniList access is not configured, log error to Grimoire with `status="error"`, return empty manifest, and notify user that manual topic input is required. 204 - **URL fetch timeout** — If Reddit/AniList URL fetch times out (>10s), retry once after 2s delay. If second attempt fails, log error, set `status="defer"`, and queue for retry in 30 minutes. 205 - **Legal firewall too aggressive** — If topic is reduced to <5 words after stripping copyrighted refs (e.g., "Why [redacted] is [redacted]"), set `status="reject"`, log to Grimoire with `rationale="topic_too_vague_after_legal_pass"`, do not proceed downstream. 206 - **All scores zero** — If engagement, brand-fit, controversy, recency all compute to 0 (malformed input), set `status="reject"`, log `rationale="insufficient_signal_data"`. 207 - **Missing topic** — If `source=manual` but `topic` field is empty or null, return error: `"Manual source requires non-empty topic string"`. 208 209 ## Grimoire logging contract 210 211 Every invocation of this skill logs via `grimoire-keeper`. Fields logged: 212 213 - `stage`: `"signal-forge"` 214 - `input_id`: `null` (first stage, no upstream manifest) 215 - `output_id`: `signal_id` from generated `SignalManifest` 216 - `decision`: `"accept"` | `"defer"` | `"reject"` | `"error"` 217 - `rationale`: one-line explanation (e.g., `"high_engagement_philosophy_topic"`, `"stale_low_engagement"`, `"legal_firewall_blocked"`) 218 - `cost_usd`: `0.00` (no paid API calls at this stage) 219 - `duration_ms`: elapsed time from input receipt to manifest generation 220 - `legal_flags`: array of detected copyrighted references (empty if none) 221 222 ## Legal firewall 223 224 This skill enforces strict copyright filtering on all external content. 225 226 ### Copyrighted reference database 227 228 Maintained in `brand/never-say.md` (not in this repo — see AnimeLegends studio monorepo). Database includes: 229 230 - Character names from Shonen Jump franchises (Naruto, One Piece, Bleach, Jujutsu Kaisen, My Hero Academia, Dragon Ball, etc.) 231 - Studio Ghibli, Trigger, Ufotable, Mappa character and series names 232 - Franchise-specific terminology (e.g., "Sharingan", "Hollow", "Quirk", "Stand", "Bankai") 233 234 ### Replacement behavior 235 236 - Character name → `[redacted character]` 237 - Series name → `[redacted series]` 238 - Franchise term → `[generic equivalent]` (e.g., "Sharingan" → "special eye technique") 239 240 ### Override 241 242 Manual topics can set `override_legal=true` to bypass substitution (e.g., for fair-use commentary), but detected refs are still logged to `legal_flags` array for audit trail. 243 244 ### AnimeLegends original IP 245 246 The following are AnimeLegends original characters and are NEVER filtered: 247 248 - **AKASHI** — wisdom keeper, deep reverb voice 249 - **KAGE** — shadow analyst, metallic clarity 250 - **MIRA** — wonder guide, warm curious tone 251 252 ## Quality gates 253 254 - [ ] Output `SignalManifest` has all required fields (signal_id, topic_raw, topic_clean, source, scores, channel, mascots, status, legal_flags, timestamp) 255 - [ ] `signal_id` is valid UUID v4 256 - [ ] `topic_clean` is non-empty and ≥5 words after legal pass 257 - [ ] `scores.weighted_total` is correctly computed: `(engagement * 0.35) + (brand_fit * 0.30) + (controversy * 0.20) + (recency * 0.15)` 258 - [ ] `status` matches weighted_total thresholds: ≥60 accept, 40-59 defer, <40 reject 259 - [ ] `channel` is one of: PowerScaling, Philosophy, LoreDrop, TrainingArc, LegendsLabs 260 - [ ] `mascots` array has exactly 3 elements from {MIRA, KAGE, AKASHI} 261 - [ ] `legal_flags` array populated if copyrighted refs detected 262 - [ ] Grimoire log entry created with all required fields 263 - [ ] No copyrighted character names in `topic_clean` unless `override_legal=true` 264 265 ## Changelog 266 267 ### 0.1.0 — 2026-08-16 268 269 - Initial release 270 - 4-axis scoring rubric (engagement 35%, brand-fit 30%, controversy 20%, recency 15%) 271 - Legal firewall with copyrighted reference stripping 272 - Channel and mascot assignment logic 273 - Accept/defer/reject status based on weighted score thresholds 274 - Grimoire logging integration