crates/cli/src/cmd/skill.rs 2.1 KiB 48 lines Raw
1 #![forbid(unsafe_code)]2 //! f0rge --skill / skill: the contract, from spec/schema.md only.3 use crate::CliError;4 5 pub fn help() -> &'static str {6     "f0rge skill: contract\nusage: f0rge [--skill|skill]\nprints schema v1 contract\ndocs: spec/schema.md §Skill\ncontract: f0rge --skill\n"7 }8 9 /// Contract text: <=30 lines, <=1000 bytes. Schema v1 decisions only.10 /// SKILL_TEXT is the single source of truth; skill/skill.md body must equal it.11 pub const SKILL_TEXT: &str = "f0rge v1: CONTRACT (not help)\n\12 id: uuid4 lowercase dashes; never changes\n\13 number: rank (created,uuid); derived never stored\n\14 files: one file per entity; command tree mirrors folder tree\n\15 tree: issue<->issues/ pr<->prs/ task<->tasks/ ci<->ci/ wiki<->wiki/\n\16 frontmatter: strict --- fences; unknown field warning; missing required error\n\17 git: .forge/ committed with repo; PR=git branch from worktree\n\18 ci: steps are scripts; run in filename order; first nonzero exit code=fail; pass|fail|running|cancelled\n\19 merge: CI-gates patch in scratch worktree; never touches main/branches; prints conflicts, never resolves; you integrate (ff) + delete branch\n\20 never delete: close/archive only; archive to .forge/archive/\n\21 wiki: files under wiki/; edit in place/stdin\n\22 spec: spec/schema.md frozen truth; labels.md/milestones.md registries\n\23 usage: f0rge <cmd> [--json] [args]; init makes .forge/ idempotent; --jq via jq; never parse prose\n\24 json: compact fixed order; empty []/{}\n\25 install: f0rge release install [ver|main]\n";26 27 /// No sub-verbs (#36). Stub for API uniformity.28 #[allow(dead_code)]29 pub fn verb_help(_verb: &str) -> Option<&'static str> {30     None31 }32 33 pub fn run(args: &[String], _fg: &f0rge_core::Forge) -> Result<(), CliError> {34     for a in args {35         if a == "-h" || a == "--help" {36             crate::output::out(help());37             return Ok(());38         }39         if a.starts_with('-') {40             return Err(CliError::Usage(format!("unknown flag: {a} (try: f0rge skill -h)")));41         }42     }43     if !args.is_empty() {44         return Err(CliError::Usage("skill takes no args (try: f0rge skill -h)".to_string()));45     }46     crate::output::out(SKILL_TEXT);47     Ok(())48 }