Skip to main content

agentics_domain/models/challenge_creation/
manifest.rs

1//! Public challenge creation manifest models.
2
3use serde::{Deserialize, Serialize};
4
5use crate::models::localization::LocalizedText;
6use crate::models::names::{ChallengeKeyword, ChallengeName};
7use crate::models::paths::RepoRelativePath;
8
9use super::private_assets::ChallengePrivateAssetRequirement;
10
11/// Public challenge manifest file expected at the root of a challenge proposal.
12pub const AGENTICS_CHALLENGE_MANIFEST_FILE: &str = "agentics.challenge.json";
13
14/// Public manifest submitted through the reviewed challenge repository.
15#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
16#[serde(deny_unknown_fields)]
17pub struct ChallengeCreationManifest {
18    pub schema_version: i32,
19    pub request: ChallengeCreationRequestKind,
20    pub challenge_name: ChallengeName,
21    pub title: String,
22    pub summary: LocalizedText,
23    #[schemars(length(min = 1, max = 6))]
24    pub keywords: Vec<ChallengeKeyword>,
25    pub readme_path: RepoRelativePath,
26    #[serde(default, skip_serializing_if = "Option::is_none")]
27    pub bundle_path: Option<RepoRelativePath>,
28    #[serde(default, skip_serializing_if = "Option::is_none")]
29    pub archive: Option<ChallengeArchiveRequestSpec>,
30    #[serde(default)]
31    pub private_assets: Vec<ChallengePrivateAssetRequirement>,
32    #[serde(default)]
33    pub ci: ChallengeCreationCiSpec,
34}
35
36/// Lifecycle request represented by a public manifest.
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
38#[serde(rename_all = "snake_case")]
39pub enum ChallengeCreationRequestKind {
40    NewChallenge,
41    ArchiveChallenge,
42}
43
44impl ChallengeCreationRequestKind {
45    /// Stable database string for this creation request.
46    pub fn as_str(self) -> &'static str {
47        match self {
48            Self::NewChallenge => "new_challenge",
49            Self::ArchiveChallenge => "archive_challenge",
50        }
51    }
52
53    /// Parse a stable database string for this creation request.
54    pub fn from_storage_value(value: &str) -> Option<Self> {
55        match value {
56            "new_challenge" => Some(Self::NewChallenge),
57            "archive_challenge" => Some(Self::ArchiveChallenge),
58            _ => None,
59        }
60    }
61}
62
63/// Public archive request metadata.
64#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
65#[serde(deny_unknown_fields)]
66pub struct ChallengeArchiveRequestSpec {
67    pub reason: String,
68}
69
70/// CI expectations for the public challenge repository.
71#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
72#[serde(deny_unknown_fields)]
73pub struct ChallengeCreationCiSpec {
74    #[serde(default = "default_required")]
75    pub validate_manifest: bool,
76    #[serde(default = "default_required")]
77    pub validate_public_bundle: bool,
78    #[serde(default)]
79    pub smoke_test_public_validation: bool,
80}
81
82impl Default for ChallengeCreationCiSpec {
83    /// Handles default for this module.
84    fn default() -> Self {
85        Self {
86            validate_manifest: true,
87            validate_public_bundle: true,
88            smoke_test_public_validation: false,
89        }
90    }
91}
92
93/// Handles default required for this module.
94fn default_required() -> bool {
95    true
96}