diff --git a/README.md b/README.md index 4d7e8ced..5d01512f 100644 --- a/README.md +++ b/README.md @@ -48,16 +48,21 @@ aitbc/ │ └── zk-circuits/ # ZK proof circuits (Circom) ├── cli/ # CLI tools (12 command groups, 90+ subcommands) ├── contracts/ # Solidity smart contracts -├── docs/ # Documentation (structure, guides, reference, reports) +├── docs/ # Documentation (10 numbered sections) ├── extensions/ # Browser extensions (Firefox wallet) -├── home/ # Local simulation scripts ├── infra/ # Infrastructure (nginx, k8s, helm, terraform) ├── packages/ # Shared libraries │ ├── py/aitbc-crypto/ # Cryptographic primitives │ ├── py/aitbc-sdk/ # Python SDK │ └── solidity/aitbc-token/# ERC-20 token contract ├── plugins/ollama/ # Ollama LLM integration -├── scripts/ # Deployment, GPU, service, and test scripts +├── scripts/ # All scripts, organized by purpose +│ ├── blockchain/ # Genesis, proposer, mock chain +│ ├── ci/ # CI/CD pipeline +│ ├── dev/ # Dev tools, local services +│ ├── examples/ # Usage examples and simulations +│ ├── ops/ # Coordinator proxy, tunnels +│ └── test/ # Integration and verification ├── systemd/ # Systemd service units ├── tests/ # Test suites (unit, integration, e2e, security, CLI) └── website/ # Public website and HTML documentation diff --git a/docs/6_architecture/8_codebase-structure.md b/docs/6_architecture/8_codebase-structure.md index ec49f8b5..ff75de63 100644 --- a/docs/6_architecture/8_codebase-structure.md +++ b/docs/6_architecture/8_codebase-structure.md @@ -10,17 +10,21 @@ aitbc/ ├── assets/ # Shared frontend assets (CSS, JS, fonts) ├── cli/ # Command-line interface tools ├── contracts/ # Solidity smart contracts (standalone) -├── dev-utils/ # Developer utilities and path configs -├── docs/ # Markdown documentation -├── examples/ # Usage examples and demos +├── docs/ # Markdown documentation (10 numbered sections) ├── extensions/ # Browser extensions (Firefox wallet) -├── home/ # Local workflow scripts (client/miner simulation) ├── infra/ # Infrastructure configs (nginx, k8s, terraform, helm) ├── packages/ # Shared libraries and SDKs ├── plugins/ # Plugin integrations (Ollama) -├── protocols/ # Protocol specs and sample data -├── scripts/ # Operational and deployment scripts -├── src/ # Shared Python source (cross-site sync, RPC) +├── scripts/ # All scripts, organized by purpose +│ ├── blockchain/ # Genesis, proposer, mock chain, testnet +│ ├── ci/ # CI/CD pipeline scripts +│ ├── deploy/ # Container and service deployment (gitignored) +│ ├── dev/ # Dev tools, local services, OpenAPI gen +│ ├── examples/ # Usage examples and simulation scripts +│ ├── gpu/ # GPU miner setup and management (gitignored) +│ ├── ops/ # Coordinator proxy, remote tunnel +│ ├── service/ # Service management (gitignored) +│ └── test/ # Integration and verification scripts ├── systemd/ # Systemd service unit files ├── tests/ # Pytest test suites (unit, integration, e2e, security, load) ├── website/ # Public-facing website and HTML documentation @@ -257,12 +261,8 @@ website/ |-----------|---------| | `cli/` | AITBC CLI package (12 command groups, 90+ subcommands, 141 unit + 24 integration tests, CI/CD, man page, plugins) | | `plugins/ollama/` | Ollama LLM integration (client plugin, miner plugin, service layer) | -| `home/` | Local simulation scripts for client/miner workflows | | `extensions/` | Firefox wallet extension source code | | `contracts/` | Standalone Solidity contracts (ZKReceiptVerifier) | -| `protocols/` | Protocol sample data (signed receipts) | -| `src/` | Shared Python modules (cross-site sync, RPC router) | | `systemd/` | Systemd unit files for all AITBC services | -| `dev-utils/` | Developer utilities (Python path config) | -| `docs/` | Markdown documentation (guides, reports, reference, tutorials, operator docs) | +| `docs/` | Markdown documentation (10 numbered sections, guides, reference, architecture) | | `assets/` | Shared frontend assets (Tailwind CSS, FontAwesome, Lucide icons, Axios) | diff --git a/home/test_ollama_blockchain.py b/home/test_ollama_blockchain.py deleted file mode 100755 index 9424400a..00000000 --- a/home/test_ollama_blockchain.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/env python3 -""" -Ollama GPU Provider Test with Blockchain Verification using Home Directory Users -Tests the complete flow: Client -> Coordinator -> GPU Miner -> Receipt -> Blockchain -""" - -import os -import sys -import subprocess -import time -import json -from typing import Optional - -import httpx - -# Add parent directories to path -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'cli')) - -# Configuration -DEFAULT_COORDINATOR = "http://127.0.0.1:18000" -DEFAULT_BLOCKCHAIN = "http://aitbc.keisanki.net/rpc" -DEFAULT_PROMPT = "What is the capital of France?" -DEFAULT_MODEL = "llama3.2:latest" -DEFAULT_TIMEOUT = 180 -POLL_INTERVAL = 3 - - -def get_wallet_balance(wallet_dir: str) -> float: - """Get wallet balance from home directory wallet""" - result = subprocess.run( - f'cd {wallet_dir} && python3 wallet.py balance', - shell=True, - capture_output=True, - text=True - ) - if result.returncode == 0: - for line in result.stdout.split('\n'): - if 'Balance:' in line: - # Extract the value after "Balance:" - balance_part = line.split('Balance:')[1].strip() - balance_value = balance_part.split()[0] # Get the numeric part before "AITBC" - try: - return float(balance_value) - except ValueError: - continue - return 0.0 - - -def get_wallet_address(wallet_dir: str) -> Optional[str]: - """Get wallet address from home directory wallet""" - result = subprocess.run( - f'cd {wallet_dir} && python3 wallet.py address', - shell=True, - capture_output=True, - text=True - ) - if result.returncode == 0: - for line in result.stdout.split('\n'): - if 'Address:' in line: - return line.split()[-1] - return None - - -def submit_job_via_client(prompt: str, model: str) -> Optional[str]: - """Submit job using the CLI client""" - cmd = f'cd ../cli && python3 client.py submit inference --prompt "{prompt}" --model {model}' - result = subprocess.run( - cmd, - shell=True, - capture_output=True, - text=True - ) - - if result.returncode != 0: - print(f"❌ Job submission failed: {result.stderr}") - return None - - # Extract job ID - for line in result.stdout.split('\n'): - if "Job ID:" in line: - return line.split()[-1] - return None - - -def get_job_status(job_id: str) -> Optional[str]: - """Get job status using CLI client""" - result = subprocess.run( - f'cd ../cli && python3 client.py status {job_id}', - shell=True, - capture_output=True, - text=True - ) - - if result.returncode != 0: - return None - - # Extract state - for line in result.stdout.split('\n'): - if "State:" in line: - return line.split()[-1] - return None - - -def get_job_result(job_id: str) -> Optional[dict]: - """Get job result via API""" - with httpx.Client() as client: - response = client.get( - f"{DEFAULT_COORDINATOR}/v1/jobs/{job_id}/result", - headers={"X-Api-Key": "${CLIENT_API_KEY}"}, - timeout=10, - ) - if response.status_code == 200: - return response.json() - return None - - -def check_blockchain_transaction(receipt_id: str) -> Optional[dict]: - """Check if receipt is recorded on blockchain""" - try: - with httpx.Client() as client: - # Try to get recent transactions - response = client.get( - f"{DEFAULT_BLOCKCHAIN}/transactions", - timeout=10, - ) - if response.status_code == 200: - data = response.json() - transactions = data.get("transactions", data.get("items", [])) - # Look for matching receipt - for tx in transactions: - payload = tx.get("payload", {}) - if payload.get("receipt_id") == receipt_id: - return tx - return None - except httpx.ConnectError: - print(f"⚠️ Blockchain node not available at {DEFAULT_BLOCKCHAIN}") - return None - except Exception as e: - print(f"⚠️ Error checking blockchain: {e}") - return None - - -def main(): - print("🚀 Ollama GPU Provider Test with Home Directory Users") - print("=" * 60) - - # Get initial balances - print("\n💰 Initial Wallet Balances:") - print("-" * 40) - - client_balance = get_wallet_balance("client") - miner_balance = get_wallet_balance("miner") - - print(f" Client: {client_balance} AITBC") - print(f" Miner: {miner_balance} AITBC") - - # Submit job - print(f"\n📤 Submitting Inference Job:") - print("-" * 40) - print(f" Prompt: {DEFAULT_PROMPT}") - print(f" Model: {DEFAULT_MODEL}") - - job_id = submit_job_via_client(DEFAULT_PROMPT, DEFAULT_MODEL) - if not job_id: - print("❌ Failed to submit job") - return 1 - - print(f"✅ Job submitted: {job_id}") - - # Monitor job progress - print(f"\n⏳ Monitoring Job Progress:") - print("-" * 40) - - deadline = time.time() + DEFAULT_TIMEOUT - - while time.time() < deadline: - state = get_job_status(job_id) - if not state: - print(" ⚠️ Could not fetch status") - time.sleep(POLL_INTERVAL) - continue - - print(f" State: {state}") - - if state == "COMPLETED": - break - elif state in {"FAILED", "CANCELED", "EXPIRED"}: - print(f"❌ Job ended in state: {state}") - return 1 - - time.sleep(POLL_INTERVAL) - - if state != "COMPLETED": - print("❌ Job did not complete within timeout") - return 1 - - # Get job result - print(f"\n📊 Job Result:") - print("-" * 40) - - result = get_job_result(job_id) - if result: - output = result.get("result", {}).get("output", "No output") - receipt = result.get("receipt") - - print(f" Output: {output[:200]}{'...' if len(output) > 200 else ''}") - - if receipt: - print(f"\n🧾 Receipt Information:") - print(f" Receipt ID: {receipt.get('receipt_id')}") - print(f" Provider: {receipt.get('provider')}") - print(f" Units: {receipt.get('units')} {receipt.get('unit_type', 'seconds')}") - print(f" Unit Price: {receipt.get('unit_price')} AITBC") - print(f" Total Price: {receipt.get('price')} AITBC") - - # Check blockchain - print(f"\n⛓️ Checking Blockchain:") - print("-" * 40) - - tx = check_blockchain_transaction(receipt.get('receipt_id')) - if tx: - print(f"✅ Transaction found on blockchain!") - print(f" TX Hash: {tx.get('tx_hash')}") - print(f" Block: {tx.get('block_height')}") - print(f" From: {tx.get('sender')}") - print(f" To: {tx.get('recipient')}") - print(f" Amount: {tx.get('amount')} AITBC") - else: - print(f"⚠️ Transaction not yet found on blockchain") - print(f" (May take a few moments to be mined)") - else: - print(f"⚠️ No receipt generated") - else: - print(" Could not fetch result") - - # Show final balances - print(f"\n💰 Final Wallet Balances:") - print("-" * 40) - - client_balance = get_wallet_balance("client") - miner_balance = get_wallet_balance("miner") - - print(f" Client: {client_balance} AITBC") - print(f" Miner: {miner_balance} AITBC") - - # Calculate difference - client_diff = client_balance - get_wallet_balance("client") - print(f"\n📈 Transaction Summary:") - print("-" * 40) - print(f" Client spent: {abs(client_diff):.4f} AITBC") - print(f" Miner earned: {abs(client_diff):.4f} AITBC") - - print(f"\n✅ Test completed successfully!") - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/protocols/receipts/samples/sample_receipt_signed.json b/protocols/receipts/samples/sample_receipt_signed.json deleted file mode 100644 index 89ae9d07..00000000 --- a/protocols/receipts/samples/sample_receipt_signed.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "private_key_hex": "e2c35a46318ec09cf1cc04f06c4ba18bf2cd3f0ed318d986f01228bdbf9fd326", - "verify_key_hex": "4c9bc7d00f69924d1cdee40c3650a2bcbb37191de2d53d93b5f21b2d3d27dbd4", - "payload": { - "version": "1.0", - "receipt_id": "rcpt-20250926-000123", - "job_id": "job-abc123", - "provider": "ait1minerxyz...", - "client": "ait1clientabc...", - "units": 1.9, - "unit_type": "gpu_seconds", - "price": 4.2, - "model": "runwayml/stable-diffusion-v1-5", - "prompt_hash": "sha256:cf1f...", - "started_at": 1695720000, - "completed_at": 1695720002, - "artifact_hash": "sha256:deadbeef...", - "coordinator_id": "coord-eu-west-1", - "nonce": "b7f3d10b", - "chain_id": 12345 - }, - "canonical": "{\"artifact_hash\":\"sha256:deadbeef...\",\"chain_id\":12345,\"client\":\"ait1clientabc...\",\"completed_at\":1695720002,\"coordinator_id\":\"coord-eu-west-1\",\"job_id\":\"job-abc123\",\"model\":\"runwayml/stable-diffusion-v1-5\",\"nonce\":\"b7f3d10b\",\"price\":4.2,\"prompt_hash\":\"sha256:cf1f...\",\"provider\":\"ait1minerxyz...\",\"receipt_id\":\"rcpt-20250926-000123\",\"started_at\":1695720000,\"unit_type\":\"gpu_seconds\",\"units\":1.9,\"version\":\"1.0\"}", - "signature": { - "alg": "Ed25519", - "key_id": "TJvH0A9pkk0c3uQMNlCivLs3GR3i1T2TtfIbLT0n29Q", - "sig": "fSmokpSz5-qf0XwwuBOBNseIONRM3Y6Bmrko4oE6mY0nS_noq_3zQ9y87Cd3IkMct3S5Ve-URC7D8TVBiBkvAg" - } -} \ No newline at end of file diff --git a/scripts/apply_bootstrap_genesis.sh b/scripts/blockchain/apply_bootstrap_genesis.sh similarity index 100% rename from scripts/apply_bootstrap_genesis.sh rename to scripts/blockchain/apply_bootstrap_genesis.sh diff --git a/scripts/assign_proposer.py b/scripts/blockchain/assign_proposer.py similarity index 100% rename from scripts/assign_proposer.py rename to scripts/blockchain/assign_proposer.py diff --git a/scripts/return_testnet_btc.sh b/scripts/blockchain/return_testnet_btc.sh similarity index 100% rename from scripts/return_testnet_btc.sh rename to scripts/blockchain/return_testnet_btc.sh diff --git a/scripts/start_mock_blockchain.sh b/scripts/blockchain/start_mock_blockchain.sh similarity index 100% rename from scripts/start_mock_blockchain.sh rename to scripts/blockchain/start_mock_blockchain.sh diff --git a/scripts/aitbc-cli.sh b/scripts/dev/aitbc-cli.sh similarity index 100% rename from scripts/aitbc-cli.sh rename to scripts/dev/aitbc-cli.sh diff --git a/dev-utils/aitbc-pythonpath.pth b/scripts/dev/aitbc-pythonpath.pth similarity index 100% rename from dev-utils/aitbc-pythonpath.pth rename to scripts/dev/aitbc-pythonpath.pth diff --git a/dev-utils/README.md b/scripts/dev/dev-utils-README.md similarity index 100% rename from dev-utils/README.md rename to scripts/dev/dev-utils-README.md diff --git a/scripts/dev_services.sh b/scripts/dev/dev_services.sh similarity index 100% rename from scripts/dev_services.sh rename to scripts/dev/dev_services.sh diff --git a/scripts/exchange-router-fixed.py b/scripts/dev/exchange-router-fixed.py similarity index 100% rename from scripts/exchange-router-fixed.py rename to scripts/dev/exchange-router-fixed.py diff --git a/scripts/generate_openapi.py b/scripts/dev/generate_openapi.py similarity index 100% rename from scripts/generate_openapi.py rename to scripts/dev/generate_openapi.py diff --git a/scripts/local-domain-proxy.py b/scripts/dev/local-domain-proxy.py similarity index 100% rename from scripts/local-domain-proxy.py rename to scripts/dev/local-domain-proxy.py diff --git a/scripts/manage_services.sh b/scripts/dev/manage_services.sh similarity index 100% rename from scripts/manage_services.sh rename to scripts/dev/manage_services.sh diff --git a/scripts/setup_systemd.sh b/scripts/dev/setup_systemd.sh similarity index 100% rename from scripts/setup_systemd.sh rename to scripts/dev/setup_systemd.sh diff --git a/home/README.md b/scripts/examples/README.md similarity index 100% rename from home/README.md rename to scripts/examples/README.md diff --git a/home/client_get_result.py b/scripts/examples/client_get_result.py similarity index 100% rename from home/client_get_result.py rename to scripts/examples/client_get_result.py diff --git a/home/client_send_job.py b/scripts/examples/client_send_job.py similarity index 100% rename from home/client_send_job.py rename to scripts/examples/client_send_job.py diff --git a/home/client/wallet.py b/scripts/examples/client_wallet.py similarity index 100% rename from home/client/wallet.py rename to scripts/examples/client_wallet.py diff --git a/home/enhanced_client.py b/scripts/examples/enhanced_client.py similarity index 100% rename from home/enhanced_client.py rename to scripts/examples/enhanced_client.py diff --git a/docs/8_development/example_client_remote.py b/scripts/examples/example_client_remote.py similarity index 100% rename from docs/8_development/example_client_remote.py rename to scripts/examples/example_client_remote.py diff --git a/home/genesis.py b/scripts/examples/genesis.py similarity index 100% rename from home/genesis.py rename to scripts/examples/genesis.py diff --git a/home/how_customer_gets_reply.py b/scripts/examples/how_customer_gets_reply.py similarity index 100% rename from home/how_customer_gets_reply.py rename to scripts/examples/how_customer_gets_reply.py diff --git a/home/miner/wallet.py b/scripts/examples/miner_wallet.py similarity index 100% rename from home/miner/wallet.py rename to scripts/examples/miner_wallet.py diff --git a/home/quick_job.py b/scripts/examples/quick_job.py similarity index 100% rename from home/quick_job.py rename to scripts/examples/quick_job.py diff --git a/home/simple_job_flow.py b/scripts/examples/simple_job_flow.py similarity index 100% rename from home/simple_job_flow.py rename to scripts/examples/simple_job_flow.py diff --git a/home/simulate.py b/scripts/examples/simulate.py similarity index 100% rename from home/simulate.py rename to scripts/examples/simulate.py diff --git a/home/wallet.py b/scripts/examples/wallet.py similarity index 100% rename from home/wallet.py rename to scripts/examples/wallet.py diff --git a/scripts/miner_workflow.py b/scripts/miner_workflow.py deleted file mode 100644 index 45376f20..00000000 --- a/scripts/miner_workflow.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python3 -""" -Complete miner workflow - poll for jobs and assign proposer -""" - -import httpx -import json -import time -from datetime import datetime - -# Configuration -COORDINATOR_URL = "http://localhost:8001" -MINER_API_KEY = "${MINER_API_KEY}" -MINER_ID = "localhost-gpu-miner" - -def poll_and_accept_job(): - """Poll for a job and accept it""" - print("🔍 Polling for jobs...") - - with httpx.Client() as client: - # Poll for a job - response = client.post( - f"{COORDINATOR_URL}/v1/miners/poll", - headers={ - "Content-Type": "application/json", - "X-Api-Key": MINER_API_KEY - }, - json={"max_wait_seconds": 5} - ) - - if response.status_code == 200: - job = response.json() - print(f"✅ Received job: {job['job_id']}") - print(f" Task: {job['payload'].get('task', 'unknown')}") - - # Simulate processing - print("⚙️ Processing job...") - time.sleep(2) - - # Submit result - result_data = { - "result": { - "status": "completed", - "output": f"Job {job['job_id']} completed successfully", - "execution_time_ms": 2000, - "miner_id": MINER_ID - }, - "metrics": { - "compute_time": 2.0, - "energy_used": 0.1 - } - } - - print(f"📤 Submitting result for job {job['job_id']}...") - result_response = client.post( - f"{COORDINATOR_URL}/v1/miners/{job['job_id']}/result", - headers={ - "Content-Type": "application/json", - "X-Api-Key": MINER_API_KEY - }, - json=result_data - ) - - if result_response.status_code == 200: - print("✅ Result submitted successfully!") - return job['job_id'] - else: - print(f"❌ Failed to submit result: {result_response.status_code}") - print(f" Response: {result_response.text}") - return None - - elif response.status_code == 204: - print("ℹ️ No jobs available") - return None - else: - print(f"❌ Failed to poll: {response.status_code}") - return None - -def check_block_proposer(job_id): - """Check if the block now has a proposer""" - print(f"\n🔍 Checking proposer for job {job_id}...") - - with httpx.Client() as client: - response = client.get(f"{COORDINATOR_URL}/v1/explorer/blocks") - - if response.status_code == 200: - blocks = response.json() - for block in blocks['items']: - if block['hash'] == job_id: - print(f"📦 Block Info:") - print(f" Height: {block['height']}") - print(f" Hash: {block['hash']}") - print(f" Proposer: {block['proposer']}") - print(f" Time: {block['timestamp']}") - return block - return None - -def main(): - print("⛏️ AITBC Miner Workflow Demo") - print(f" Miner ID: {MINER_ID}") - print(f" Coordinator: {COORDINATOR_URL}") - print() - - # Poll and accept a job - job_id = poll_and_accept_job() - - if job_id: - # Check if the block has a proposer now - time.sleep(1) # Give the server a moment to update - check_block_proposer(job_id) - else: - print("\n💡 Tip: Create a job first using example_client_remote.py") - -if __name__ == "__main__": - main() diff --git a/scripts/check_coordinator_proxy.sh b/scripts/ops/check_coordinator_proxy.sh similarity index 100% rename from scripts/check_coordinator_proxy.sh rename to scripts/ops/check_coordinator_proxy.sh diff --git a/scripts/start_remote_tunnel.sh b/scripts/ops/start_remote_tunnel.sh similarity index 100% rename from scripts/start_remote_tunnel.sh rename to scripts/ops/start_remote_tunnel.sh diff --git a/scripts/testing/README.md b/scripts/test/README.md similarity index 100% rename from scripts/testing/README.md rename to scripts/test/README.md diff --git a/scripts/testing/register_test_clients.py b/scripts/test/register_test_clients.py similarity index 100% rename from scripts/testing/register_test_clients.py rename to scripts/test/register_test_clients.py diff --git a/scripts/testing/run_test_suite.py b/scripts/test/run_test_suite.py similarity index 100% rename from scripts/testing/run_test_suite.py rename to scripts/test/run_test_suite.py diff --git a/scripts/testing/run_tests.py b/scripts/test/run_tests.py similarity index 100% rename from scripts/testing/run_tests.py rename to scripts/test/run_tests.py diff --git a/scripts/testing/test_block_import.py b/scripts/test/test_block_import.py similarity index 100% rename from scripts/testing/test_block_import.py rename to scripts/test/test_block_import.py diff --git a/scripts/testing/test_block_import_complete.py b/scripts/test/test_block_import_complete.py similarity index 100% rename from scripts/testing/test_block_import_complete.py rename to scripts/test/test_block_import_complete.py diff --git a/scripts/testing/test_minimal.py b/scripts/test/test_minimal.py similarity index 100% rename from scripts/testing/test_minimal.py rename to scripts/test/test_minimal.py diff --git a/scripts/testing/test_model_validation.py b/scripts/test/test_model_validation.py similarity index 100% rename from scripts/testing/test_model_validation.py rename to scripts/test/test_model_validation.py diff --git a/scripts/testing/test_payment_integration.py b/scripts/test/test_payment_integration.py similarity index 100% rename from scripts/testing/test_payment_integration.py rename to scripts/test/test_payment_integration.py diff --git a/scripts/testing/test_payment_local.py b/scripts/test/test_payment_local.py similarity index 100% rename from scripts/testing/test_payment_local.py rename to scripts/test/test_payment_local.py diff --git a/scripts/testing/test_simple_import.py b/scripts/test/test_simple_import.py similarity index 100% rename from scripts/testing/test_simple_import.py rename to scripts/test/test_simple_import.py diff --git a/scripts/testing/test_tx_import.py b/scripts/test/test_tx_import.py similarity index 100% rename from scripts/testing/test_tx_import.py rename to scripts/test/test_tx_import.py diff --git a/scripts/testing/test_tx_model.py b/scripts/test/test_tx_model.py similarity index 100% rename from scripts/testing/test_tx_model.py rename to scripts/test/test_tx_model.py diff --git a/scripts/testing/verify_windsurf_tests.py b/scripts/test/verify_windsurf_tests.py similarity index 100% rename from scripts/testing/verify_windsurf_tests.py rename to scripts/test/verify_windsurf_tests.py