Validates and persists signal files to the yahoo-mlb signals directory. Every MLB skill calls this skill before writing a signal. Enforces the signal-framework.md schema -- required YAML frontmatter fields (type, date, emitted_by, confidence, source_urls), range-checks numeric signals (0-100 unipolar, -100 to +100 bipolar), verifies variant_synthesis metadata, and enforces file naming. On validation failure, does not persist and routes a failure entry to mlb-decision-logger. Use when an agent or skill needs to emit a signal, validate a signal file, write to signals/YYYY-MM-DD-<type>.md, or check signal frontmatter. Triggers — "emit signal", "validate signal", "write signal file", "signal frontmatter".
Action: Write to yahoo-mlb/signals/2026-04-17-player-caminero.md and return the absolute path.
Failure scenario: If confidence: 1.4 had been passed, validation fails. The skill does NOT write the file. It calls mlb-decision-logger with a failure entry: kind: signal_validation_failure, signal_type: player, reason: confidence out of range (1.4 not in [0.0, 1.0]), emitter: mlb-player-analyzer, and returns an error to the calling agent.
The caller hands in three things: (1) YAML frontmatter key-value pairs, (2) signal body (markdown tables), (3) intent (e.g., "this is a final synthesized signal" vs. "this is an intermediate variant dump"). See resources/template.md for the canonical input shape.
Frontmatter fields collected
Body (markdown tables) supplied
Intent known: final vs. variant-intermediate
Step 2: Validate YAML frontmatter
Confirm all required keys are present and well-typed. See resources/methodology.md for the full list.
type present and in the allowed enum (lineup, waivers, streaming, trade, category-plan, playoff-push, player, matchup, regression, two-start, closer, faab, cat-state)
date present and formatted YYYY-MM-DD
emitted_by present and references a known skill or agent
confidence present as a float in [0.0, 1.0]
source_urls present as a non-empty list of URLs
Step 3: Range-check numeric signals
Every numeric signal in the body must fall inside its declared range. See resources/methodology.md for the per-signal range table (it mirrors signal-framework.md).
Bipolar signals (regression_index, positional_flex_delta) in [-100, +100]
Integer signals (playoff_games) >= 0
Dollar signals (acquisition_value, faab_max_bid, faab_rec_bid) >= 0
Enum signals (cat_position, verdict) inside their declared allowed sets
Step 4: Validate variant synthesis metadata
If this is a synthesized final signal, it must declare which variants produced it.
If variant_synthesis: true, variants_fired is a list with >= 1 entry
If variant_synthesis: true, synthesis_confidence is present and in [0.0, 1.0]
If variant_synthesis: false, the file is an intermediate variant dump; filename must include the variant suffix (see Step 5)
red_team_findings (if present) is a list of objects with severity, likelihood, score, note fields
Step 5: Determine and validate file path
The canonical path is yahoo-mlb/signals/YYYY-MM-DD-<type>.md. For an intermediate variant dump, use YYYY-MM-DD-<type>-<variant>.md. For per-player or per-game files, an optional identifier suffix is allowed: YYYY-MM-DD-<type>-<identifier>.md.
Compute path from date and type in frontmatter
Check that a signal of this type+date does not already exist unless the caller explicitly passed overwrite: true
Ensure the parent directory exists (create if missing)
Reject paths that escape the signals/ directory
Step 6: Write file OR log validation failure
If all checks pass: write the file, return the absolute path. If any check fails: do NOT write, call mlb-decision-logger with a structured failure entry, return an error object to the caller. See resources/methodology.md for the failure log schema.
On pass: write file, return absolute path
On fail: build failure object (reason, field, expected, actual), send to mlb-decision-logger, return error
Required numeric signals in body: daily_quality, plus the three components (form_score, matchup_score, opportunity_score)
Always a final synthesized signal when emitted by mlb-player-analyzer -- so variant_synthesis: true and variants_fired: [advocate, critic]
Source URLs must include Baseball Savant, FanGraphs, and MLB.com (confirmed lineup)
Pattern 2: Daily lineup roll-up (type: lineup)
Filename: YYYY-MM-DD-lineup.md
Body references, by name, the per-player signal files it consumed (provenance chain)
synthesis_confidence reflects agreement between the advocate (bat-everyone) and critic (sit-risky) variants
Red-team findings typically flag weather, role uncertainty, or fragile platoon calls
Pattern 3: Intermediate variant dump (variant suffix in filename)
Filename: YYYY-MM-DD-<type>-advocate.md or YYYY-MM-DD-<type>-critic.md
variant_synthesis: false (this IS a variant, not a synthesis)
emitted_by names the agent and variant (e.g., mlb-lineup-optimizer/advocate)
The synthesizing agent reads these two intermediate files, produces the final synthesized signal, then emits with variant_synthesis: true
Pattern 4: Low-confidence graceful degrade
When a web search fails, the upstream skill should still emit a signal but with confidence <= 0.3 and a red_team_findings entry flagging the missing data source
This skill does NOT reject low-confidence signals -- low confidence is legitimate. It only rejects out-of-range or missing fields.
Flag in body: "Could not verify opposing pitcher; using prior-start proxy."
Guardrails
Never silently drop a signal. If validation fails, the failure must be logged via mlb-decision-logger so the calibration review can see what was rejected and why. A signal that never gets written AND never gets logged is invisible to the team.
Do not re-derive signal values. This skill is a validator and file-writer only. It never computes daily_quality or any other signal itself. If an upstream skill passes in a half-computed signal, reject it rather than filling in the blanks.
Reject unknown type values. The enum in signal-framework.md is the authoritative list. If a caller passes type: vibe-check, reject and log. Adding a new signal type requires updating signal-framework.md first, then this skill's validator.
Range checks are hard limits. A form_score of 105 is not "close enough" -- it indicates a bug upstream (probably forgot to normalize). Reject and log. Do NOT clamp-and-accept.
confidence is required, not optional. Even a perfectly-computed signal with three source URLs must carry a confidence float. A missing confidence is a validator failure, not a warning.
source_urls must be a non-empty list. Per CLAUDE.md rule 1 ("Web-search everything"), every factual signal is backed by a live source. An empty source_urls list means the signal was not grounded -- reject and log.
Variant synthesis claims must be provable. If variant_synthesis: true but variants_fired is empty or missing, that is a lie about the team's process. Reject and log.
Do not overwrite without explicit consent. If a signal already exists at the target path, refuse to overwrite unless the caller passes overwrite: true. This prevents losing an earlier morning's signal when a mid-day re-run happens.
Quick Reference
Required frontmatter fields (always):
type (enum)
date (YYYY-MM-DD)
emitted_by (string)
confidence (float 0.0-1.0)
source_urls (non-empty list)
Required when variant_synthesis: true:
variants_fired (list, >= 1)
synthesis_confidence (float 0.0-1.0)
File path conventions:
Final synthesized: signals/YYYY-MM-DD-<type>.md
With identifier: signals/YYYY-MM-DD-<type>-<id>.md
resources/evaluators/rubric_mlb_signal_emitter.json: 8 criteria for evaluating the emitter's behavior
Inputs required:
Frontmatter key-value pairs from caller
Signal body (markdown tables)
overwrite flag (default false)
Outputs produced:
On success: absolute file path of the written signal
On failure: error object; a failure entry appended to tracker/decisions-log.md via mlb-decision-logger
1---2name: mlb-signal-emitter3description: Validates and persists signal files to the yahoo-mlb signals directory. Every MLB skill calls this skill before writing a signal. Enforces the signal-framework.md schema -- required YAML frontmatter fields (type, date, emitted_by, confidence, source_urls), range-checks numeric signals (0-100 unipolar, -100 to +100 bipolar), verifies variant_synthesis metadata, and enforces file naming. On validation failure, does not persist and routes a failure entry to mlb-decision-logger. Use when an agent or skill needs to emit a signal, validate a signal file, write to signals/YYYY-MM-DD-<type>.md, or check signal frontmatter. Triggers — "emit signal", "validate signal", "write signal file", "signal frontmatter".4---5# MLB Signal Emitter
67## Table of Contents
8- [Example](#example)
9- [Workflow](#workflow)
10- [Common Patterns](#common-patterns)
11- [Guardrails](#guardrails)
12- [Quick Reference](#quick-reference)
1314## Example
1516**Scenario**: `mlb-player-analyzer` has computed a `daily_quality` signal for Junior Caminero on 2026-04-17 and wants to persist it.
1718**Inputs passed to this skill**:
19- `type: player`
20- `date: 2026-04-17`
21- `emitted_by: mlb-player-analyzer`
22- `variant_synthesis: true`, `variants_fired: [advocate, critic]`
23- Body contains: `form_score: 68`, `matchup_score: 74`, `opportunity_score: 62`, `daily_quality: 69`, `regression_index: +18`, `confidence: 0.78`
24- `source_urls: [baseballsavant..., fangraphs..., mlb.com/gameday...]`
2526**Validation pass** (what this skill checks):
2728| Check | Result |
29|---|---|
30| YAML frontmatter parses | PASS |
31| `type` is in allowed enum | PASS (`player`) |
32| `date` is ISO YYYY-MM-DD | PASS |
33| `emitted_by` present | PASS |
34| `confidence` in [0.0, 1.0] | PASS (0.78) |
35| `source_urls` is non-empty list | PASS (3 URLs) |
36| `variant_synthesis: true` implies `variants_fired` has >= 1 | PASS (2 fired) |
37| All numeric signals in declared range | PASS (all 0-100 signals clamped; regression_index in +-100) |
38| File path matches `signals/YYYY-MM-DD-<type>.md` convention | PASS |
3940**Action**: Write to `yahoo-mlb/signals/2026-04-17-player-caminero.md` and return the absolute path.
4142**Failure scenario**: If `confidence: 1.4` had been passed, validation fails. The skill does NOT write the file. It calls `mlb-decision-logger` with a failure entry: `kind: signal_validation_failure`, `signal_type: player`, `reason: confidence out of range (1.4 not in [0.0, 1.0])`, `emitter: mlb-player-analyzer`, and returns an error to the calling agent.
4344## Workflow
4546Copy this checklist and track progress:
4748```
49Signal Emission Progress:
50- [ ] Step 1: Receive signal payload from upstream skill/agent
51- [ ] Step 2: Validate YAML frontmatter (required fields)
52- [ ] Step 3: Range-check all numeric signals
53- [ ] Step 4: Validate variant synthesis metadata
54- [ ] Step 5: Determine and validate file path
55- [ ] Step 6: Write file OR log validation failure
56```
5758**Step 1: Receive signal payload**
5960The caller hands in three things: (1) YAML frontmatter key-value pairs, (2) signal body (markdown tables), (3) intent (e.g., "this is a final synthesized signal" vs. "this is an intermediate variant dump"). See [resources/template.md](resources/template.md) for the canonical input shape.
6162- [ ] Frontmatter fields collected
63- [ ] Body (markdown tables) supplied
64- [ ] Intent known: final vs. variant-intermediate
6566**Step 2: Validate YAML frontmatter**
6768Confirm all required keys are present and well-typed. See [resources/methodology.md](resources/methodology.md#required-frontmatter-fields) for the full list.
6970- [ ] `type` present and in the allowed enum (lineup, waivers, streaming, trade, category-plan, playoff-push, player, matchup, regression, two-start, closer, faab, cat-state)
71- [ ] `date` present and formatted `YYYY-MM-DD`
72- [ ] `emitted_by` present and references a known skill or agent
73- [ ] `confidence` present as a float in [0.0, 1.0]
74- [ ] `source_urls` present as a non-empty list of URLs
7576**Step 3: Range-check numeric signals**
7778Every numeric signal in the body must fall inside its declared range. See [resources/methodology.md](resources/methodology.md#range-check-rules) for the per-signal range table (it mirrors signal-framework.md).
7980- [ ] Unipolar signals (form_score, matchup_score, opportunity_score, daily_quality, qs_probability, streamability_score, role_certainty, cat_pressure, playoff_matchup_quality, etc.) in [0, 100]
81- [ ] Bipolar signals (regression_index, positional_flex_delta) in [-100, +100]
82- [ ] Integer signals (playoff_games) >= 0
83- [ ] Dollar signals (acquisition_value, faab_max_bid, faab_rec_bid) >= 0
84- [ ] Enum signals (cat_position, verdict) inside their declared allowed sets
8586**Step 4: Validate variant synthesis metadata**
8788If this is a synthesized final signal, it must declare which variants produced it.
8990- [ ] If `variant_synthesis: true`, `variants_fired` is a list with >= 1 entry
91- [ ] If `variant_synthesis: true`, `synthesis_confidence` is present and in [0.0, 1.0]
92- [ ] If `variant_synthesis: false`, the file is an intermediate variant dump; filename must include the variant suffix (see Step 5)
93- [ ] `red_team_findings` (if present) is a list of objects with `severity`, `likelihood`, `score`, `note` fields
9495**Step 5: Determine and validate file path**
9697The canonical path is `yahoo-mlb/signals/YYYY-MM-DD-<type>.md`. For an intermediate variant dump, use `YYYY-MM-DD-<type>-<variant>.md`. For per-player or per-game files, an optional identifier suffix is allowed: `YYYY-MM-DD-<type>-<identifier>.md`.
9899- [ ] Compute path from `date` and `type` in frontmatter
100- [ ] Check that a signal of this type+date does not already exist unless the caller explicitly passed `overwrite: true`
101- [ ] Ensure the parent directory exists (create if missing)
102- [ ] Reject paths that escape the `signals/` directory
103104**Step 6: Write file OR log validation failure**
105106If all checks pass: write the file, return the absolute path. If any check fails: do NOT write, call `mlb-decision-logger` with a structured failure entry, return an error object to the caller. See [resources/methodology.md](resources/methodology.md#handling-validation-failures) for the failure log schema.
107108- [ ] On pass: write file, return absolute path
109- [ ] On fail: build failure object (reason, field, expected, actual), send to `mlb-decision-logger`, return error
110111## Common Patterns
112113**Pattern 1: Per-player daily signal (`type: player`)**
114- Filename: `YYYY-MM-DD-player-<lastname>.md` (e.g., `2026-04-17-player-caminero.md`)
115- Required numeric signals in body: `daily_quality`, plus the three components (`form_score`, `matchup_score`, `opportunity_score`)
116- Always a final synthesized signal when emitted by `mlb-player-analyzer` -- so `variant_synthesis: true` and `variants_fired: [advocate, critic]`
117- Source URLs must include Baseball Savant, FanGraphs, and MLB.com (confirmed lineup)
118119**Pattern 2: Daily lineup roll-up (`type: lineup`)**
120- Filename: `YYYY-MM-DD-lineup.md`
121- Body references, by name, the per-player signal files it consumed (provenance chain)
122- `synthesis_confidence` reflects agreement between the advocate (bat-everyone) and critic (sit-risky) variants
123- Red-team findings typically flag weather, role uncertainty, or fragile platoon calls
124125**Pattern 3: Intermediate variant dump (variant suffix in filename)**
126- Filename: `YYYY-MM-DD-<type>-advocate.md` or `YYYY-MM-DD-<type>-critic.md`
127- `variant_synthesis: false` (this IS a variant, not a synthesis)
128- `emitted_by` names the agent and variant (e.g., `mlb-lineup-optimizer/advocate`)
129- The synthesizing agent reads these two intermediate files, produces the final synthesized signal, then emits with `variant_synthesis: true`
130131**Pattern 4: Low-confidence graceful degrade**
132- When a web search fails, the upstream skill should still emit a signal but with `confidence <= 0.3` and a `red_team_findings` entry flagging the missing data source
133- This skill does NOT reject low-confidence signals -- low confidence is legitimate. It only rejects out-of-range or missing fields.
134- Flag in body: "Could not verify opposing pitcher; using prior-start proxy."
135136## Guardrails
1371381. **Never silently drop a signal.** If validation fails, the failure must be logged via `mlb-decision-logger` so the calibration review can see what was rejected and why. A signal that never gets written AND never gets logged is invisible to the team.
1391402. **Do not re-derive signal values.** This skill is a validator and file-writer only. It never computes `daily_quality` or any other signal itself. If an upstream skill passes in a half-computed signal, reject it rather than filling in the blanks.
1411423. **Reject unknown `type` values.** The enum in signal-framework.md is the authoritative list. If a caller passes `type: vibe-check`, reject and log. Adding a new signal type requires updating signal-framework.md first, then this skill's validator.
1431444. **Range checks are hard limits.** A `form_score` of 105 is not "close enough" -- it indicates a bug upstream (probably forgot to normalize). Reject and log. Do NOT clamp-and-accept.
1451465. **`confidence` is required, not optional.** Even a perfectly-computed signal with three source URLs must carry a confidence float. A missing confidence is a validator failure, not a warning.
1471486. **`source_urls` must be a non-empty list.** Per CLAUDE.md rule 1 ("Web-search everything"), every factual signal is backed by a live source. An empty `source_urls` list means the signal was not grounded -- reject and log.
1491507. **Variant synthesis claims must be provable.** If `variant_synthesis: true` but `variants_fired` is empty or missing, that is a lie about the team's process. Reject and log.
1511528. **Do not overwrite without explicit consent.** If a signal already exists at the target path, refuse to overwrite unless the caller passes `overwrite: true`. This prevents losing an earlier morning's signal when a mid-day re-run happens.
153154## Quick Reference
155156**Required frontmatter fields (always):**
157- `type` (enum)
158- `date` (YYYY-MM-DD)
159- `emitted_by` (string)
160- `confidence` (float 0.0-1.0)
161- `source_urls` (non-empty list)
162163**Required when `variant_synthesis: true`:**
164- `variants_fired` (list, >= 1)
165- `synthesis_confidence` (float 0.0-1.0)
166167**File path conventions:**
168- Final synthesized: `signals/YYYY-MM-DD-<type>.md`
169- With identifier: `signals/YYYY-MM-DD-<type>-<id>.md`
170- Intermediate variant: `signals/YYYY-MM-DD-<type>-<variant>.md`
171172**Signal ranges (see [resources/methodology.md](resources/methodology.md#range-check-rules) for the full table):**
173- Unipolar (0-100): form_score, matchup_score, opportunity_score, daily_quality, qs_probability, k_ceiling, era_whip_risk, streamability_score, role_certainty, save_role_certainty, cat_pressure, cat_reachability, cat_punt_score, positional_need_fit, opp_sp_quality, park_hitter_factor, park_pitcher_factor, weather_risk, bullpen_state, playoff_matchup_quality, holding_value, obp_contribution, sb_opportunity
174- Bipolar (-100 to +100): regression_index, positional_flex_delta
175- Dollar (>= 0): acquisition_value, faab_max_bid, faab_rec_bid, trade_value_delta
176- Integer (>= 0): playoff_games
177- Enum: cat_position (winning|tied|losing), verdict (accept|counter|reject)
178179**On validation failure:**
1801. Do NOT write the signal file.
1812. Build failure entry: `{kind: signal_validation_failure, signal_type, reason, field, expected, actual, emitter, timestamp}`.
1823. Call `mlb-decision-logger` with the failure entry.
1834. Return an error object to the caller.
184185**Key resources:**
186- **[resources/template.md](resources/template.md)**: Canonical signal file template with every required frontmatter field and a fully-populated example body
187- **[resources/methodology.md](resources/methodology.md)**: Validation rules -- required fields, range checks, variant-synthesis checks, path conventions, failure handling
188- **[resources/evaluators/rubric_mlb_signal_emitter.json](resources/evaluators/rubric_mlb_signal_emitter.json)**: 8 criteria for evaluating the emitter's behavior
189190**Inputs required:**
191- Frontmatter key-value pairs from caller
192- Signal body (markdown tables)
193- `overwrite` flag (default false)
194195**Outputs produced:**
196- On success: absolute file path of the written signal
197- On failure: error object; a failure entry appended to `tracker/decisions-log.md` via `mlb-decision-logger`
Run npx skillmds add lyndonkl/mlb-signal-emitter in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Validates and persists signal files to the yahoo-mlb signals directory. Every MLB skill calls this skill before writing a signal. Enforces the signal-framework.md schema -- required YAML frontmatter fields (type, date, emitted_by, confidence, source_urls), range-checks numeric signals (0-100 unipolar, -100 to +100 bipolar), verifies variant_synthesis metadata, and enforces file naming. On validation failure, does not persist and routes a failure entry to mlb-decision-logger. Use when an agent or skill needs to emit a signal, validate a signal file, write to signals/YYYY-MM-DD-<type>.md, or check signal frontmatter. Triggers — "emit signal", "validate signal", "write signal file", "signal frontmatter". It is listed under AI & ML on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: docs only. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
lyndonkl (@lyndonkl) published this skill. Their other Agent Skills are listed on their SkillMD profile.