Production unit-test evidence inventory — 2026-10-14
Preparation for Issue #496.
Assessed source revision: 34af7f8226647c722899a5837eff7e887cf7fbe6 (origin/main at discovery).
Inventory captured 2026-10-14 UTC. This is a historical snapshot; later changes require a fresh inventory.
Result and limits
All 62 production skills are inventoried below: 59 have non-test Python helper candidates,
and three have none. The index declares unit_tests: not_verified for the 59 and
not_applicable for the three. This inventory changes no verification declarations.
This is a file and policy inventory, not a completed semantic test audit. It does not
satisfy any acceptance criterion of #496, prove missing coverage, or establish passed.
The confirmed evidence gap is the conservative shared baseline rationale: no retained,
helper-by-helper happy/boundary/error-path, fail-closed, and schema-conformance audit.
Whether existing tests already meet those requirements is NOT_ASSESSED here.
Tests were not executed to produce this table. File counts cannot establish test quality.
Security review and instruction-contract review are also NOT_ASSESSED.
Discovery and triage rules
- Read the index, policy, file modes, and file contents from the exact source revision using
git show/git ls-tree; untracked files, local caches, and the working tree cannot alter the snapshot. - Include every
status: productionID exactly once, sorted by ID. Scope is each skill’sscripts/tree. Files outside that tree are not assessed as helper candidates. - Count non-test
.pyfiles as helper candidates, including generated clients and library modules. This does not assert that each file is a CLI entry point. - Test modules are
.pyfiles in anytests/directory or namedtest_*/*_test.py.__init__.pyandconftest.pyare counted separately as support files, including those outside tests. Support files may contain executable imports or fixtures and need review too. - Other files include test fixtures and data. None has a tracked executable bit or shebang; discovery aborts if such a non-Python candidate is found, requiring manual classification. Consequently the three skills with no Python helpers have no detected non-Python script executable either. This does not audit executable snippets in SKILL.md.
- Read coverage waivers from
config/ci-test-policy.yamlat the assessed revision. Missing or malformed policy fails discovery. “No skill waiver” means no per-skill waiver entry; it is not a measured coverage result. Waiver presence does not itself block an axis pass, nor does meeting a coverage floor prove the axis criteria.
The table lists helper paths relative to skills/<id>/scripts/. Test/support counts refer
to that same tree; the reproduction command enumerates their exact membership. All 59
helper-bearing rows have the same outstanding semantic review task: map every helper and
relevant support module to happy, boundary, and error fixtures, demonstrate applicable
fail-closed behavior and schema conformance, then run and record the exact test command,
exit status, revision and date. For outputs without a schema requirement, record why it
is inapplicable rather than inventing schema evidence.
Prioritize core risk/state skills (drawdown-circuit-breaker, futures-position-sizer,
position-sizer, trader-memory-core) for that review. Then address waiver-bearing skills
with #293. Coordinate FMP client evidence with PR #556: its generated clients differ from
this snapshot, so evidence from this revision must not be carried forward automatically.
Do not infer coverage gaps from helper/test filename mismatches or module-count ratios.
Complete production inventory
| Production skill | Python helpers (relative to scripts/) |
Test modules / support | Other files | Waiver floor / target / expiry |
|---|---|---|---|---|
backtest-expert (not_verified) |
evaluate_backtest.py |
1 / 1 | None | No skill waiver |
breadth-chart-analyst (not_verified) |
detect_breadth_values.pydetect_uptrend_ratio.pyextract_chart_right_edge.pyfetch_breadth_csv.py |
2 / 2 | None | 25 / 70 / 2027-01-31 |
breakout-trade-planner (not_verified) |
_market_calendar.pyorder_builder.pyplan_breakout_trades.pyrisk_calculator.py |
4 / 1 | None | No skill waiver |
canslim-screener (not_verified) |
calculators/earnings_calculator.pycalculators/growth_calculator.pycalculators/institutional_calculator.pycalculators/leadership_calculator.pycalculators/market_calculator.pycalculators/new_highs_calculator.pycalculators/supply_demand_calculator.pycheck_institutional_endpoint.pyfinviz_stock_client.pyfmp_client.pyreport_generator.pyscorer.pyscreen_canslim.py |
5 / 1 | None | 48 / 70 / 2027-01-31 |
contrarian-setup-gate (not_verified) |
gate_logic.pyrun_contrarian_setup_gate.py |
2 / 1 | None | No skill waiver |
cot-contrarian-detector (not_verified) |
cot_index.pyfmp_client.pyscreen_cot_crowding.py |
3 / 0 | None | No skill waiver |
data-quality-checker (not_verified) |
check_data_quality.py |
1 / 1 | None | No skill waiver |
dividend-growth-pullback-screener (not_verified) |
screen_dividend_growth_rsi.py |
2 / 0 | None | 39 / 70 / 2027-01-31 |
downtrend-duration-analyzer (not_verified) |
analyze_downtrends.pygenerate_histogram_html.py |
3 / 1 | None | 46 / 70 / 2027-01-31 |
drawdown-circuit-breaker (not_verified) |
_market_calendar.pycheck_circuit_breaker.py |
2 / 1 | None | No skill waiver |
dual-axis-skill-reviewer (not_verified) |
run_dual_axis_review.py |
1 / 1 | None | No skill waiver |
earnings-calendar (not_verified) |
_fmp_compat.pyfetch_earnings_fmp.pyfmp_client.pygenerate_report.py |
3 / 1 | None | No skill waiver |
earnings-trade-analyzer (not_verified) |
_fmp_compat.py_market_calendar.pyanalyze_earnings_trades.pycalculators/gap_size_calculator.pycalculators/ma200_calculator.pycalculators/ma50_calculator.pycalculators/pre_earnings_trend_calculator.pycalculators/volume_trend_calculator.pyfmp_client.pyreport_generator.pyscorer.py |
5 / 2 | None | No skill waiver |
economic-calendar-fetcher (not_verified) |
fmp_client.pyget_economic_calendar.py |
2 / 0 | None | No skill waiver |
edge-candidate-agent (not_verified) |
auto_detect_candidates.pycandidate_contract.pyexport_candidate.pyvalidate_candidate.py |
4 / 1 | None | 40 / 70 / 2027-01-31 |
edge-concept-synthesizer (not_verified) |
synthesize_edge_concepts.py |
1 / 1 | None | No skill waiver |
edge-hint-extractor (not_verified) |
build_hints.py |
1 / 1 | None | No skill waiver |
edge-pipeline-orchestrator (not_verified) |
orchestrate_edge_pipeline.py |
1 / 1 | None | No skill waiver |
edge-signal-aggregator (not_verified) |
aggregate_signals.py |
1 / 1 | None | No skill waiver |
edge-strategy-designer (not_verified) |
design_strategy_drafts.py |
1 / 1 | None | 47 / 70 / 2027-01-31 |
edge-strategy-reviewer (not_verified) |
review_strategy_drafts.py |
1 / 1 | None | No skill waiver |
exposure-coach (not_verified) |
calculate_exposure.py |
1 / 1 | None | No skill waiver |
finviz-screener (not_verified) |
open_finviz_screener.py |
1 / 1 | None | No skill waiver |
ftd-detector (not_verified) |
fmp_client.pyftd_detector.pypost_ftd_monitor.pyrally_tracker.pyreport_generator.py |
6 / 1 | None | No skill waiver |
futures-position-sizer (not_verified) |
futures_position_sizer.pyfutures_sizing.py |
2 / 1 | None | No skill waiver |
ibd-distribution-day-monitor (not_verified) |
_fmp_compat.pydata_loader.pydistribution_day_tracker.pyexposure_policy.pyfmp_client.pyhistory_utils.pyibd_monitor.pymath_utils.pymodels.pyreport_generator.pyrisk_classifier.py |
10 / 1 | None | 44 / 70 / 2027-01-31 |
institutional-flow-tracker (not_verified) |
analyze_single_stock.pydata_quality.pyfmp_client.pytrack_institution_portfolio.pytrack_institutional_flow.py |
6 / 1 | None | No skill waiver |
kanchi-dividend-review-monitor (not_verified) |
build_review_queue.py |
1 / 1 | None | No skill waiver |
kanchi-dividend-sop (not_verified) |
build_entry_signals.pybuild_sop_plan.pydividend_basis.pyevent_scanner.pypayout_safety.pythresholds.pyverdict.py |
11 / 1 | None | No skill waiver |
kanchi-dividend-us-tax-accounting (not_verified) |
build_tax_planning_sheet.py |
1 / 1 | None | No skill waiver |
macro-regime-detector (not_verified) |
calculators/concentration_calculator.pycalculators/credit_conditions_calculator.pycalculators/equity_bond_calculator.pycalculators/sector_rotation_calculator.pycalculators/size_factor_calculator.pycalculators/utils.pycalculators/yield_curve_calculator.pyfmp_client.pymacro_regime_detector.pyreport_generator.pyscorer.py |
13 / 2 | None | No skill waiver |
market-breadth-analyzer (not_verified) |
calculators/bearish_signal_calculator.pycalculators/cycle_calculator.pycalculators/divergence_calculator.pycalculators/historical_context_calculator.pycalculators/ma_crossover_calculator.pycalculators/trend_level_calculator.pycsv_client.pyhistory_tracker.pymarket_breadth_analyzer.pyreport_generator.pyscorer.py |
10 / 2 | None | No skill waiver |
market-environment-analysis (not_verified) |
_market_calendar.pymarket_utils.py |
2 / 1 | None | No skill waiver |
market-news-analyst (not_applicable) |
None | 1 / 0 | None | No skill waiver |
market-top-detector (not_verified) |
_market_calendar.pybreadth_csv_client.pycalculators/breadth_calculator.pycalculators/defensive_rotation_calculator.pycalculators/distribution_day_calculator.pycalculators/index_technical_calculator.pycalculators/leading_stock_calculator.pycalculators/math_utils.pycalculators/sentiment_calculator.pyfmp_client.pyhistorical_comparator.pymarket_top_detector.pyreport_generator.pyscenario_engine.pyscorer.pyutils.py |
18 / 2 | None | No skill waiver |
news-reaction-failure-analyzer (not_verified) |
analyze_news_reaction.pyreaction_math.py |
2 / 0 | None | No skill waiver |
options-strategy-advisor (not_verified) |
black_scholes.py |
2 / 1 | None | No skill waiver |
pair-trade-screener (not_verified) |
analyze_spread.pyfind_pairs.pystatsmodels_support.py |
2 / 1 | None | 56 / 70 / 2027-01-31 |
parabolic-short-trade-planner (not_verified) |
_fmp_compat.py_market_calendar.pyadapters/alpaca_inventory_adapter.pyadapters/alpaca_market_data_adapter.pyadapters/fixture_market_data_adapter.pyadapters/market_data_adapter.pybar_normalizer.pybroker_short_inventory_adapter.pycalculators/acceleration_calculator.pycalculators/atr_calculator.pycalculators/liquidity_metrics_calculator.pycalculators/ma_extension_calculator.pycalculators/parabolic_score_calculator.pycalculators/range_expansion_calculator.pycheck_live_apis.pyfmp_client.pygenerate_pre_market_plan.pyintraday_evaluators/first_red_evaluator.pyintraday_evaluators/orl_evaluator.pyintraday_evaluators/vwap_fail_evaluator.pyintraday_size_resolver.pyintraday_state_machine.pyintraday_state_store.pyinvalidation_rules.pymanual_reasons.pymarket_clock.pymath_helpers.pymonitor_intraday_trigger.pyparabolic_report_generator.pyparabolic_scorer.pyplan_builders/first_red_plan_builder.pyplan_builders/orl_plan_builder.pyplan_builders/vwap_fail_plan_builder.pyscreen_parabolic.pysize_recipe_builder.pyssr_state_tracker.pystate_caps.pyvwap.py |
34 / 5 | tests/fixtures/dry_run_minimal.jsontests/fixtures/intraday_bars/first_red_clean.jsontests/fixtures/intraday_bars/first_red_invalidated.jsontests/fixtures/intraday_bars/first_red_same_bar_invalidation_wins.jsontests/fixtures/intraday_bars/no_bars_yet.jsontests/fixtures/intraday_bars/orl_clean_break.jsontests/fixtures/intraday_bars/orl_invalidated.jsontests/fixtures/intraday_bars/orl_low_volume_no_fire.jsontests/fixtures/intraday_bars/vwap_full_fsm.jsontests/fixtures/intraday_bars/vwap_invalidated_after_trigger.jsontests/fixtures/phase2_plan_smoke.json |
No skill waiver |
pead-screener (not_verified) |
_fmp_compat.pycalculators/breakout_calculator.pycalculators/liquidity_calculator.pycalculators/risk_reward_calculator.pycalculators/weekly_candle_calculator.pyfmp_client.pyreport_generator.pyscorer.pyscreen_pead.py |
2 / 2 | None | No skill waiver |
portfolio-manager (not_verified) |
check_alpaca_connection.pyreconcile_positions.py |
2 / 1 | None | No skill waiver |
position-sizer (not_verified) |
position_sizer.py |
1 / 1 | None | No skill waiver |
pre-trade-discipline-gate (not_verified) |
check_pre_trade_discipline.py |
1 / 1 | None | No skill waiver |
scenario-analyzer (not_applicable) |
None | 1 / 0 | None | No skill waiver |
sector-analyst (not_verified) |
analyze_sector_rotation.py |
2 / 1 | None | No skill waiver |
signal-postmortem (not_verified) |
postmortem_analyzer.pypostmortem_recorder.py |
3 / 1 | None | No skill waiver |
skill-designer (not_verified) |
build_design_prompt.py |
1 / 1 | None | 47 / 70 / 2027-01-31 |
skill-idea-miner (not_verified) |
mine_session_logs.pyscore_ideas.py |
3 / 2 | None | No skill waiver |
skill-integration-tester (not_verified) |
validate_workflows.py |
1 / 1 | None | No skill waiver |
stanley-druckenmiller-investment (not_verified) |
allocation_engine.pyreport_generator.pyreport_loader.pyscorer.pystrategy_synthesizer.py |
5 / 1 | None | No skill waiver |
strategy-pivot-designer (not_verified) |
detect_stagnation.pygenerate_pivots.py |
4 / 1 | None | No skill waiver |
technical-analyst (not_verified) |
check_weekly_price_action.pyweekly_price_action.py |
3 / 0 | None | No skill waiver |
theme-detector (not_verified) |
_market_calendar.pycalculators/heat_calculator.pycalculators/industry_ranker.pycalculators/lifecycle_calculator.pycalculators/theme_classifier.pycalculators/theme_discoverer.pyconfig_loader.pydefault_theme_config.pyetf_scanner.pyfinviz_performance_client.pyleadership.pyreport_generator.pyrepresentative_stock_selector.pyscorer.pytheme_detector.pytheme_history.pytheme_matcher.pyuptrend_client.py |
19 / 2 | tests/README.mdthemes.yaml |
No skill waiver |
trade-hypothesis-ideator (not_verified) |
pipeline/evidence_extractor.pypipeline/format_output.pypipeline/normalize.pypipeline/ranking.pypipeline/strategy_exporter.pyrun_hypothesis_ideator.py |
6 / 2 | None | No skill waiver |
trader-memory-core (not_verified) |
fmp_price_adapter.pythesis_ingest.pythesis_review.pythesis_store.pytrader_memory_cli.py |
6 / 1 | None | No skill waiver |
trading-skills-navigator (not_verified) |
build_snapshot.pyintent_benchmark.pyrecommend.py |
2 / 1 | None | No skill waiver |
uptrend-analyzer (not_verified) |
calculators/historical_context_calculator.pycalculators/market_breadth_calculator.pycalculators/momentum_calculator.pycalculators/sector_participation_calculator.pycalculators/sector_rotation_calculator.pydata_fetcher.pyreport_generator.pyscorer.pyuptrend_analyzer.py |
11 / 2 | None | No skill waiver |
us-market-bubble-detector (not_verified) |
bubble_scorer.py |
1 / 0 | None | No skill waiver |
us-stock-analysis (not_applicable) |
None | 1 / 0 | None | No skill waiver |
value-dividend-screener (not_verified) |
screen_dividend_stocks.py |
2 / 1 | None | 34 / 70 / 2027-01-31 |
vcp-screener (not_verified) |
_fmp_compat.pycalculators/execution_state.pycalculators/forward_outcome.pycalculators/pattern_classifier.pycalculators/pivot_proximity_calculator.pycalculators/relative_strength_calculator.pycalculators/trend_template_calculator.pycalculators/vcp_pattern_calculator.pycalculators/volume_pattern_calculator.pyfmp_client.pyhistorical_report.pyhistorical_scanner.pyreport_generator.pyscorer.pyscreen_vcp.py |
4 / 2 | None | No skill waiver |
weekly-performance-digest (not_verified) |
generate_weekly_digest.py |
1 / 1 | None | No skill waiver |
Production skills: 62. Totals: {‘helpers’: 267, ‘not_applicable’: 3, ‘not_verified’: 59, ‘other’: 13, ‘support’: 68, ‘tests’: 251, ‘with_helpers’: 59, ‘without_helpers’: 3}.
Reproduce the inventory
Run from a checkout containing the assessed commit, with Python 3.9 and PyYAML installed.
The command is read-only and emits the table and totals above. It pins all inputs to the
assessed revision, even when run from another branch. To inspect exact test/support paths,
inspect the groups lists in the command; the classification is explicit.
python3.9 - <<'PY'
import subprocess
from collections import Counter
from pathlib import Path
import yaml
revision = "34af7f8226647c722899a5837eff7e887cf7fbe6"
def read(path):
return subprocess.check_output(["git", "show", f"{revision}:{path}"])
skills = yaml.safe_load(read("skills-index.yaml"))["skills"]
production = sorted(
(skill for skill in skills if skill["status"] == "production"),
key=lambda skill: skill["id"],
)
waivers = yaml.safe_load(read("config/ci-test-policy.yaml"))["coverage"]["waivers"]
files = subprocess.check_output(["git", "ls-tree", "-r", "-z", revision]).decode().split("\0")
tracked = {}
for entry in filter(None, files):
metadata, path = entry.split("\t", 1)
mode, kind, _ = metadata.split()
if kind == "blob":
tracked[path] = mode
totals = Counter()
print(
"| Production skill | Python helpers (relative to `scripts/`) | Test modules / support | Other files | Waiver floor / target / expiry |"
)
print("|---|---|---|---|---|")
for skill in production:
prefix = f"skills/{skill['id']}/scripts/"
groups = {key: [] for key in ("helpers", "tests", "support", "other")}
for path in sorted(tracked):
if not path.startswith(prefix):
continue
relative = path[len(prefix) :]
item = Path(relative)
is_test = (
"tests" in item.parts
or item.name.startswith("test_")
or item.name.endswith("_test.py")
or item.name == "conftest.py"
)
if item.name in {"__init__.py", "conftest.py"}:
group = "support"
elif item.suffix == ".py":
group = "tests" if is_test else "helpers"
else:
group = "other"
first_line = read(path).split(b"\n", 1)[0]
if tracked[path] == "100755" or first_line.startswith(b"#!"):
raise RuntimeError(f"Review non-Python executable before classifying: {path}")
groups[group].append(relative)
totals.update({key: len(value) for key, value in groups.items()})
totals["with_helpers" if groups["helpers"] else "without_helpers"] += 1
declaration = skill["verification"]["unit_tests"]
totals[declaration] += 1
helper_text = "<br>".join(f"`{path}`" for path in groups["helpers"]) or "None"
other_text = "<br>".join(f"`{path}`" for path in groups["other"]) or "None"
waiver = waivers.get(skill["id"])
waiver_text = (
f"{waiver['floor']} / {waiver['target']} / {waiver['expires_on']}"
if waiver is not None
else "No skill waiver"
)
print(
f"| `{skill['id']}` ({declaration}) | {helper_text} | "
f"{len(groups['tests'])} / {len(groups['support'])} | "
f"{other_text} | {waiver_text} |"
)
print()
print(f"Production skills: {len(production)}. Totals: {dict(sorted(totals.items()))}.")
PY
Follow-up evidence record
For each skill, retain helper/support path, test node IDs, exercised behavior, output schema
(or applicability rationale), command and exit status, reviewed revision, reviewer and date.
Use the production criteria before any passed override;
update the baseline and index together only when every requirement is established.
Issue #496 remains open for the semantic audit, security review, and instruction contracts.