Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Term Challenge is a WASM evaluation module for AI agents on the Bittensor networ

```
term-challenge/
├── Cargo.toml # workspace with members = [".", "wasm", "cli", "server", "storage"]
├── Cargo.toml # workspace with members = [".", "wasm", "cli", "lib", "server", "storage"]
├── src/
│ ├── lib.rs # Root library crate entry point
│ └── dataset/
Expand All @@ -29,6 +29,20 @@ term-challenge/
│ ├── llm_review.rs # LLM-based code review, reviewer selection, aggregation
│ ├── submission.rs # Named submission registry and version tracking
│ └── timeout_handler.rs # Review assignment timeout tracking and replacement
├── lib/
│ ├── Cargo.toml # native library, depends on platform-core & platform-challenge-sdk
│ └── src/
│ ├── lib.rs # Module declarations, re-exports dataset/ChallengeId/Hotkey
│ ├── dataset.rs # Validator-side dataset management types
│ ├── synthetic/mod.rs # Synthetic task generation
│ ├── validation/mod.rs # Validation result types
│ ├── admin/mod.rs # Admin action types
│ ├── util/mod.rs # Utility module
│ ├── util/hotkey.rs # Hotkey parsing helpers (wraps platform_core::Hotkey)
│ ├── cache/mod.rs # Score caching layer
│ ├── chain/mod.rs # Chain submission types
│ ├── worker/mod.rs # Worker job processing types
│ └── bin/term-sudo.rs # Admin CLI binary
├── server/
│ ├── Cargo.toml # lib + bin, depends on platform-challenge-sdk (server mode)
│ └── src/
Expand Down Expand Up @@ -170,6 +184,9 @@ The `term-cli` crate is a **native binary** (NOT `no_std`) that provides a termi
## Build Commands

```bash
# Build library (native)
cargo build --release -p term-challenge-lib

# Build CLI (native)
cargo build --release -p term-cli

Expand Down Expand Up @@ -205,7 +222,7 @@ Git hooks live in `.githooks/` and are activated with `git config core.hooksPath
5. **Host functions are the ONLY external interface.** No direct HTTP, no filesystem, no std::net.
6. **Do NOT add `#[allow(dead_code)]` broadly.** Fix unused code or remove it.

> **Note:** The `cli/`, `server/`, and `storage/` crates are exempt from the `no_std` rule (rule 1) and the host-functions-only rule (rule 5) since they are native code that runs outside the WASM sandbox. Rules 2, 3, 4, and 6 still apply to all.
> **Note:** The `cli/`, `core/`, `lib/`, `server/`, and `storage/` crates are exempt from the `no_std` rule (rule 1) and the host-functions-only rule (rule 5) since they are native code that runs outside the WASM sandbox. Rules 2, 3, 4, and 6 still apply to all crates.

## DO / DO NOT

Expand Down
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = [".", "wasm", "cli", "core", "server", "storage"]
members = [".", "wasm", "cli", "core", "lib", "server", "storage"]
default-members = ["wasm"]

[workspace.package]
Expand All @@ -19,6 +19,9 @@ bincode = "1.3"
aes-gcm = "0.10"
parity-scale-codec = { version = "3.7.5", features = ["derive"] }

[patch.crates-io]
w3f-bls = { git = "https://github.com/opentensor/bls", branch = "fix-no-std" }

[package]
name = "term-challenge"
version.workspace = true
Expand Down
24 changes: 24 additions & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "term-challenge-lib"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
description = "Terminal Benchmark Challenge — validator-side library"

[lib]
name = "term_challenge_lib"
path = "src/lib.rs"

[[bin]]
name = "term-sudo"
path = "src/bin/term-sudo.rs"

[dependencies]
platform-core = { workspace = true }
platform-challenge-sdk = { workspace = true }

serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
clap = { version = "4.5", features = ["derive"] }

11 changes: 11 additions & 0 deletions lib/src/admin/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use platform_challenge_sdk::ChallengeId;
use platform_core::Hotkey;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AdminAction {
pub challenge_id: ChallengeId,
pub issuer: Hotkey,
pub action: String,
pub payload: serde_json::Value,
}
51 changes: 51 additions & 0 deletions lib/src/bin/term-sudo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use clap::Parser;
use term_challenge_lib::{ChallengeId, Hotkey};

#[derive(Parser)]
#[command(name = "term-sudo", about = "Term Challenge admin CLI")]
struct Cli {
#[arg(long)]
challenge_id: String,

#[arg(long)]
hotkey: String,

#[command(subcommand)]
command: Command,
}

#[derive(clap::Subcommand)]
enum Command {
Status,
ResetEpoch {
#[arg(long)]
epoch: u64,
},
}

