CLAUDE.md@crates/orbit-types · git:20260829.e25929a · 2026-08-29 · sha256 fdbee69f6c205e94
CLAUDE.md@crates/orbit-types git:20260829.e25929aA
Immutable. This exact content is served forever at /api/v1/blob/fdbee69f6c205e94.
# orbit-types Project instructions for the lowest internal contract crate. ## One job Shared **data contracts**: structs, enums, serde shapes, pure constructors, normalization, lifecycle predicates, and narrow domain errors. Nothing else. `orbit-types` has **zero Orbit dependencies** and is the only crate that may be depended on by every other crate. It performs no filesystem, process, environment, database, network, logging, or tracing work — if a change here needs `std::fs`, `std::process`, `std::env`, `rusqlite`, or `tracing`, the behavior belongs one layer up in `orbit-common` and only its *shape* belongs here. ## Domain-qualified modules, never a grab-bag Every item lives under exactly one domain module: [`identity`](src/identity), [`policy`](src/policy), [`record`](src/record), [`resource`](src/resource), [`task`](src/task), [`telemetry`](src/telemetry), [`tool`](src/tool), [`workflow`](src/workflow), [`workspace`](src/workspace). `OrbitId` is the **only** crate-root primitive. Do not add a second one; pick the domain it belongs to instead. A new top-level module means a genuinely new domain, not a convenient home for something that did not fit. Each domain module follows the same shape — see [`identity/mod.rs`](src/identity/mod.rs) or [`task/mod.rs`](src/task/mod.rs): - Submodules are **private** (`mod actor;`), never `pub mod`. - `mod.rs` is declarations plus an explicit `pub use` list. The re-export list *is* the module's public surface; adding a type without listing it there keeps it unreachable on purpose. - One `error.rs` per domain holding a narrow `thiserror` enum (`TaskError`, `IdentityError`, `RecordError`, …) re-exported from `mod.rs`. Workspace-wide `OrbitError` lives in `orbit-common` and must not appear here. - `#[cfg(test)] mod tests;` pointing at a sibling `tests/` directory that mirrors source filenames ([`test_layout.md`](../../docs/design-patterns/test_layout.md)). Choosing between neighbouring domains is a real decision, not a coin flip: `record` holds durable authored artifacts (ADR, friction, event, audit record), while `telemetry` holds measurement of runs (invocation traces, audit events, token pricing, metrics). Put a new type where its *lifecycle* belongs. ## Serde shapes are persisted contract Types here are serialized into task bundles, YAML definitions, SQLite columns, and the MCP wire. Renaming a field or changing a `#[serde]` attribute is a data migration, not a rename — check for a reader in `orbit-store` (bundle/driver code and its `migration` ledger) before touching a shape, and keep `*_SCHEMA_VERSION` constants and their guards in step. The crate is tier **stable** in [`ARCHITECTURE.md`](../../ARCHITECTURE.md); breaking a public shape needs a deliberate decision, not a drive-by cleanup. ## The `clap` feature is presentation-only `clap` is an optional dependency used exclusively through `#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]` and `value(...)` attributes so CLI enums parse from argv without the CLI redefining them. Do not grow it into `Args`/`Parser` derives, help text, or any other command surface — that is `orbit-cli`'s job. A default build of this crate must not link clap.