Move validation scripts from docs/agent-training to scripts/training

- Move validate_stage_dependencies.py to scripts/training/
- Move generate_prerequisite_checks.py to scripts/training/
- Scripts/training is the standard location for training-related scripts
This commit is contained in:
aitbc
2026-05-07 11:59:53 +02:00
parent 295b0a604b
commit db93b314d9
2 changed files with 0 additions and 0 deletions

View File

@@ -1,265 +0,0 @@
#!/usr/bin/env python3
"""
Prerequisite Check Generator
Generates prerequisite validation checks for training stages.
Validates that all dependencies (stage and resource) are satisfied before running a stage.
"""
import json
import sys
from pathlib import Path
from typing import Dict, List, Set
STAGE_ORDER = [
"stage0_environment_setup",
"stage1_foundation",
"stage2_operations_mastery",
"stage3_ai_operations",
"stage4_marketplace_economics",
"stage5_expert_operations",
"stage6_agent_identity_sdk",
"stage7_cross_node_training",
"stage8_advanced_agent_specialization",
"stage9_multi_chain_architecture",
]
class PrerequisiteChecker:
def __init__(self, stages_dir: Path):
self.stages_dir = stages_dir
self.stages: Dict[str, dict] = {}
self.errors = []
self.warnings = []
def load_stages(self):
"""Load all stage JSON files."""
for stage_name in STAGE_ORDER:
stage_file = self.stages_dir / f"{stage_name}.json"
if stage_file.exists():
self.stages[stage_name] = json.loads(stage_file.read_text())
else:
self.warnings.append(f"Stage file not found: {stage_file}")
def check_stage_order(self, stage_name: str) -> bool:
"""Check that depends_on stages come before this stage in order."""
stage_data = self.stages.get(stage_name)
if not stage_data:
return False
depends_on = stage_data.get("depends_on", [])
stage_index = STAGE_ORDER.index(stage_name)
for dep_stage in depends_on:
if dep_stage not in STAGE_ORDER:
self.errors.append(f"{stage_name}: depends_on references unknown stage '{dep_stage}'")
continue
dep_index = STAGE_ORDER.index(dep_stage)
if dep_index >= stage_index:
self.errors.append(
f"{stage_name}: depends_on '{dep_stage}' comes after it in stage order "
f"(index {dep_index} >= {stage_index})"
)
return len(self.errors) == 0
def check_resource_dependencies(self, stage_name: str) -> bool:
"""Check that resource_depends references valid stages."""
stage_data = self.stages.get(stage_name)
if not stage_data:
return False
resource_depends = stage_data.get("resource_depends", [])
depends_on = stage_data.get("depends_on", [])
for resource_dep in resource_depends:
provider_stage = resource_dep.get("stage")
if provider_stage:
if provider_stage not in STAGE_ORDER:
self.errors.append(
f"{stage_name}: resource_depends references unknown stage '{provider_stage}'"
)
elif provider_stage not in depends_on and provider_stage != stage_name:
self.warnings.append(
f"{stage_name}: resource_depends stage '{provider_stage}' "
f"not in depends_on (should be added)"
)
return len(self.errors) == 0
def check_wallet_balance_placement(self, stage_name: str) -> bool:
"""Check that wallet_balance appears before operations with wallet+password."""
stage_data = self.stages.get(stage_name)
if not stage_data:
return False
operations = stage_data.get("training_data", {}).get("operations", [])
wallet_balance_found = False
for i, op in enumerate(operations):
op_name = op.get("operation", "")
params = op.get("parameters", {})
if op_name == "wallet_balance":
wallet_balance_found = True
continue
has_wallet = "wallet" in params
has_password = "password" in params
if has_wallet and has_password and not wallet_balance_found:
self.errors.append(
f"{stage_name}: operation '{op_name}' (index {i}) has wallet+password "
f"but no wallet_balance check before it"
)
return len(self.errors) == 0
def check_currency_fields(self, stage_name: str) -> bool:
"""Check that operations with amount/price have currency field."""
stage_data = self.stages.get(stage_name)
if not stage_data:
return False
operations = stage_data.get("training_data", {}).get("operations", [])
currency_required_params = {"amount", "price", "bounty_amount", "stake_amount", "spread"}
for i, op in enumerate(operations):
op_name = op.get("operation", "")
params = op.get("parameters", {})
requires_currency = any(param in currency_required_params for param in params.keys())
if requires_currency and "currency" not in params:
self.errors.append(
f"{stage_name}: operation '{op_name}' (index {i}) has "
f"{currency_required_params} parameter(s) but missing 'currency' field"
)
return len(self.errors) == 0
def validate_stage(self, stage_name: str) -> bool:
"""Run all prerequisite checks for a stage."""
self.check_stage_order(stage_name)
self.check_resource_dependencies(stage_name)
self.check_wallet_balance_placement(stage_name)
self.check_currency_fields(stage_name)
return len(self.errors) == 0
def validate_all(self) -> bool:
"""Validate all stages."""
for stage_name in STAGE_ORDER:
if stage_name in self.stages:
self.validate_stage(stage_name)
return len(self.errors) == 0
def generate_prerequisite_script(self, stage_name: str) -> str:
"""Generate a bash script to check prerequisites for a stage."""
stage_data = self.stages.get(stage_name)
if not stage_data:
return f"# Stage {stage_name} not found"
depends_on = stage_data.get("depends_on", [])
resource_depends = stage_data.get("resource_depends", [])
script_lines = [
f"#!/bin/bash",
f"# Prerequisite checks for {stage_name}",
f"#",
f"# This script validates that all prerequisites are satisfied",
f"# before starting the training stage.",
f"",
f"set -e",
f"",
f'echo "Checking prerequisites for {stage_name}..."',
]
# Check stage dependencies
if depends_on:
script_lines.append(f"# Stage dependencies")
for dep_stage in depends_on:
script_lines.extend([
f"if [ ! -f \"$(dirname \"$0\")/{dep_stage}.json\" ]; then",
f' echo "❌ Missing prerequisite stage: {dep_stage}"',
f" exit 1",
f"fi",
f'echo "✅ Prerequisite stage found: {dep_stage}"',
f"",
])
# Check resource dependencies
if resource_depends:
script_lines.append(f"# Resource dependencies")
for res_dep in resource_depends:
resource_type = res_dep.get("resource", "")
condition = res_dep.get("condition", "")
script_lines.extend([
f"# Check {resource_type}: {condition}",
f"# TODO: Implement resource check for {resource_type}",
f'echo "⚠️ Resource check not implemented: {resource_type}"',
f"",
])
script_lines.extend([
f'echo "✅ All prerequisites satisfied for {stage_name}"',
f"exit 0",
])
return "\n".join(script_lines)
def report(self):
"""Print validation report."""
print("Prerequisite Validation Report")
print("=" * 50)
if self.errors:
print(f"{len(self.errors)} error(s) found:")
for error in self.errors:
print(f" - {error}")
else:
print("✅ No errors found")
if self.warnings:
print(f"\n⚠️ {len(self.warnings)} warning(s):")
for warning in self.warnings:
print(f" - {warning}")
print("\nStage Status:")
for stage_name in STAGE_ORDER:
if stage_name in self.stages:
print(f"{stage_name}")
else:
print(f"{stage_name} (file not found)")
def main():
if len(sys.argv) < 2:
print("Usage: generate_prerequisite_checks.py <stages_dir> [stage_name]")
print(" stages_dir: Path to directory containing stage JSON files")
print(" stage_name: (optional) Generate prerequisite script for specific stage")
sys.exit(1)
stages_dir = Path(sys.argv[1])
if not stages_dir.exists():
print(f"❌ Stages directory not found: {stages_dir}")
sys.exit(1)
checker = PrerequisiteChecker(stages_dir)
checker.load_stages()
# If specific stage requested, generate prerequisite script
if len(sys.argv) >= 3:
stage_name = sys.argv[2]
script = checker.generate_prerequisite_script(stage_name)
print(script)
sys.exit(0)
# Otherwise, validate all stages
checker.validate_all()
checker.report()
sys.exit(0 if len(checker.errors) == 0 else 1)
if __name__ == "__main__":
main()

