MLB Signal Emitter

SkillFiles & storage

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".

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the MLB Signal Emitter skill

What this skill tells your AI

The instructions your AI receives, as published by lyndonkl/claude in skills/mlb-signal-emitter/SKILL.md and read by ahel’s review.

Table of Contents

  • Example
  • Workflow
  • Common Patterns
  • Guardrails
  • Quick Reference

Example

Scenario: mlb-player-analyzer has computed a daily_quality signal for Junior Caminero on 2026-04-17 and wants to persist it.

Inputs passed to this skill:

  • type: player
  • date: 2026-04-17
  • emitted_by: mlb-player-analyzer
  • variant_synthesis: true, variants_fired: [advocate, critic]
  • Body contains: form_score: 68, matchup_score: 74, opportunity_score: 62, daily_quality: 69, regression_index: +18, confidence: 0.78
  • source_urls: [baseballsavant..., fangraphs..., mlb.com/gameday...]

Validation pass (what this skill checks):

CheckResult
YAML frontmatter parsesPASS
type is in allowed enumPASS (player)
date is ISO YYYY-MM-DDPASS
emitted_by presentPASS
confidence in [0.0, 1.0]PASS (0.78)
source_urls is non-empty listPASS (3 URLs)
variant_synthesis: true implies variants_fired has >= 1PASS (2 fired)
All numeric signals in declared rangePASS (all 0-100 signals clamped; regression_index in +-100)
File path matches signals/YYYY-MM-DD-<type>.md conventionPASS

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.

Workflow

Copy this checklist and track progress:

Signal Emission Progress:
- [ ] Step 1: Receive signal payload from upstream skill/agent
- [ ] Step 2: Validate YAML frontmatter (required fields)
- [ ] Step 3: Range-check all numeric signals
- [ ] Step 4: Validate variant synthesis metadata
- [ ] Step 5: Determine and validate file path
- [ ] Step 6: Write file OR log validation failure

Step 1: Receive signal payload

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).

  • 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]
  • 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

Common Patterns

Pattern 1: Per-player daily signal (type: player)

  • Filename: YYYY-MM-DD-player-<lastname>.md (e.g., 2026-04-17-player-caminero.md)
  • 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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

  8. 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
  • Intermediate variant: signals/YYYY-MM-DD-<type>-<variant>.md

Signal ranges (see resources/methodology.md for the full table):

  • 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
  • Bipolar (-100 to +100): regression_index, positional_flex_delta
  • Dollar (>= 0): acquisition_value, faab_max_bid, faab_rec_bid, trade_value_delta
  • Integer (>= 0): playoff_games
  • Enum: cat_position (winning|tied|losing), verdict (accept|counter|reject)

On validation failure:

  1. Do NOT write the signal file.
  2. Build failure entry: {kind: signal_validation_failure, signal_type, reason, field, expected, actual, emitter, timestamp}.
  3. Call mlb-decision-logger with the failure entry.
  4. Return an error object to the caller.

Key resources:

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

Signals

GitHub stars
159
Forks
23
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
mlb-signal-emitter
Source
github.com/lyndonkl/claude