diff --git a/.github/workflows/monthly_publish.yml b/.github/workflows/monthly_publish.yml index bf1109e..3374ecf 100644 --- a/.github/workflows/monthly_publish.yml +++ b/.github/workflows/monthly_publish.yml @@ -24,7 +24,7 @@ jobs: PRODUCTION_PROFILE: binance_only_core_major_monthly DOWNLOAD_TOP_LIQUID: ${{ vars.DOWNLOAD_TOP_LIQUID || '90' }} FIRESTORE_COLLECTION: ${{ vars.FIRESTORE_COLLECTION || 'strategy' }} - FIRESTORE_DOCUMENT: ${{ vars.FIRESTORE_DOCUMENT || 'CRYPTO_LEADER_ROTATION_LIVE_POOL' }} + FIRESTORE_DOCUMENT: ${{ vars.FIRESTORE_DOCUMENT || 'CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL' }} GCP_PROJECT_ID: ${{ vars.GCP_PROJECT_ID }} GCS_BUCKET: ${{ vars.GCS_BUCKET }} FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" @@ -121,7 +121,7 @@ jobs: "Authorization": f"Bearer {token}", "Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28", - "User-Agent": "crypto-leader-rotation-monthly-publish", + "User-Agent": "crypto-live-pool-pipelines-monthly-publish", } api_base = f"https://api.github.com/repos/{repository}" label_name = "monthly-review" @@ -235,7 +235,7 @@ jobs: "Accept": "application/vnd.github+json", "Content-Type": "application/json", "X-GitHub-Api-Version": "2022-11-28", - "User-Agent": "crypto-leader-rotation-monthly-publish", + "User-Agent": "crypto-live-pool-pipelines-monthly-publish", }, ) with urllib.request.urlopen(request) as response: diff --git a/config/default.yaml b/config/default.yaml index c5652c4..ecf6368 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -1,5 +1,5 @@ project: - name: "crypto-leader-rotation" + name: "crypto-live-pool-pipelines" timezone: "UTC" release: @@ -269,10 +269,10 @@ publish: mode: "core_major" gcp_project_id: null gcs_bucket: null - gcs_root_prefix: "crypto-leader-rotation" + gcs_root_prefix: "crypto-live-pool-pipelines" firestore_collection: "strategy" - firestore_document: "CRYPTO_LEADER_ROTATION_LIVE_POOL" - source_project: "crypto-leader-rotation" + firestore_document: "CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL" + source_project: "crypto-live-pool-pipelines" upload_current_pointer: true external_data: diff --git a/docs/integration_contract.md b/docs/integration_contract.md index d46ec2e..dbf06e4 100644 --- a/docs/integration_contract.md +++ b/docs/integration_contract.md @@ -9,7 +9,7 @@ - 风险提示:涉及实盘、密钥、权限、Cloud Run、交易所或券商 API 的变更,必须先在测试环境或 dry-run 验证;不要只凭示例直接修改生产。 - 英文正文保留更完整的命令、字段名和配置键;如果摘要和正文不一致,以正文中的实际命令和配置为准。 This document defines the production contract exposed by `CryptoLivePoolPipelines` to downstream strategy systems. -The current v1 artifact namespace remains `crypto-leader-rotation` for compatibility with existing published objects and downstream readers. +The current v1 artifact namespace is `crypto-live-pool-pipelines`. The upstream project publishes a monthly `core_major` live pool and exposes it through: @@ -19,7 +19,7 @@ The upstream project publishes a monthly `core_major` live pool and exposes it t ## Authority Boundary -`CryptoLivePoolPipelines` owns monthly live-pool membership, ranking, and order for `crypto_leader_rotation`. Downstream strategy and execution repositories should treat the ordered `symbols` list from `live_pool.json` or `artifact_manifest.json` as canonical. +`CryptoLivePoolPipelines` owns monthly live-pool membership, ranking, and order for `crypto_live_pool_rotation`. Downstream strategy and execution repositories should treat the ordered `symbols` list from `live_pool.json` or `artifact_manifest.json` as canonical. Downstream systems may apply runtime execution gates, sell rules, top-N selection, sizing, and degraded-source policy after artifact validation. They should not recalculate monthly membership or replace the published order from local indicators. `latest_ranking.csv` and `selection_meta` are upstream evidence and diagnostics; `live_pool.json` plus `artifact_manifest.json` are the stable execution contract. @@ -34,10 +34,10 @@ binding to `CryptoLivePoolPipelines` internals. Required stable fields: - `manifest_type = strategy_artifact` -- `contract_version = crypto_leader_rotation.live_pool.v1` -- `strategy_profile = crypto_leader_rotation` +- `contract_version = crypto_live_pool_rotation.live_pool.v1` +- `strategy_profile = crypto_live_pool_rotation` - `artifact_type = live_pool` -- `artifact_name = crypto_leader_rotation_live_pool` +- `artifact_name = crypto_live_pool_rotation_live_pool` - `as_of_date` - `snapshot_as_of` - `version` @@ -57,8 +57,8 @@ The `artifacts` mapping includes relative file paths and SHA-256 checksums for: - `live_pool_legacy` Downstream platforms should treat this manifest as the strategy artifact -contract and keep legacy `live_pool_legacy.json` parsing as a compatibility -path, not as the only contract shape. +contract. `live_pool_legacy.json` remains a secondary payload shape for scripts +that need a direct symbol mapping. ### `live_pool_legacy.json` @@ -86,7 +86,7 @@ Schema: "NEARUSDT": {"base_asset": "NEAR"}, "LTCUSDT": {"base_asset": "LTC"} }, - "source_project": "crypto-leader-rotation" + "source_project": "crypto-live-pool-pipelines" } ``` @@ -119,7 +119,7 @@ This file contains both the ordered list and the symbol mapping: "NEARUSDT": {"base_asset": "NEAR"}, "LTCUSDT": {"base_asset": "LTC"} }, - "source_project": "crypto-leader-rotation" + "source_project": "crypto-live-pool-pipelines" } ``` @@ -152,7 +152,7 @@ Optional additive research extension: Collection and document defaults: - collection: `strategy` -- document: `CRYPTO_LEADER_ROTATION_LIVE_POOL` +- document: `CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL` Payload example: @@ -170,18 +170,18 @@ Payload example: "NEARUSDT": {"base_asset": "NEAR"}, "LTCUSDT": {"base_asset": "LTC"} }, - "storage_prefix": "gs://example-bucket/crypto-leader-rotation/releases/2026-03-13-core_major", - "current_prefix": "gs://example-bucket/crypto-leader-rotation/current", - "live_pool_legacy_uri": "gs://example-bucket/crypto-leader-rotation/current/live_pool_legacy.json", - "live_pool_uri": "gs://example-bucket/crypto-leader-rotation/current/live_pool.json", - "artifact_manifest_uri": "gs://example-bucket/crypto-leader-rotation/current/artifact_manifest.json", - "latest_universe_uri": "gs://example-bucket/crypto-leader-rotation/current/latest_universe.json", - "latest_ranking_uri": "gs://example-bucket/crypto-leader-rotation/current/latest_ranking.csv", - "versioned_live_pool_legacy_uri": "gs://example-bucket/crypto-leader-rotation/releases/2026-03-13-core_major/live_pool_legacy.json", - "versioned_artifact_manifest_uri": "gs://example-bucket/crypto-leader-rotation/releases/2026-03-13-core_major/artifact_manifest.json", - "artifact_contract_version": "crypto_leader_rotation.live_pool.v1", + "storage_prefix": "gs://example-bucket/crypto-live-pool-pipelines/releases/2026-03-13-core_major", + "current_prefix": "gs://example-bucket/crypto-live-pool-pipelines/current", + "live_pool_legacy_uri": "gs://example-bucket/crypto-live-pool-pipelines/current/live_pool_legacy.json", + "live_pool_uri": "gs://example-bucket/crypto-live-pool-pipelines/current/live_pool.json", + "artifact_manifest_uri": "gs://example-bucket/crypto-live-pool-pipelines/current/artifact_manifest.json", + "latest_universe_uri": "gs://example-bucket/crypto-live-pool-pipelines/current/latest_universe.json", + "latest_ranking_uri": "gs://example-bucket/crypto-live-pool-pipelines/current/latest_ranking.csv", + "versioned_live_pool_legacy_uri": "gs://example-bucket/crypto-live-pool-pipelines/releases/2026-03-13-core_major/live_pool_legacy.json", + "versioned_artifact_manifest_uri": "gs://example-bucket/crypto-live-pool-pipelines/releases/2026-03-13-core_major/artifact_manifest.json", + "artifact_contract_version": "crypto_live_pool_rotation.live_pool.v1", "generated_at": "2026-03-13T13:00:00+00:00", - "source_project": "crypto-leader-rotation" + "source_project": "crypto-live-pool-pipelines" } ``` @@ -199,21 +199,21 @@ Stable vs additive fields: Versioned release objects: ```text -gs:///crypto-leader-rotation/releases//latest_universe.json -gs:///crypto-leader-rotation/releases//latest_ranking.csv -gs:///crypto-leader-rotation/releases//live_pool.json -gs:///crypto-leader-rotation/releases//live_pool_legacy.json -gs:///crypto-leader-rotation/releases//artifact_manifest.json +gs:///crypto-live-pool-pipelines/releases//latest_universe.json +gs:///crypto-live-pool-pipelines/releases//latest_ranking.csv +gs:///crypto-live-pool-pipelines/releases//live_pool.json +gs:///crypto-live-pool-pipelines/releases//live_pool_legacy.json +gs:///crypto-live-pool-pipelines/releases//artifact_manifest.json ``` Current pointers: ```text -gs:///crypto-leader-rotation/current/latest_universe.json -gs:///crypto-leader-rotation/current/latest_ranking.csv -gs:///crypto-leader-rotation/current/live_pool.json -gs:///crypto-leader-rotation/current/live_pool_legacy.json -gs:///crypto-leader-rotation/current/artifact_manifest.json +gs:///crypto-live-pool-pipelines/current/latest_universe.json +gs:///crypto-live-pool-pipelines/current/latest_ranking.csv +gs:///crypto-live-pool-pipelines/current/live_pool.json +gs:///crypto-live-pool-pipelines/current/live_pool_legacy.json +gs:///crypto-live-pool-pipelines/current/artifact_manifest.json ``` ## Local Shadow Release History @@ -286,7 +286,7 @@ This wrapper refreshes the official baseline artifacts, runs the publish dry-run ## Recommended Downstream Read Priority -1. Read Firestore `strategy/CRYPTO_LEADER_ROTATION_LIVE_POOL` +1. Read Firestore `strategy/CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL` 2. If the latest Firestore payload is invalid or unavailable, prefer the downstream script's last known good upstream payload 3. If explicitly configured, read the synchronized `live_pool_legacy.json` or `live_pool.json` 4. If all upstream-aware layers fail, fall back to the downstream script's static universe as an emergency-only path @@ -302,7 +302,7 @@ Freshness semantics: ```python def load_trend_pool(): - payload = try_read_firestore("strategy", "CRYPTO_LEADER_ROTATION_LIVE_POOL") + payload = try_read_firestore("strategy", "CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL") if is_valid_and_fresh(payload): return payload["symbol_map"], {"source": "fresh_upstream"} @@ -321,7 +321,7 @@ def load_trend_pool(): Preferred rollback: -1. choose the previous version under `gs:///crypto-leader-rotation/releases/` +1. choose the previous version under `gs:///crypto-live-pool-pipelines/releases/` 2. copy its four artifacts back onto the `current/` prefix 3. update the Firestore summary document so `version`, `as_of_date`, and URIs point to that release diff --git a/docs/operator_runbook.md b/docs/operator_runbook.md index 07b7bba..a066e71 100644 --- a/docs/operator_runbook.md +++ b/docs/operator_runbook.md @@ -32,13 +32,12 @@ Primary production outputs: Primary publish targets: -- GCS current pointers under `crypto-leader-rotation/current` -- GCS versioned release objects under `crypto-leader-rotation/releases/` -- Firestore `strategy/CRYPTO_LEADER_ROTATION_LIVE_POOL` +- GCS current pointers under `crypto-live-pool-pipelines/current` +- GCS versioned release objects under `crypto-live-pool-pipelines/releases/` +- Firestore `strategy/CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL` -The GCS prefix, Firestore document, and `source_project` value intentionally -remain in the `crypto-leader-rotation` v1 artifact namespace for downstream -compatibility. +The GCS prefix, Firestore document, and `source_project` value use the +`crypto-live-pool-pipelines` v1 artifact namespace. This repository owns the monthly live-pool membership, ranking, and published symbol order. Downstream runtime repositories should consume the validated @@ -221,7 +220,7 @@ Use rollback only when the newest publish is clearly bad or malformed. 1. Identify the last known good version from: - Firestore document history -- GCS `crypto-leader-rotation/releases//` +- GCS `crypto-live-pool-pipelines/releases//` - the last good `data/output/release_manifest.json` 2. Restore the five canonical artifacts from that version into `data/output/`: @@ -256,6 +255,6 @@ Rollback note: - Confirm `release_status_summary.json` reports `status=ok` for the published month. - Confirm `data/output/monthly_report_bundle/job_summary.md` matches the released month and includes the expected bundle file list. - Confirm the Actions run uploaded a `monthly-report-` artifact for download. -- Confirm Firestore `strategy/CRYPTO_LEADER_ROTATION_LIVE_POOL` contains the expected `version`, `mode`, `symbols`, and `source_project`. +- Confirm Firestore `strategy/CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL` contains the expected `version`, `mode`, `symbols`, and `source_project`. - Confirm GCS current pointers and versioned objects exist for the same version. - Confirm downstream consumers are reading the new version without falling back to degraded sources. diff --git a/scripts/build_live_pool.py b/scripts/build_live_pool.py index cbbd10a..9018367 100644 --- a/scripts/build_live_pool.py +++ b/scripts/build_live_pool.py @@ -58,7 +58,7 @@ def main() -> None: config["paths"].output_dir, expected_mode=result["universe_mode"], expected_source_project=str( - config.get("publish", {}).get("source_project", config.get("project", {}).get("name", "crypto-leader-rotation")) + config.get("publish", {}).get("source_project", config.get("project", {}).get("name", "crypto-live-pool-pipelines")) ), expected_pool_size=int(config["export"]["live_pool_size"]), max_age_days=args.contract_max_age_days, diff --git a/scripts/run_research_backtest.py b/scripts/run_research_backtest.py index 667f911..e87f891 100644 --- a/scripts/run_research_backtest.py +++ b/scripts/run_research_backtest.py @@ -15,7 +15,7 @@ def parse_args() -> argparse.Namespace: - parser = argparse.ArgumentParser(description="Run the full crypto leader rotation research pipeline.") + parser = argparse.ArgumentParser(description="Run the full crypto live pool rotation research pipeline.") parser.add_argument("--config", default="config/default.yaml", help="Path to the YAML config file.") parser.add_argument("--universe-mode", default=None, help="Optional universe mode override, e.g. broad_liquid.") return parser.parse_args() diff --git a/scripts/validate_release_contract.py b/scripts/validate_release_contract.py index 704fecb..7e7eecb 100644 --- a/scripts/validate_release_contract.py +++ b/scripts/validate_release_contract.py @@ -19,7 +19,7 @@ def parse_args() -> argparse.Namespace: ) parser.add_argument("--output-dir", default="data/output", help="Directory containing release artifacts.") parser.add_argument("--mode", default=None, help="Optional expected mode, for example core_major.") - parser.add_argument("--source-project", default="crypto-leader-rotation", help="Expected source_project value.") + parser.add_argument("--source-project", default="crypto-live-pool-pipelines", help="Expected source_project value.") parser.add_argument("--expected-pool-size", type=int, default=None, help="Optional expected live pool size.") parser.add_argument( "--max-age-days", diff --git a/src/__init__.py b/src/__init__.py index 6ac9b9f..7f32632 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -1,4 +1,4 @@ -"""Crypto leader rotation research and live pool package.""" +"""Crypto live pool rotation research and live pool package.""" __all__ = ["__version__"] __version__ = "0.1.0" diff --git a/src/export.py b/src/export.py index 9bfd108..ba71e13 100644 --- a/src/export.py +++ b/src/export.py @@ -10,9 +10,9 @@ from .utils import date_to_str, write_json -DEFAULT_STRATEGY_PROFILE = "crypto_leader_rotation" +DEFAULT_STRATEGY_PROFILE = "crypto_live_pool_rotation" DEFAULT_ARTIFACT_TYPE = "live_pool" -DEFAULT_ARTIFACT_CONTRACT_VERSION = "crypto_leader_rotation.live_pool.v1" +DEFAULT_ARTIFACT_CONTRACT_VERSION = "crypto_live_pool_rotation.live_pool.v1" def _sha256_file(path: Path) -> str: @@ -75,7 +75,7 @@ def build_live_pool_payload( as_of_date: pd.Timestamp, pool_size: int, mode: str = "core_major", - source_project: str = "crypto-leader-rotation", + source_project: str = "crypto-live-pool-pipelines", selection_meta_fields: list[str] | None = None, ) -> tuple[dict[str, Any], dict[str, Any]]: """Build additive live-pool payloads without performing I/O.""" @@ -137,7 +137,7 @@ def export_live_pool( as_of_date: pd.Timestamp, pool_size: int, mode: str = "core_major", - source_project: str = "crypto-leader-rotation", + source_project: str = "crypto-live-pool-pipelines", selection_meta_fields: list[str] | None = None, save_legacy: bool = True, ) -> dict[str, Any]: @@ -165,7 +165,7 @@ def build_strategy_artifact_manifest( strategy_profile: str = DEFAULT_STRATEGY_PROFILE, artifact_type: str = DEFAULT_ARTIFACT_TYPE, contract_version: str = DEFAULT_ARTIFACT_CONTRACT_VERSION, - source_project: str = "crypto-leader-rotation", + source_project: str = "crypto-live-pool-pipelines", generated_at: Any | None = None, ) -> dict[str, Any]: """Build the profile-aware artifact manifest consumed by downstream runtimes.""" @@ -231,7 +231,7 @@ def export_strategy_artifact_manifest( strategy_profile: str = DEFAULT_STRATEGY_PROFILE, artifact_type: str = DEFAULT_ARTIFACT_TYPE, contract_version: str = DEFAULT_ARTIFACT_CONTRACT_VERSION, - source_project: str = "crypto-leader-rotation", + source_project: str = "crypto-live-pool-pipelines", ) -> dict[str, Any]: manifest = build_strategy_artifact_manifest( output_dir=output_dir, diff --git a/src/pipeline.py b/src/pipeline.py index a721643..813822c 100644 --- a/src/pipeline.py +++ b/src/pipeline.py @@ -394,7 +394,7 @@ def build_live_pool_outputs( source_project = str( config.get("publish", {}).get( "source_project", - config.get("project", {}).get("name", "crypto-leader-rotation"), + config.get("project", {}).get("name", "crypto-live-pool-pipelines"), ) ) live_payload = export_live_pool( diff --git a/src/publish.py b/src/publish.py index c6df6ec..3e41488 100644 --- a/src/publish.py +++ b/src/publish.py @@ -89,7 +89,7 @@ def resolve_publish_settings( mode=str(effective_mode), gcp_project_id=gcp_project_id or os.getenv("GCP_PROJECT_ID") or publish_cfg.get("gcp_project_id"), gcs_bucket=gcs_bucket or os.getenv("GCS_BUCKET") or publish_cfg.get("gcs_bucket"), - gcs_root_prefix=str(publish_cfg.get("gcs_root_prefix", "crypto-leader-rotation")).strip("/"), + gcs_root_prefix=str(publish_cfg.get("gcs_root_prefix", "crypto-live-pool-pipelines")).strip("/"), firestore_collection=( firestore_collection or os.getenv("FIRESTORE_COLLECTION") @@ -98,9 +98,9 @@ def resolve_publish_settings( firestore_document=( firestore_document or os.getenv("FIRESTORE_DOCUMENT") - or publish_cfg.get("firestore_document", "CRYPTO_LEADER_ROTATION_LIVE_POOL") + or publish_cfg.get("firestore_document", "CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL") ), - source_project=str(publish_cfg.get("source_project", config.get("project", {}).get("name", "crypto-leader-rotation"))), + source_project=str(publish_cfg.get("source_project", config.get("project", {}).get("name", "crypto-live-pool-pipelines"))), upload_current_pointer=parse_bool( os.getenv("UPLOAD_CURRENT_POINTER"), publish_cfg.get("upload_current_pointer", True), diff --git a/src/release_contract.py b/src/release_contract.py index 2ddc055..47cd612 100644 --- a/src/release_contract.py +++ b/src/release_contract.py @@ -61,7 +61,7 @@ "live_pool": "live_pool.json", "live_pool_legacy": "live_pool_legacy.json", } -EXPECTED_ARTIFACT_CONTRACT_VERSION = "crypto_leader_rotation.live_pool.v1" +EXPECTED_ARTIFACT_CONTRACT_VERSION = "crypto_live_pool_rotation.live_pool.v1" def _sha256_file(path: Path) -> str: @@ -512,8 +512,8 @@ def validate_release_outputs( errors.append( f"artifact_manifest.json contract_version must be {EXPECTED_ARTIFACT_CONTRACT_VERSION}" ) - if str(artifact_manifest.get("strategy_profile", "")).strip() != "crypto_leader_rotation": - errors.append("artifact_manifest.json strategy_profile must be crypto_leader_rotation") + if str(artifact_manifest.get("strategy_profile", "")).strip() != "crypto_live_pool_rotation": + errors.append("artifact_manifest.json strategy_profile must be crypto_live_pool_rotation") if str(artifact_manifest.get("artifact_type", "")).strip() != "live_pool": errors.append("artifact_manifest.json artifact_type must be live_pool") if str(artifact_manifest.get("primary_artifact", "")).strip() != "live_pool": diff --git a/src/shadow.py b/src/shadow.py index 8377c9c..6df262b 100644 --- a/src/shadow.py +++ b/src/shadow.py @@ -36,7 +36,7 @@ def build_shadow_release_history( source_project = str( config.get("publish", {}).get("source_project") or config.get("project", {}).get("name") - or "crypto-leader-rotation" + or "crypto-live-pool-pipelines" ) pool_size = int(config["export"]["live_pool_size"]) diff --git a/src/utils.py b/src/utils.py index cb6bee6..7d42547 100644 --- a/src/utils.py +++ b/src/utils.py @@ -9,7 +9,7 @@ import pandas as pd -def get_logger(name: str = "crypto_leader_rotation") -> logging.Logger: +def get_logger(name: str = "crypto_live_pool_rotation") -> logging.Logger: """Create a process-wide console logger with a simple format.""" logger = logging.getLogger(name) if logger.handlers: diff --git a/tests/fixtures/build_live_pool_smoke/live_pool.json b/tests/fixtures/build_live_pool_smoke/live_pool.json index e009149..7ddf2d0 100644 --- a/tests/fixtures/build_live_pool_smoke/live_pool.json +++ b/tests/fixtures/build_live_pool_smoke/live_pool.json @@ -27,5 +27,5 @@ "base_asset": "SOL" } }, - "source_project": "crypto-leader-rotation" + "source_project": "crypto-live-pool-pipelines" } diff --git a/tests/fixtures/build_live_pool_smoke/live_pool_legacy.json b/tests/fixtures/build_live_pool_smoke/live_pool_legacy.json index ca88601..e208c77 100644 --- a/tests/fixtures/build_live_pool_smoke/live_pool_legacy.json +++ b/tests/fixtures/build_live_pool_smoke/live_pool_legacy.json @@ -37,5 +37,5 @@ "base_asset": "SOL" } }, - "source_project": "crypto-leader-rotation" + "source_project": "crypto-live-pool-pipelines" } diff --git a/tests/test_build_live_pool_smoke.py b/tests/test_build_live_pool_smoke.py index f7699d0..3b4f2e1 100644 --- a/tests/test_build_live_pool_smoke.py +++ b/tests/test_build_live_pool_smoke.py @@ -28,7 +28,7 @@ def write_config(path: Path, output_dir: Path) -> None: "\n".join( [ "project:", - ' name: "crypto-leader-rotation"', + ' name: "crypto-live-pool-pipelines"', "data:", f' raw_dir: "{fixture_root / "raw"}"', f' cache_dir: "{fixture_root / "cache"}"', @@ -40,7 +40,7 @@ def write_config(path: Path, output_dir: Path) -> None: " live_pool_size: 5", " save_legacy_live_pool: true", "publish:", - ' source_project: "crypto-leader-rotation"', + ' source_project: "crypto-live-pool-pipelines"', "", ] ), @@ -90,7 +90,7 @@ def fake_build_live_pool_outputs(config, as_of_date=None, universe_mode=None): validation = validate_release_outputs( output_dir, expected_mode="core_major", - expected_source_project="crypto-leader-rotation", + expected_source_project="crypto-live-pool-pipelines", expected_pool_size=5, require_artifact_manifest=True, require_freshness=False, diff --git a/tests/test_monthly_review_briefing.py b/tests/test_monthly_review_briefing.py index e51115c..83d7aac 100644 --- a/tests/test_monthly_review_briefing.py +++ b/tests/test_monthly_review_briefing.py @@ -42,7 +42,7 @@ def write_fixture_files( "mode": "core_major", "pool_size": 5, "symbols": ["TRXUSDT", "ETHUSDT", "BCHUSDT", "NEARUSDT", "SOLUSDT"], - "source_project": "crypto-leader-rotation", + "source_project": "crypto-live-pool-pipelines", } manifest = { "as_of_date": "2026-03-13", @@ -50,11 +50,11 @@ def write_fixture_files( "mode": "core_major", "dry_run": True, "publish_enabled": False, - "release_prefix": "crypto-leader-rotation/releases/2026-03-13-core_major", - "current_prefix": "crypto-leader-rotation/current", + "release_prefix": "crypto-live-pool-pipelines/releases/2026-03-13-core_major", + "current_prefix": "crypto-live-pool-pipelines/current", "firestore": { "collection": "strategy", - "document": "CRYPTO_LEADER_ROTATION_LIVE_POOL", + "document": "CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL", }, } with (output_dir / "live_pool.json").open("w", encoding="utf-8") as handle: @@ -70,7 +70,7 @@ def write_fixture_files( "mode": "core_major", "pool_size": 5, "symbols": ["TRXUSDT", "ETHUSDT", "BCHUSDT", "NEARUSDT", "SOLUSDT"], - "source_project": "crypto-leader-rotation", + "source_project": "crypto-live-pool-pipelines", }, "validation": {"errors": [], "warnings": []}, }, diff --git a/tests/test_release_contract.py b/tests/test_release_contract.py index 1200f17..1cf8502 100644 --- a/tests/test_release_contract.py +++ b/tests/test_release_contract.py @@ -31,7 +31,7 @@ def build_outputs( *, as_of_date: str = "2026-03-13", mode: str = "core_major", - source_project: str = "crypto-leader-rotation", + source_project: str = "crypto-live-pool-pipelines", include_manifest: bool = False, ) -> None: output_dir = root / "data" / "output" @@ -89,10 +89,10 @@ def build_outputs( output_dir / "artifact_manifest.json", { "manifest_type": "strategy_artifact", - "contract_version": "crypto_leader_rotation.live_pool.v1", - "strategy_profile": "crypto_leader_rotation", + "contract_version": "crypto_live_pool_rotation.live_pool.v1", + "strategy_profile": "crypto_live_pool_rotation", "artifact_type": "live_pool", - "artifact_name": "crypto_leader_rotation_live_pool", + "artifact_name": "crypto_live_pool_rotation_live_pool", "as_of_date": as_of_date, "snapshot_as_of": as_of_date, "version": version, @@ -132,12 +132,12 @@ def build_outputs( "dry_run": True, "publish_enabled": False, "as_of_date": as_of_date, - "release_prefix": f"crypto-leader-rotation/releases/{version}", - "current_prefix": "crypto-leader-rotation/current", + "release_prefix": f"crypto-live-pool-pipelines/releases/{version}", + "current_prefix": "crypto-live-pool-pipelines/current", "artifacts": {}, "firestore": { "collection": "strategy", - "document": "CRYPTO_LEADER_ROTATION_LIVE_POOL", + "document": "CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL", "payload": { "as_of_date": as_of_date, "version": version, @@ -159,7 +159,7 @@ def test_validate_release_outputs_accepts_consistent_contract(self) -> None: validation = validate_release_outputs( root / "data" / "output", expected_mode="core_major", - expected_source_project="crypto-leader-rotation", + expected_source_project="crypto-live-pool-pipelines", expected_pool_size=5, reference_date="2026-03-14", max_age_days=45, @@ -170,7 +170,7 @@ def test_validate_release_outputs_accepts_consistent_contract(self) -> None: self.assertTrue(validation["ok"]) self.assertTrue(validation["artifact_manifest_present"]) - self.assertEqual(validation["artifact_contract_version"], "crypto_leader_rotation.live_pool.v1") + self.assertEqual(validation["artifact_contract_version"], "crypto_live_pool_rotation.live_pool.v1") self.assertEqual(validation["version"], "2026-03-13-core_major") self.assertEqual(validation["pool_size"], 5) self.assertEqual(validation["age_days"], 1) @@ -181,7 +181,7 @@ def test_validate_release_outputs_rejects_mismatched_artifact_manifest(self) -> self.build_outputs(root) manifest_path = root / "data" / "output" / "artifact_manifest.json" manifest = json.loads(manifest_path.read_text(encoding="utf-8")) - manifest["contract_version"] = "crypto_leader_rotation.live_pool.v0" + manifest["contract_version"] = "crypto_live_pool_rotation.live_pool.v0" manifest["artifacts"]["live_pool"]["sha256"] = "wrong" write_json(manifest_path, manifest) @@ -192,7 +192,7 @@ def test_validate_release_outputs_rejects_mismatched_artifact_manifest(self) -> self.assertFalse(validation["ok"]) self.assertIn( - "artifact_manifest.json contract_version must be crypto_leader_rotation.live_pool.v1", + "artifact_manifest.json contract_version must be crypto_live_pool_rotation.live_pool.v1", validation["errors"], ) self.assertIn( @@ -310,12 +310,12 @@ def test_publish_preflight_requires_real_publish_targets(self) -> None: (), { "mode": "core_major", - "source_project": "crypto-leader-rotation", + "source_project": "crypto-live-pool-pipelines", "dry_run": False, "gcp_project_id": None, "gcs_bucket": None, "firestore_collection": "strategy", - "firestore_document": "CRYPTO_LEADER_ROTATION_LIVE_POOL", + "firestore_document": "CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL", }, )(), root / "data" / "output", diff --git a/tests/test_release_status_summary.py b/tests/test_release_status_summary.py index 3292594..83e7f7c 100644 --- a/tests/test_release_status_summary.py +++ b/tests/test_release_status_summary.py @@ -54,7 +54,7 @@ def write_outputs( "pool_size": 5, "symbols": symbols, "symbol_map": symbol_map, - "source_project": "crypto-leader-rotation", + "source_project": "crypto-live-pool-pipelines", }, ) write_json( @@ -66,7 +66,7 @@ def write_outputs( "pool_size": 5, "symbols": symbol_map, "symbol_map": symbol_map, - "source_project": "crypto-leader-rotation", + "source_project": "crypto-live-pool-pipelines", }, ) pd.DataFrame( @@ -92,17 +92,17 @@ def write_outputs( output_dir / "artifact_manifest.json", { "manifest_type": "strategy_artifact", - "contract_version": "crypto_leader_rotation.live_pool.v1", - "strategy_profile": "crypto_leader_rotation", + "contract_version": "crypto_live_pool_rotation.live_pool.v1", + "strategy_profile": "crypto_live_pool_rotation", "artifact_type": "live_pool", - "artifact_name": "crypto_leader_rotation_live_pool", + "artifact_name": "crypto_live_pool_rotation_live_pool", "as_of_date": "2026-03-13", "snapshot_as_of": "2026-03-13", "version": version, "mode": "core_major", "symbol_count": len(symbols), "symbols": symbols, - "source_project": "crypto-leader-rotation", + "source_project": "crypto-live-pool-pipelines", "generated_at": "2026-03-13T00:00:00+00:00", "primary_artifact": "live_pool", "artifacts": { @@ -135,11 +135,11 @@ def write_outputs( "dry_run": True, "publish_enabled": False, "as_of_date": "2026-03-13", - "release_prefix": f"crypto-leader-rotation/releases/{version}", - "current_prefix": "crypto-leader-rotation/current", + "release_prefix": f"crypto-live-pool-pipelines/releases/{version}", + "current_prefix": "crypto-live-pool-pipelines/current", "firestore": { "collection": "strategy", - "document": "CRYPTO_LEADER_ROTATION_LIVE_POOL", + "document": "CRYPTO_LIVE_POOL_ROTATION_LIVE_POOL", "payload": { "as_of_date": "2026-03-13", "version": version, @@ -147,7 +147,7 @@ def write_outputs( "pool_size": 5, "symbols": symbols, "symbol_map": symbol_map, - "source_project": "crypto-leader-rotation", + "source_project": "crypto-live-pool-pipelines", }, }, }, @@ -172,7 +172,7 @@ def test_build_release_status_payload_reports_ok_for_consistent_release(self) -> self.assertEqual(payload["status"], "ok") self.assertEqual(payload["official_release"]["version"], "2026-03-13-core_major") self.assertEqual(payload["artifact_summary"]["latest_universe_symbol_count"], 6) - self.assertEqual(payload["artifact_summary"]["artifact_contract_version"], "crypto_leader_rotation.live_pool.v1") + self.assertEqual(payload["artifact_summary"]["artifact_contract_version"], "crypto_live_pool_rotation.live_pool.v1") self.assertEqual(len(payload["artifact_summary"]["ranking_preview"]), 3) self.assertTrue(payload["validation"]["ok"]) diff --git a/tests/test_shadow_release_history.py b/tests/test_shadow_release_history.py index 4609dd2..c406e09 100644 --- a/tests/test_shadow_release_history.py +++ b/tests/test_shadow_release_history.py @@ -42,7 +42,7 @@ def test_build_shadow_release_history_writes_index_and_selection_meta(self) -> N ) config = { "export": {"live_pool_size": 2}, - "publish": {"mode": "core_major", "source_project": "crypto-leader-rotation"}, + "publish": {"mode": "core_major", "source_project": "crypto-live-pool-pipelines"}, "universe": {"live_mode": "core_major"}, }