[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6WY9JQ795HW1VG9EBHT4MF7":3,"skill-same:01M6WY9JQ795HW1VG9EBHT4MF7":77},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":56,"commitSha":57,"skillDirectory":58,"forksCount":14,"repositoryHtmlUrl":59,"repositoryHomepageUrl":60,"ownerHtmlUrl":61,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":62,"install":63,"resources":76},"01M6WY9JQ795HW1VG9EBHT4MF7","rust-conventions",null,"Rust conventions — error handling with anyhow\u002Fthiserror, module layout, clippy. Use when writing or reviewing Rust code, organizing modules, or deciding on error handling, naming, and testing conventions.","projectious-work\u002Fprocesskit","projectious-work","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F263889726?v=4","01M6N97TJJ118WQ35CHRV8RD0E","projectious.work","01M6N97TPWJPF0BMKYQ4PBY5W8",0,"MIT","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.13.0\u002Fcontext\u002Fskills\u002Fengineering\u002Frust-conventions\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"rust","rust conventions","conventions","when","testing","v1","naming","with","error","module","layout","testing conventions","clippy","modules","use","work","engineering","error handling","code","writing","2026-11-10 10:12:30",false,"---\nname: rust-conventions\ndescription: |\n  Rust conventions — error handling with anyhow\u002Fthiserror, module layout, clippy. Use when writing or reviewing Rust code, organizing modules, or deciding on error handling, naming, and testing conventions.\nmetadata:\n  processkit:\n    apiVersion: processkit.projectious.work\u002Fv1\n    id: SKILL-rust-conventions\n    version: \"1.1.0\"\n    created: 2026-04-06T00:00:00Z\n    category: engineering\n---\n\n# Rust Conventions\n\n## Intro\n\nIdiomatic Rust uses `anyhow` for applications and `thiserror` for\nlibraries, pays its `cargo clippy -- -D warnings` bill on every\nbuild, and organizes modules by domain. No `.unwrap()` in\nproduction code.\n\n## Overview\n\n### Error handling\n\nUse `anyhow::Result` for application code where callers just want a\ngood error message, and `thiserror` for libraries where callers\nneed to pattern-match on error variants. Add `.context(\"...\")` to\nevery `?` so the final error message is a breadcrumb trail. Never\n`.unwrap()` in production code. `.expect(\"reason\")` is acceptable\nonly for invariants that cannot fail — the reason documents why.\n\n### Module structure\n\nOne module per file. Re-export public items in `mod.rs` (or the\nparent module) so callers don't depend on file layout. Keep\n`main.rs` and `lib.rs` thin — they should wire things up and\ndelegate to modules. Group by domain (`commands\u002F`, `config\u002F`,\n`output\u002F`), not by type (`traits\u002F`, `structs\u002F`).\n\n### Naming\n\n- Types: `PascalCase`\n- Functions and methods: `snake_case`\n- Constants and statics: `SCREAMING_SNAKE_CASE`\n- `new()` for simple constructors; `from_*()` for conversions;\n  builder pattern for complex construction.\n\n### Clippy compliance\n\nBuild with `cargo clippy -- -D warnings` in CI. Fix every warning\nrather than suppressing it. When you do need `#[allow(...)]`, add\na comment explaining why. Prefer `&str` over `&String` and `&[T]`\nover `&Vec\u003CT>` in function parameters.\n\n### Testing\n\nUnit tests live in a `#[cfg(test)] mod tests` block at the bottom\nof each source file. Integration tests go under `tests\u002F`. Use\n`assert_eq!` with a third argument for the failure message when\nthe context isn't obvious from the values alone.\n\n## Gotchas\n\nAgent-specific failure modes — provider-neutral pause-and-self-check items:\n\n- **`.unwrap()` in production code.** `.unwrap()` panics on `None` or `Err`, producing an unrecoverable crash with no context. Use `?` to propagate the error or `.expect(\"reason\")` only when the reason documents an invariant that cannot fail in production — and even then, think twice.\n- **`.expect(\"\")` with an empty message.** An empty `.expect(\"\")` panics with no information about why the invariant should hold. The message should explain the assumption: `.expect(\"config always has a default value\")`.\n- **Returning `Box\u003Cdyn Error>` from library APIs.** A library that returns `Box\u003Cdyn Error>` forces callers to pattern-match on dynamic dispatch and prevents them from handling specific error variants. Use `thiserror`-derived enums so callers get typed error variants.\n- **Using `anyhow::Error` at a library boundary.** `anyhow` is for applications where you want a good error message, not for library code where callers need to match on error type. Use `thiserror` in libraries, `anyhow` in binaries.\n- **Holding a lock across an `.await` point.** A `MutexGuard` (from `std::sync`) held across an `await` causes the future to be `!Send`, breaking async runtimes. Use `tokio::sync::Mutex` for async code, or acquire and release the guard before the await.\n- **Suppressing clippy warnings with `#[allow(...)]` without a comment.** Clippy warnings are almost always correct. When you do need to suppress one, the `#[allow(...)]` must be accompanied by a comment explaining why the warning doesn't apply in this case — otherwise future readers have no basis for trusting the suppression.\n- **`&String` or `&Vec\u003CT>` in function parameters.** `&str` is strictly more general than `&String` (any `&str` can be passed where `&String` is accepted, but not vice versa). Similarly `&[T]` is more general than `&Vec\u003CT>`. Prefer the slice types in function signatures.\n\n## Full reference\n\n### Error handling patterns\n\n```rust\nuse anyhow::{Context, Result};\n\nfn load_config(path: &Path) -> Result\u003CConfig> {\n    let raw = std::fs::read_to_string(path)\n        .with_context(|| format!(\"reading config from {}\", path.display()))?;\n    toml::from_str(&raw)\n        .with_context(|| format!(\"parsing config at {}\", path.display()))\n}\n```\n\nFor libraries, define a typed error enum:\n\n```rust\nuse thiserror::Error;\n\n#[derive(Debug, Error)]\npub enum ConfigError {\n    #[error(\"reading {path}: {source}\")]\n    Io { path: PathBuf, source: std::io::Error },\n    #[error(\"parsing {path}: {source}\")]\n    Parse { path: PathBuf, source: toml::de::Error },\n}\n```\n\n### Ownership and borrowing rules of thumb\n\n- Prefer borrowed slices (`&str`, `&[T]`) in parameters; own in\n  return types unless a lifetime is part of the contract.\n- Avoid `Rc`\u002F`Arc` until a measured need appears — usually a\n  refactor can eliminate shared ownership.\n- Reach for `Clone` before `Rc` when the clone is cheap and the\n  code stays simpler.\n- Use `Cow\u003C'_, str>` for APIs that usually borrow but sometimes\n  need to own.\n\n### Anti-patterns\n\n- `.unwrap()` or `.expect(\"\")` (empty message) in non-test code.\n- Returning `Box\u003Cdyn Error>` from libraries — use `thiserror`.\n- Catch-all `anyhow::Error` at library boundaries.\n- `#[allow(...)]` without a comment explaining why.\n- Deep module trees re-exporting everything — flatten the public\n  surface.\n- Borrowing `&String` or `&Vec\u003CT>` in function signatures.\n- Holding locks across `.await` points.\n\n### Testing conventions\n\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn parse_size_handles_kilobytes() {\n        assert_eq!(parse_size(\"2KB\").unwrap(), 2048);\n    }\n}\n```\n\nPut integration tests under `tests\u002F`, one file per feature area.\nUse `#[should_panic(expected = \"...\")]` for panic assertions and\n`assert!(matches!(...))` for enum variants.\n","# Rust Conventions\n\n## Intro\n\nIdiomatic Rust uses `anyhow` for applications and `thiserror` for\nlibraries, pays its `cargo clippy -- -D warnings` bill on every\nbuild, and organizes modules by domain. No `.unwrap()` in\nproduction code.\n\n## Overview\n\n### Error handling\n\nUse `anyhow::Result` for application code where callers just want a\ngood error message, and `thiserror` for libraries where callers\nneed to pattern-match on error variants. Add `.context(\"...\")` to\nevery `?` so the final error message is a breadcrumb trail. Never\n`.unwrap()` in production code. `.expect(\"reason\")` is acceptable\nonly for invariants that cannot fail — the reason documents why.\n\n### Module structure\n\nOne module per file. Re-export public items in `mod.rs` (or the\nparent module) so callers don't depend on file layout. Keep\n`main.rs` and `lib.rs` thin — they should wire things up and\ndelegate to modules. Group by domain (`commands\u002F`, `config\u002F`,\n`output\u002F`), not by type (`traits\u002F`, `structs\u002F`).\n\n### Naming\n\n- Types: `PascalCase`\n- Functions and methods: `snake_case`\n- Constants and statics: `SCREAMING_SNAKE_CASE`\n- `new()` for simple constructors; `from_*()` for conversions;\n  builder pattern for complex construction.\n\n### Clippy compliance\n\nBuild with `cargo clippy -- -D warnings` in CI. Fix every warning\nrather than suppressing it. When you do need `#[allow(...)]`, add\na comment explaining why. Prefer `&str` over `&String` and `&[T]`\nover `&Vec\u003CT>` in function parameters.\n\n### Testing\n\nUnit tests live in a `#[cfg(test)] mod tests` block at the bottom\nof each source file. Integration tests go under `tests\u002F`. Use\n`assert_eq!` with a third argument for the failure message when\nthe context isn't obvious from the values alone.\n\n## Gotchas\n\nAgent-specific failure modes — provider-neutral pause-and-self-check items:\n\n- **`.unwrap()` in production code.** `.unwrap()` panics on `None` or `Err`, producing an unrecoverable crash with no context. Use `?` to propagate the error or `.expect(\"reason\")` only when the reason documents an invariant that cannot fail in production — and even then, think twice.\n- **`.expect(\"\")` with an empty message.** An empty `.expect(\"\")` panics with no information about why the invariant should hold. The message should explain the assumption: `.expect(\"config always has a default value\")`.\n- **Returning `Box\u003Cdyn Error>` from library APIs.** A library that returns `Box\u003Cdyn Error>` forces callers to pattern-match on dynamic dispatch and prevents them from handling specific error variants. Use `thiserror`-derived enums so callers get typed error variants.\n- **Using `anyhow::Error` at a library boundary.** `anyhow` is for applications where you want a good error message, not for library code where callers need to match on error type. Use `thiserror` in libraries, `anyhow` in binaries.\n- **Holding a lock across an `.await` point.** A `MutexGuard` (from `std::sync`) held across an `await` causes the future to be `!Send`, breaking async runtimes. Use `tokio::sync::Mutex` for async code, or acquire and release the guard before the await.\n- **Suppressing clippy warnings with `#[allow(...)]` without a comment.** Clippy warnings are almost always correct. When you do need to suppress one, the `#[allow(...)]` must be accompanied by a comment explaining why the warning doesn't apply in this case — otherwise future readers have no basis for trusting the suppression.\n- **`&String` or `&Vec\u003CT>` in function parameters.** `&str` is strictly more general than `&String` (any `&str` can be passed where `&String` is accepted, but not vice versa). Similarly `&[T]` is more general than `&Vec\u003CT>`. Prefer the slice types in function signatures.\n\n## Full reference\n\n### Error handling patterns\n\n```rust\nuse anyhow::{Context, Result};\n\nfn load_config(path: &Path) -> Result\u003CConfig> {\n    let raw = std::fs::read_to_string(path)\n        .with_context(|| format!(\"reading config from {}\", path.display()))?;\n    toml::from_str(&raw)\n        .with_context(|| format!(\"parsing config at {}\", path.display()))\n}\n```\n\nFor libraries, define a typed error enum:\n\n```rust\nuse thiserror::Error;\n\n#[derive(Debug, Error)]\npub enum ConfigError {\n    #[error(\"reading {path}: {source}\")]\n    Io { path: PathBuf, source: std::io::Error },\n    #[error(\"parsing {path}: {source}\")]\n    Parse { path: PathBuf, source: toml::de::Error },\n}\n```\n\n### Ownership and borrowing rules of thumb\n\n- Prefer borrowed slices (`&str`, `&[T]`) in parameters; own in\n  return types unless a lifetime is part of the contract.\n- Avoid `Rc`\u002F`Arc` until a measured need appears — usually a\n  refactor can eliminate shared ownership.\n- Reach for `Clone` before `Rc` when the clone is cheap and the\n  code stays simpler.\n- Use `Cow\u003C'_, str>` for APIs that usually borrow but sometimes\n  need to own.\n\n### Anti-patterns\n\n- `.unwrap()` or `.expect(\"\")` (empty message) in non-test code.\n- Returning `Box\u003Cdyn Error>` from libraries — use `thiserror`.\n- Catch-all `anyhow::Error` at library boundaries.\n- `#[allow(...)]` without a comment explaining why.\n- Deep module trees re-exporting everything — flatten the public\n  surface.\n- Borrowing `&String` or `&Vec\u003CT>` in function signatures.\n- Holding locks across `.await` points.\n\n### Testing conventions\n\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn parse_size_handles_kilobytes() {\n        assert_eq!(parse_size(\"2KB\").unwrap(), 2048);\n    }\n}\n```\n\nPut integration tests under `tests\u002F`, one file per feature area.\nUse `#[should_panic(expected = \"...\")]` for panic assertions and\n`assert!(matches!(...))` for enum variants.\n",{"name":5,"metadata":49,"description":55},{"processkit":50},{"id":51,"created":52,"version":53,"category":40,"apiVersion":54},"SKILL-rust-conventions",1775433600000,"1.1.0","processkit.projectious.work\u002Fv1","Rust conventions — error handling with anyhow\u002Fthiserror, module layout, clippy. Use when writing or reviewing Rust code, organizing modules, or deciding on error handling, naming, and testing conventions.\n","main","4876a92620ee792aac2ac9a1a806322d8a572367","archive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.13.0\u002Fcontext\u002Fskills\u002Fengineering\u002Frust-conventions","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit","https:\u002F\u002Fprojectious-work.github.io\u002Fprocesskit\u002F","https:\u002F\u002Fgithub.com\u002Fprojectious-work","2026-11-11 23:24:18",{"source":8,"skillName":5,"commands":64,"prompt":74,"zipAvailable":75},[65,68,71],{"tool":66,"command":67},"npx","npx skills add projectious-work\u002Fprocesskit --skill rust-conventions",{"tool":69,"command":70},"bunx","bunx skills add projectious-work\u002Fprocesskit --skill rust-conventions",{"tool":72,"command":73},"pnpm","pnpm dlx skills add projectious-work\u002Fprocesskit --skill rust-conventions","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Farchive\u002Fprocesskit-install-20261101\u002Fcontext\u002Ftemplates\u002Fprocesskit\u002Fv0.13.0\u002Fcontext\u002Fskills\u002Fengineering\u002Frust-conventions\u002FSKILL.md",true,[],[78,102,122,143,160,178],{"skillNo":79,"name":80,"nameZh":6,"description":81,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":87,"publishedAt":44},"01M6X5MTC89B4ZGXW3JVSQCPF8","skill-management","Manage Skill package manifests as v1 ontology entities.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fskill-management\u002FSKILL.md",[84],{"categoryNo":85,"categoryName":86,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[88,89,90,91,92,93,39,94,95,96,80,97,98,99,29,100,101],"management","skill management","create","update","package","alpha","list","manage","ontology","get","as","manifests","skill package","transition",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":109,"publishedAt":44},"01M6X5MCV74NHW5MEDNHZRF2C8","schema-management","Manage generated processkit schema contracts through deterministic MCP rebuild and inspection workflows.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fschema-management\u002FSKILL.md",[108],{"categoryNo":85,"categoryName":86,"taxonomyType":21,"taxonomyTypeDesc":22},[88,110,111,112,113,114,93,39,115,116,95,117,118,119,97,120,121],"schema","schema management","MCP","workflows","validation","generated","rebuild","contracts","wed","deterministic","contract","mode",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":128,"publishedAt":44},"01M6X5M5G6YJ96AMZGSCZJ1D13","proposition-management","Record claims, risks, beliefs, world facts, WSJF estimates, and assumptions through the Proposition interface.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fproposition-management\u002FSKILL.md",[],[88,129,130,90,91,131,93,39,132,133,134,135,97,136,137,138,139,140,141,142],"proposition","proposition management","index","log","world","record","query","creation","event","interface","updates","facts","claims","WSJF",{"skillNo":144,"name":145,"nameZh":6,"description":146,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":147,"categories":148,"keywords":149,"publishedAt":44},"01M6X5KMQ83QN9M6MPWZM7344F","ontology-management","Manage generated v1 ontology entities that do not require a dedicated domain server.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fontology-management\u002FSKILL.md",[],[88,96,150,90,93,151,152,115,153,132,95,154,155,97,156,157,137,158,29,159],"ontology management","lifecycle","archive","roadmap","do","domain","iteration","keep","measurement","generic",{"skillNo":161,"name":162,"nameZh":6,"description":163,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":164,"categories":165,"keywords":166,"publishedAt":44},"01M6X5KCY2DN3SM21RERSFNEBT","okf-compatibility","Import, export, and validate conformant Open Knowledge Format bundles.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fokf-compatibility\u002FSKILL.md",[],[167,168,169,170,93,171,172,173,39,174,175,176,177],"okf","compatibility","okf compatibility","validate","open","knowledge","format","export","bundles","bundle","import",{"skillNo":179,"name":180,"nameZh":6,"description":181,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":182,"categories":183,"keywords":184,"publishedAt":44},"01M6X5JA8S5PNGJVFW4EQY8T83","capability-management","Manage versioned Capability entities and their governed lifecycle.","https:\u002F\u002Fgithub.com\u002Fprojectious-work\u002Fprocesskit\u002Fblob\u002Fmain\u002Fsrc\u002Fcontext\u002Fskills\u002Fprocesskit\u002Fcapability-management\u002FSKILL.md",[],[88,185,186,90,91,131,93,151,39,94,132,187,95,134,97,157,137,138,188,101],"capability","capability management","queries","changes"]