Flagged on review of nullislabs/shepherd#440. Code is in nexum-world (L1 nullislabs/nexum-runtime). Confirmed unchanged to the end of the completed shepherd feature train (no later car converts it; a git log -S 'enum Capability' / IntoStaticStr across every subsequent car is empty).
Problem
nexum-world models the capability and fault vocabulary as bare &str consts with hand-written string matching:
nexum-world/src/lib.rs:24-36 - the seven host capabilities as &str consts (CHAIN = "chain", IDENTITY = "identity", LOCAL_STORE = "local-store", ...), plus ALL: [&str; 7].
nexum-world/src/lib.rs:43-55 - the seven fault kinds as &str consts (UNSUPPORTED, UNAVAILABLE, DENIED, RATE_LIMITED, ...).
struct Capability + const CORE: &[Capability] (lib.rs:69, 87) - a table keyed on those string names.
is_known / known_names / manifest_capabilities / synthesize match and compare on &str.
This is primitive-obsessed: an unknown capability is caught only at runtime by a string miss, adding one means editing several unlinked &str sites, and the validation error ("expected one of: chain, identity, ...") is hand-assembled from the array.
strum is already a workspace dependency (used for enums in engine_config.rs, manifest/error.rs, supervisor.rs, and the chain/log kinds), so the tooling is already in the tree.
Change
- Introduce
enum Capability { Chain, Identity, LocalStore, RemoteStore, Messaging, Logging, Http } and enum FaultKind { Unsupported, Unavailable, Denied, RateLimited, Timeout, InvalidInput, Internal }, each deriving strum::{IntoStaticStr, EnumString, Display, EnumIter} (with the kebab-case wire spelling where needed) plus serde where they cross a manifest boundary.
- Replace the
&str consts, ALL, and the string-keyed CORE table with variant-driven equivalents: is_known becomes a parse::<Capability>(), known_names becomes Capability::iter(), and the "expected one of" error is generated from the enum rather than hand-assembled.
- Fold the remaining mechanical
Display / From impls in this area into derive_more where they carry no logic.
Acceptance criteria
- No bare
&str capability or fault-kind name literals remain in nexum-world; matching is on enum variants.
- Adding a capability or fault kind is a single exhaustively-checked enum edit.
- The manifest round-trip (parse plus the "expected one of" error) is derived, not hand-written.
Related: #28 (types the two WASI names into a WasiCap enum) and #48 (the derive_more adoption); this is the core vocabulary those only nick.
Problem
nexum-worldmodels the capability and fault vocabulary as bare&strconsts with hand-written string matching:nexum-world/src/lib.rs:24-36- the seven host capabilities as&strconsts (CHAIN = "chain",IDENTITY = "identity",LOCAL_STORE = "local-store", ...), plusALL: [&str; 7].nexum-world/src/lib.rs:43-55- the seven fault kinds as&strconsts (UNSUPPORTED,UNAVAILABLE,DENIED,RATE_LIMITED, ...).struct Capability+const CORE: &[Capability](lib.rs:69, 87) - a table keyed on those string names.is_known/known_names/manifest_capabilities/synthesizematch and compare on&str.This is primitive-obsessed: an unknown capability is caught only at runtime by a string miss, adding one means editing several unlinked
&strsites, and the validation error ("expected one of: chain, identity, ...") is hand-assembled from the array.strumis already a workspace dependency (used for enums inengine_config.rs,manifest/error.rs,supervisor.rs, and the chain/log kinds), so the tooling is already in the tree.Change
enum Capability { Chain, Identity, LocalStore, RemoteStore, Messaging, Logging, Http }andenum FaultKind { Unsupported, Unavailable, Denied, RateLimited, Timeout, InvalidInput, Internal }, each derivingstrum::{IntoStaticStr, EnumString, Display, EnumIter}(with the kebab-case wire spelling where needed) plusserdewhere they cross a manifest boundary.&strconsts,ALL, and the string-keyedCOREtable with variant-driven equivalents:is_knownbecomes aparse::<Capability>(),known_namesbecomesCapability::iter(), and the "expected one of" error is generated from the enum rather than hand-assembled.Display/Fromimpls in this area intoderive_morewhere they carry no logic.Acceptance criteria
&strcapability or fault-kind name literals remain innexum-world; matching is on enum variants.Related: #28 (types the two WASI names into a
WasiCapenum) and #48 (thederive_moreadoption); this is the core vocabulary those only nick.