Edge Signal Aggregator
Aggregate and rank signals from multiple edge-finding skills (edge-candidate-agent, theme-detector, sector-analyst, institutional-flow-tracker) into a prioritized conviction dashboard with weighted scoring, deduplication, and contradiction detection.
No API
Download Skill Package (.skill) View Source on GitHub
Table of Contents
1. Overview
Combine outputs from multiple upstream edge-finding skills into a single weighted conviction dashboard. This skill applies configurable signal weights, deduplicates overlapping themes, flags contradictions between skills, and ranks composite edge ideas by aggregate confidence score. The result is a prioritized edge shortlist with provenance links to each contributing skill.
2. When to Use
- After running multiple edge-finding skills and wanting a unified view
- When consolidating signals from edge-candidate-agent, theme-detector, sector-analyst, and institutional-flow-tracker
- Before making portfolio allocation decisions based on multiple signal sources
- To identify contradictions between different analysis approaches
- When prioritizing which edge ideas deserve deeper research
3. Prerequisites
- Python 3.9+
- No API keys required (processes local JSON/YAML files from other skills)
- Dependencies:
pyyaml(standard in most environments)
4. Quick Start
python3 skills/edge-signal-aggregator/scripts/aggregate_signals.py \
--edge-candidates reports/edge_candidate_agent_*.json \
--edge-concepts reports/edge_concepts_*.yaml \
--themes reports/theme_detector_*.json \
--sectors reports/sector_analyst_*.json \
--institutional reports/institutional_flow_*.json \
--hints reports/edge_hints_*.yaml \
--output-dir reports/
5. Workflow
Step 1: Gather Upstream Skill Outputs
Collect output files from the upstream skills you want to aggregate:
reports/edge_candidate_*.jsonfrom edge-candidate-agentreports/edge_concepts_*.yamlfrom edge-concept-synthesizerreports/theme_detector_*.jsonfrom theme-detectorreports/sector_analyst_*.jsonfrom sector-analystreports/institutional_flow_*.jsonfrom institutional-flow-trackerreports/edge_hints_*.yamlfrom edge-hint-extractor
Step 2: Run Signal Aggregation
Execute the aggregator script with paths to upstream outputs:
python3 skills/edge-signal-aggregator/scripts/aggregate_signals.py \
--edge-candidates reports/edge_candidate_agent_*.json \
--edge-concepts reports/edge_concepts_*.yaml \
--themes reports/theme_detector_*.json \
--sectors reports/sector_analyst_*.json \
--institutional reports/institutional_flow_*.json \
--hints reports/edge_hints_*.yaml \
--output-dir reports/
Optional: Use a custom weights configuration:
python3 skills/edge-signal-aggregator/scripts/aggregate_signals.py \
--edge-candidates reports/edge_candidate_agent_*.json \
--weights-config skills/edge-signal-aggregator/assets/custom_weights.yaml \
--output-dir reports/
Step 3: Review Aggregated Dashboard
Open the generated report to review:
- Ranked Edge Ideas - Sorted by composite conviction score
- Signal Provenance - Which skills contributed to each idea (with
evidence_idper contributor) - Contradictions - Conflicting signals flagged for manual review
- Deduplication Log - Merged overlapping themes (verbatim re-ingested duplicates get no bonus)
- Invalid Signals - Scores that are NaN/infinite, negative, or out of declared range are dropped and reported, never converted into confidence
Step 4: Act on High-Conviction Signals
Filter the shortlist by minimum conviction threshold:
python3 skills/edge-signal-aggregator/scripts/aggregate_signals.py \
--edge-candidates reports/edge_candidate_agent_*.json \
--min-conviction 0.7 \
--output-dir reports/
6. Resources
References:
skills/edge-signal-aggregator/references/signal-weighting-framework.md
Scripts:
skills/edge-signal-aggregator/scripts/aggregate_signals.py
7. Producer Contract and Scoring Rules (schema 1.1)
Since schema 1.1, aggregation is idempotent and strict about score validity (Issue #510):
evidence_id(optional, per item): stable evidence identity. Re-ingesting the same evidence (same skill +evidence_id) never adds a bonus. Without it a deterministic fallback is derived from skill, signal reference, title, tickers, and direction (timestamps excluded, so refreshed timestamps cannot forge a new identity). When copies differ, the newest observation wins: the latest parsed timezone-aware timestamp (date-only and naive values read as UTC) supplies the retained score. Equal, missing, or unparsable timestamps keep the highest raw score, then a stable key, so ingestion order cannot change the result. Only ISO-8601 strings (orYYYY-MM-DD) are ordered; epoch numbers and compact forms such as20261010count as missing timestamps. A newer, lower score replaces an older, higher one, and discarded copies are listed indeduplication_log[].discarded_copies.score_scale(optional, per item or per document:"0-1"/"0-100"): declared scales are enforced strictly. NaN/infinity, negative, and out-of-range values are rejected intoinvalid_signals; a present-but-unparsable declaration ("","foo") is rejected asmissing_scale. When the key is absent, values in (1, 100] are assumed 0-100 and flagged (score_scale_assumed: true+scale_assumptions_reportwith the originalvalueand thenormalized_value); values > 100 are rejected.- Agreement rule: bonuses fire on
agreement_tier = min(distinct evidence ids, distinct event fingerprints, distinct skills). Verbatim cross-skill restatements (identical normalized title + tickers) count once and cannot self-confirm; re-ingested duplicates earn nothing. Known limitation: event fingerprints are vocabulary-based, so paraphrased cross-skill restatements with disjoint word sets still earn the agreement bonus. merge_bonus_per_duplicate(in custom weights YAML) is deprecated and ignored.