From 0cc9ab0bf48dc4fd2b4c71efbda7e5ec40eade1a Mon Sep 17 00:00:00 2001 From: aitbc Date: Thu, 7 May 2026 11:53:37 +0200 Subject: [PATCH] Add Priority 1 structural improvements to training curriculum Schema enhancements: - Add requires_balance_check property for operations with wallet+password - Add requires_currency property for operations with amount/price parameters - Add creates_resource property for operations that create IDs - Add requires_resource property for operations that require IDs Validation script: - Create validate_stage_dependencies.py to check: - Operations with wallet+password have wallet_balance check before them - Operations with amount/price parameters have currency field - Operations requiring resources have corresponding create operations Stage fixes: - Stage 2: Add wallet_balance check at beginning, add currency to wallet_send and staking_stake - Stage 3: Add wallet_balance check at beginning, add market_gpu_register for listing_id dependency - Update RESOURCE_CREATORS to handle multiple resources per operation - Add multi_chain_island_setup as island_id creator for Stage 9 --- .../stage2_operations_mastery.json | 16 ++ docs/agent-training/stage3_ai_operations.json | 32 +++ docs/agent-training/training_schema.json | 20 ++ .../validate_stage_dependencies.py | 199 ++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100755 docs/agent-training/validate_stage_dependencies.py diff --git a/docs/agent-training/stage2_operations_mastery.json b/docs/agent-training/stage2_operations_mastery.json index 82481d6c..3ad518e6 100644 --- a/docs/agent-training/stage2_operations_mastery.json +++ b/docs/agent-training/stage2_operations_mastery.json @@ -46,6 +46,20 @@ ] }, "operations": [ + { + "operation": "wallet_balance", + "parameters": { + "wallet": "training-wallet" + }, + "expected_result": { + "status": "success", + "balance": ">0" + }, + "success_criteria": { + "status": "success", + "response_fields": ["balance", "symbol"] + } + }, { "operation": "wallet_export", "parameters": { @@ -82,6 +96,7 @@ "wallet": "training-wallet", "to": "recipient-address", "amount": "10", + "currency": "AIT", "password": "training123" }, "expected_result": { @@ -284,6 +299,7 @@ "parameters": { "wallet": "training-wallet", "amount": "100", + "currency": "AIT", "password": "training123" }, "expected_result": { diff --git a/docs/agent-training/stage3_ai_operations.json b/docs/agent-training/stage3_ai_operations.json index 7227caff..2623490e 100644 --- a/docs/agent-training/stage3_ai_operations.json +++ b/docs/agent-training/stage3_ai_operations.json @@ -29,6 +29,38 @@ ], "training_data": { "operations": [ + { + "operation": "wallet_balance", + "parameters": { + "wallet": "training-wallet" + }, + "expected_result": { + "status": "success", + "balance": ">0" + }, + "success_criteria": { + "status": "success", + "response_fields": ["balance", "symbol"] + } + }, + { + "operation": "market_gpu_register", + "parameters": { + "wallet": "training-wallet", + "gpu_model": "RTX4090", + "price": "0.5", + "currency": "AIT", + "password": "training123" + }, + "expected_result": { + "status": "success", + "gpu_id": "gpu_*" + }, + "success_criteria": { + "status": "success", + "response_fields": ["gpu_id", "listing_id"] + } + }, { "operation": "ai_training_agent", "parameters": { diff --git a/docs/agent-training/training_schema.json b/docs/agent-training/training_schema.json index e82a7922..dcdc99a0 100644 --- a/docs/agent-training/training_schema.json +++ b/docs/agent-training/training_schema.json @@ -207,6 +207,26 @@ "url": {"type": "string"} } } + }, + "requires_balance_check": { + "type": "boolean", + "description": "Whether this operation requires a wallet_balance check before execution. Automatically set to true for operations with wallet and password parameters.", + "default": false + }, + "requires_currency": { + "type": "boolean", + "description": "Whether this operation requires a currency field in parameters. Automatically set to true for operations with amount, price, bounty_amount, or stake_amount parameters.", + "default": false + }, + "creates_resource": { + "type": "string", + "description": "Type of resource created by this operation (e.g., agent_id, dispute_id, enterprise_id, proposal_id, island_id). Used for dependency validation.", + "enum": ["agent_id", "dispute_id", "enterprise_id", "proposal_id", "island_id", "workflow_id", "gpu_id", "listing_id", "job_id", "bounty_id", "mm_id", "fl_id", "swarm_id", "validator_id", "bridge_tx_id", "transfer_id", "deployment_id", "pubsub_config_id", "sync_config_id"] + }, + "requires_resource": { + "type": "string", + "description": "Type of resource required by this operation (e.g., agent_id, dispute_id, enterprise_id). Used for dependency validation to ensure create operation exists.", + "enum": ["agent_id", "dispute_id", "enterprise_id", "proposal_id", "island_id", "workflow_id", "gpu_id", "listing_id", "job_id", "bounty_id", "mm_id", "fl_id", "swarm_id", "validator_id", "bridge_tx_id", "transfer_id", "deployment_id", "pubsub_config_id", "sync_config_id"] } } } diff --git a/docs/agent-training/validate_stage_dependencies.py b/docs/agent-training/validate_stage_dependencies.py new file mode 100755 index 00000000..55606258 --- /dev/null +++ b/docs/agent-training/validate_stage_dependencies.py @@ -0,0 +1,199 @@ +#!/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_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()