fn main() {
let cli = Cli::parse();

let challenge_id = ChallengeId::from_str(&cli.challenge_id).unwrap_or_else(|| {
eprintln!("Invalid challenge ID: {}", cli.challenge_id);
std::process::exit(1);
});

let hotkey = Hotkey::from_ss58(&cli.hotkey).unwrap_or_else(|| {
eprintln!("Invalid SS58 hotkey: {}", cli.hotkey);
std::process::exit(1);
});

match cli.command {
Command::Status => {
println!("Challenge: {}", challenge_id);
println!("Hotkey: {:?}", hotkey);
println!("Status: OK");
}
Command::ResetEpoch { epoch } => {
println!("Challenge: {}", challenge_id);
println!("Hotkey: {:?}", hotkey);
println!("Reset epoch: {}", epoch);
}
}
}
29 changes: 29 additions & 0 deletions lib/src/cache/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use platform_challenge_sdk::ChallengeId;
use platform_core::Hotkey;
use std::collections::HashMap;

pub struct ScoreCache {
scores: HashMap<(ChallengeId, Hotkey), f64>,
}

impl ScoreCache {
pub fn new() -> Self {
Self {
scores: HashMap::new(),
}
}

pub fn get(&self, challenge_id: &ChallengeId, hotkey: &Hotkey) -> Option<f64> {
self.scores.get(&(*challenge_id, hotkey.clone())).copied()
}

pub fn insert(&mut self, challenge_id: ChallengeId, hotkey: Hotkey, score: f64) {
self.scores.insert((challenge_id, hotkey), score);
}
}

impl Default for ScoreCache {
fn default() -> Self {
Self::new()
}
}
12 changes: 12 additions & 0 deletions lib/src/chain/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use platform_challenge_sdk::ChallengeId;
use platform_core::Hotkey;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChainSubmission {
pub challenge_id: ChallengeId,
pub miner: Hotkey,
pub agent_hash: String,
pub epoch: u64,
pub score: f64,
}
21 changes: 21 additions & 0 deletions lib/src/dataset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use platform_challenge_sdk::ChallengeId;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DatasetEntry {
pub challenge_id: ChallengeId,
pub task_ids: Vec<String>,
pub selected_at_epoch: u64,
pub dataset_hash: String,
}

impl DatasetEntry {
pub fn new(challenge_id: ChallengeId, task_ids: Vec<String>, epoch: u64, hash: String) -> Self {
Self {
challenge_id,
task_ids,
selected_at_epoch: epoch,
dataset_hash: hash,
}
}
}
14 changes: 14 additions & 0 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub mod dataset;

pub mod admin;
pub mod cache;
pub mod chain;
pub mod synthetic;
pub mod util;
pub mod validation;
pub mod worker;

pub use dataset::DatasetEntry;

pub use platform_challenge_sdk::ChallengeId;
pub use platform_core::Hotkey;
11 changes: 11 additions & 0 deletions lib/src/synthetic/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use platform_challenge_sdk::ChallengeId;
use platform_core::Hotkey;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SyntheticTask {
pub challenge_id: ChallengeId,
pub owner: Hotkey,
pub task_data: Vec<u8>,
pub created_epoch: u64,
}
5 changes: 5 additions & 0 deletions lib/src/util/hotkey.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use platform_core::Hotkey;

pub fn parse_hotkey(ss58: &str) -> Option<Hotkey> {
Hotkey::from_ss58(ss58)
}
3 changes: 3 additions & 0 deletions lib/src/util/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod hotkey;

pub use hotkey::parse_hotkey;
11 changes: 11 additions & 0 deletions lib/src/validation/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use platform_challenge_sdk::ChallengeId;
use platform_core::Hotkey;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ValidationResult {
pub challenge_id: ChallengeId,
pub validator: Hotkey,
pub is_valid: bool,
pub reason: Option<String>,
}
20 changes: 20 additions & 0 deletions lib/src/worker/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use platform_challenge_sdk::ChallengeId;
use platform_core::Hotkey;
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct WorkerJob {
pub challenge_id: ChallengeId,
pub assigned_validator: Hotkey,
pub agent_hash: String,
pub epoch: u64,
pub status: WorkerJobStatus,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum WorkerJobStatus {
Queued,
Running,
Completed,
Failed,
}
2 changes: 1 addition & 1 deletion server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ name = "term-challenge-server"
path = "src/main.rs"

[dependencies]
platform-challenge-sdk = { git = "https://github.com/PlatformNetwork/platform-v2", branch = "main", features = ["http-server"] }
platform-challenge-sdk = { workspace = true }

axum = { version = "0.7", features = ["json"] }
tokio = { version = "1.40", features = ["full"] }
Expand Down
4 changes: 2 additions & 2 deletions storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ license.workspace = true
description = "Storage layer for Term Challenge using platform SDK types"

[dependencies]
platform-core = { git = "https://github.com/PlatformNetwork/platform-v2", branch = "main" }
platform-challenge-sdk = { git = "https://github.com/PlatformNetwork/platform-v2", branch = "main" }
platform-core = { workspace = true }
platform-challenge-sdk = { workspace = true }

tokio = { version = "1.40", features = ["full"] }
tokio-postgres = { version = "0.7", features = ["with-uuid-1", "with-chrono-0_4", "with-serde_json-1"] }
Expand Down