View File

@@ -1,199 +0,0 @@
#!/usr/bin/env python3
"""
Stage Dependency Validator
Validates that stage JSON files follow dependency rules:
1. Operations with wallet+password parameters should have wallet_balance check before them
2. Operations with amount/price parameters should have currency field
3. Operations that require resources (agent_id, dispute_id, etc.) should have corresponding create operations
"""
import json
import sys
from pathlib import Path
from typing import Dict, List, Set
# Parameters that indicate wallet+password operations
WALLET_PASSWORD_PARAMS = {"wallet", "password"}
# Parameters that indicate currency requirement
CURRENCY_REQUIRED_PARAMS = {"amount", "price", "bounty_amount", "stake_amount", "spread"}
# Resource ID patterns
RESOURCE_PATTERNS = {
"agent_id": "agent_*",
"dispute_id": "dispute_*",
"enterprise_id": "enterprise_*",
"proposal_id": "proposal_*",
"island_id": "island_*",
"workflow_id": "workflow_*",
"gpu_id": "gpu_*",
"listing_id": "listing_*",
"job_id": "job_*",
"bounty_id": "bounty_*",
"mm_id": "mm_*",
"fl_id": "fl_*",
"swarm_id": "swarm_*",
"validator_id": "validator_*",
"bridge_tx_id": "bridge_tx_*",
"transfer_id": "transfer_*",
"deployment_id": "deployment_*",
"pubsub_config_id": "pubsub_config_*",
"sync_config_id": "sync_config_*",
}
# Operations that create resources (can create multiple resources)
RESOURCE_CREATORS = {
"agent_create": ["agent_id"],
"dispute_create": ["dispute_id"],
"enterprise_create": ["enterprise_id"],
"governance_propose": ["proposal_id"],
"island_create": ["island_id"],
"multi_chain_island_setup": ["island_id"],
"workflow_create": ["workflow_id"],
"market_gpu_register": ["gpu_id", "listing_id"],
"market_sell": ["listing_id"],
"ai_submit": ["job_id"],
"bounty_system": ["bounty_id"],
"cross_chain_market_maker": ["mm_id"],
"federated_learning_coordinator": ["fl_id"],
"agent_swarm_create": ["swarm_id"],
"staking_validator_agent": ["validator_id"],
"cross_chain_bridge": ["bridge_tx_id"],
"cross_chain_transfer": ["transfer_id"],
"production_deploy": ["deployment_id"],
"redis_pubsub_config": ["pubsub_config_id"],
"gossip_sync_config": ["sync_config_id"],
}
class StageValidator:
def __init__(self, stage_file: Path):
self.stage_file = stage_file
self.stage_data = json.loads(stage_file.read_text())
self.errors = []
self.warnings = []
def validate(self) -> bool:
"""Run all validation checks."""
operations = self.stage_data.get("training_data", {}).get("operations", [])
self._validate_wallet_balance_checks(operations)
self._validate_currency_fields(operations)
self._validate_resource_dependencies(operations)
return len(self.errors) == 0
def _validate_wallet_balance_checks(self, operations: List[Dict]):
"""Ensure operations with wallet+password have wallet_balance check before them."""
wallet_balance_found = False
for i, op in enumerate(operations):
op_name = op.get("operation", "")
params = op.get("parameters", {})
if op_name == "wallet_balance":
wallet_balance_found = True
continue
# Check if operation requires wallet+password
has_wallet = "wallet" in params
has_password = "password" in params
if has_wallet and has_password:
if not wallet_balance_found:
self.errors.append(
f"Operation '{op_name}' (index {i}) has wallet+password parameters "
f"but no wallet_balance check before it"
)
def _validate_currency_fields(self, operations: List[Dict]):
"""Ensure operations with amount/price parameters have currency field."""
for i, op in enumerate(operations):
op_name = op.get("operation", "")
params = op.get("parameters", {})
# Check if operation requires currency
requires_currency = any(
param in CURRENCY_REQUIRED_PARAMS for param in params.keys()
)
if requires_currency and "currency" not in params:
self.errors.append(
f"Operation '{op_name}' (index {i}) has {CURRENCY_REQUIRED_PARAMS} parameter(s) "
f"but missing 'currency' field"
)
def _validate_resource_dependencies(self, operations: List[Dict]):
"""Ensure operations that require resources have corresponding create operations."""
created_resources: Dict[str, Set[str]] = {} # resource_type -> set of patterns
required_resources: List[tuple] = [] # (index, op_name, resource_type, pattern)
for i, op in enumerate(operations):
op_name = op.get("operation", "")
params = op.get("parameters", {})
# Track resources created
if op_name in RESOURCE_CREATORS:
resource_types = RESOURCE_CREATORS[op_name]
if isinstance(resource_types, str):
resource_types = [resource_types]
for resource_type in resource_types:
if resource_type not in created_resources:
created_resources[resource_type] = set()
created_resources[resource_type].add(RESOURCE_PATTERNS.get(resource_type, f"{resource_type}_*"))
# Track resources required
for param_name, param_value in params.items():
for resource_type, pattern in RESOURCE_PATTERNS.items():
if param_name == resource_type or (isinstance(param_value, str) and pattern in param_value):
required_resources.append((i, op_name, resource_type, pattern))
# Validate that required resources have corresponding create operations
for index, op_name, resource_type, pattern in required_resources:
if resource_type not in created_resources:
self.errors.append(
f"Operation '{op_name}' (index {index}) requires '{resource_type}' "
f"but no '{resource_type}' create operation found"
)
def report(self):
"""Print validation report."""
stage_name = self.stage_data.get("stage", self.stage_file.name)
if self.errors:
print(f"{stage_name}: {len(self.errors)} error(s)")
for error in self.errors:
print(f" - {error}")
else:
print(f"{stage_name}: No errors")
if self.warnings:
print(f"⚠️ {stage_name}: {len(self.warnings)} warning(s)")
for warning in self.warnings:
print(f" - {warning}")
def main():
if len(sys.argv) < 2:
print("Usage: validate_stage_dependencies.py <stage_file.json> [stage_file2.json ...]")
sys.exit(1)
all_valid = True
for stage_path in sys.argv[1:]:
stage_file = Path(stage_path)
if not stage_file.exists():
print(f"❌ File not found: {stage_file}")
all_valid = False
continue
validator = StageValidator(stage_file)
if not validator.validate():
all_valid = False
validator.report()
sys.exit(0 if all_valid else 1)
if __name__ == "__main__":
main()