use hmd_core::{BlockDescriptor, MetadataField, MetadataFieldKind, ProfileDescriptor};
use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum EntryKind {
Research,
Plan,
Change,
Test,
Review,
Decision,
Blocker,
Handoff,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ProgressMeta {
pub id: String,
pub project: String,
pub status: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct EntryMeta {
pub id: String,
pub at: String,
pub actor: String,
pub kind: EntryKind,
pub summary: String,
pub corrects: Option<String>,
pub supersedes: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct ChangeMeta {
pub files: Vec<String>,
pub scope: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct TestMeta {
pub command: String,
pub result: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct BlockerMeta {
pub id: String,
pub severity: Option<String>,
pub owner: Option<String>,
pub status: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct NextMeta {
pub task: String,
pub priority: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ProgressProfileSchema {
pub progress: Option<ProgressMeta>,
pub entry: Option<EntryMeta>,
pub change: Option<ChangeMeta>,
pub test: Option<TestMeta>,
pub blocker: Option<BlockerMeta>,
pub next: Option<NextMeta>,
}
const ENTRY_KINDS: &[&str] = &[
"research", "plan", "change", "test", "review", "decision", "blocker", "handoff",
];
const PROGRESS_FIELDS: &[MetadataField] = &[
MetadataField::required("id", MetadataFieldKind::String),
MetadataField::required("project", MetadataFieldKind::String),
MetadataField::required("status", MetadataFieldKind::String),
];
const ENTRY_FIELDS: &[MetadataField] = &[
MetadataField::required("id", MetadataFieldKind::String),
MetadataField::required("at", MetadataFieldKind::String),
MetadataField::required("actor", MetadataFieldKind::String),
MetadataField::required_enum("kind", ENTRY_KINDS),
MetadataField::required("summary", MetadataFieldKind::String),
MetadataField::optional("corrects", MetadataFieldKind::String),
MetadataField::optional("supersedes", MetadataFieldKind::String),
];
const CHANGE_FIELDS: &[MetadataField] = &[
MetadataField::required("files", MetadataFieldKind::StringArray),
MetadataField::optional("scope", MetadataFieldKind::String),
];
const TEST_FIELDS: &[MetadataField] = &[
MetadataField::required("command", MetadataFieldKind::String),
MetadataField::optional("result", MetadataFieldKind::String),
];
const BLOCKER_FIELDS: &[MetadataField] = &[
MetadataField::required("id", MetadataFieldKind::String),
MetadataField::optional("severity", MetadataFieldKind::String),
MetadataField::optional("owner", MetadataFieldKind::String),
MetadataField::optional("status", MetadataFieldKind::String),
];
const NEXT_FIELDS: &[MetadataField] = &[
MetadataField::required("task", MetadataFieldKind::String),
MetadataField::optional("priority", MetadataFieldKind::String),
];
const PROGRESS_CHILDREN: &[&str] = &["entry"];
const ENTRY_CHILDREN: &[&str] = &["change", "test", "blocker", "next"];
const BLOCKS: &[BlockDescriptor] = &[
BlockDescriptor {
block_type: "progress",
schema_id: "https://hmd.dev/schemas/progress@0.1/progress.schema.json",
fields: PROGRESS_FIELDS,
allowed_child_block_types: Some(PROGRESS_CHILDREN),
},
BlockDescriptor {
block_type: "entry",
schema_id: "https://hmd.dev/schemas/progress@0.1/entry.schema.json",
fields: ENTRY_FIELDS,
allowed_child_block_types: Some(ENTRY_CHILDREN),
},
BlockDescriptor {
block_type: "change",
schema_id: "https://hmd.dev/schemas/progress@0.1/change.schema.json",
fields: CHANGE_FIELDS,
allowed_child_block_types: None,
},
BlockDescriptor {
block_type: "test",
schema_id: "https://hmd.dev/schemas/progress@0.1/test.schema.json",
fields: TEST_FIELDS,
allowed_child_block_types: None,
},
BlockDescriptor {
block_type: "blocker",
schema_id: "https://hmd.dev/schemas/progress@0.1/blocker.schema.json",
fields: BLOCKER_FIELDS,
allowed_child_block_types: None,
},
BlockDescriptor {
block_type: "next",
schema_id: "https://hmd.dev/schemas/progress@0.1/next.schema.json",
fields: NEXT_FIELDS,
allowed_child_block_types: None,
},
];
pub const PROFILE: ProfileDescriptor = ProfileDescriptor {
id: "progress@0.1",
name: "progress",
version: "0.1",
source: "official",
blocks: BLOCKS,
reference_rules: &[],
};
pub fn descriptor() -> ProfileDescriptor {
PROFILE
}
pub fn register_profile() -> ProfileDescriptor {
descriptor()
}
pub fn json_schema() -> serde_json::Value {
serde_json::to_value(schema_for!(ProgressProfileSchema)).expect("serializes schema")
}