# sim-sdk Human Docs
This lane contains human-readable guides generated by `xtask simdoc`.
## Index Backlinks
This generated lane consumes `docs/generated/sim-index-fragment.sx`. Global index consumers merge that fragment into `docs/index/overview.md`, `docs/index/features.md`, and the package maps.
| `repo/sim-sdk` | `repo` | sim-sdk |
| `doc-set/sim-sdk/generated` | `doc-set` | sim-sdk generated docs |
## Feature Rows
| `feature/sim-sdk/generated-docs` | `crate/xtask` | 0 | Publish generated package, card, recipe, and index facts for the SDK facade and conformance crate. |
| `feature/sim-sdk/facade-runtime` | `crate/sim-nest` | 1 | Boot the public SIM facade and expose its command plus reversible view surface. |
| `feature/sim-sdk/facade-codecs` | `crate/sim-nest` | 0 | Expose public codec exports through the SDK facade while implementation crates keep the codec behavior. |
| `feature/sim-sdk/facade-model-workflows` | `crate/sim-nest` | 0 | Expose model-facing facade exports for answer routing and drafter setup. |
| `feature/sim-sdk/genai-feature-bundles` | `crate/sim-nest` | 2 | Select base, local, and provider GenAI dependency bundles through SDK Cargo feature aliases. |
| `feature/sim-sdk/gpu-math-composition` | `crate/sim-nest` | 1 | Expose opt-in Tensor, ODE, compute-provider, and FEMM solver composition through direct SDK re-exports. |
| `feature/sim-sdk/interference-composition` | `crate/sim-nest` | 1 | Compose canonical interference records, solve/runtime, Tensor compute, and reversible view behavior through direct SDK re-exports. |
| `feature/sim-sdk/expression-tree-composition` | `crate/sim-nest` | 1 | Expose the canonical finite-tree core, bounded calculator, loadable runtime, reversible view, and authoritative server behind one opt-in SDK feature. |
| `feature/sim-sdk/music-algorithm-composition` | `crate/sim-nest` | 1 | Select frozen signal, bounded-search, exact-ratio, consonance, and counterpoint candidates through focused features or curated SDK groups. |
| `feature/sim-sdk/serial-music-composition` | `crate/sim-nest` | 5 | Select the frozen serial-series, row-theory, immutable-plan, adaptation, and reversible-completion candidates through one curated SDK facade. |
| `feature/sim-sdk/facade-shapes` | `crate/sim-nest` | 0 | Expose public Shape exports through the SDK facade while shape crates keep the matching behavior. |
| `feature/sim-sdk/device-recipes` | `crate/sim-nest` | 1 | Exercise modeled device, watch, and glasses workflows through SDK-level recipe entry points. |
| `feature/sim-sdk/conformance-contract` | `crate/sim-conformance` | 1 | Run the SDK conformance contract as a checked operational recipe. |
## Surfaces
| `cli/sim-nest` | `cli` | `crate/sim-nest` |
| `cli/xtask` | `cli` | `crate/xtask` |
| `docs/sim-sdk/generated` | `docs` | `doc-set/sim-sdk/generated` |
| `site-device/glasses-hud` | `site-device` | `crate/sim-nest` |
| `site-device/glasses-luma-ultra` | `site-device` | `crate/sim-nest` |
| `site/sim-nest` | `site` | `crate/sim-nest` |
| `view-edit/sim-nest` | `view-edit` | `crate/sim-nest` |
| `view/sim-nest` | `view` | `crate/sim-nest` |
## Recipes
- `crates/sim-conformance/recipes/01-basics/chapter.toml`
- `crates/sim-conformance/recipes/01-basics/run-contract/README.md`
- `crates/sim-conformance/recipes/01-basics/run-contract/input.sh`
- `crates/sim-conformance/recipes/01-basics/run-contract/recipe.toml`
- `crates/sim-conformance/recipes/book.toml`
- `recipes/01-basics/boot-runtime/README.md`
- `recipes/01-basics/boot-runtime/expected.txt`
- `recipes/01-basics/boot-runtime/input.lisp`
- `recipes/01-basics/boot-runtime/recipe.toml`
- `recipes/01-basics/chapter.toml`
- `recipes/book.toml`
- `recipes/device/chapter.toml`
- `recipes/device/consent/README.md`
- `recipes/device/consent/input.lisp`
- `recipes/device/consent/recipe.toml`
- `recipes/device/route-swap/README.md`
- `recipes/device/route-swap/input.lisp`
- `recipes/device/route-swap/recipe.toml`
- `recipes/device/two-rate/README.md`
- `recipes/device/two-rate/input.lisp`
- `recipes/device/two-rate/recipe.toml`
- `recipes/glasses/book.toml`
- `recipes/glasses/chapter.toml`
- `recipes/glasses/co-use/README.md`
- `recipes/glasses/co-use/input.lisp`
- `recipes/glasses/co-use/recipe.toml`
- `recipes/glasses/halo-glance-pager/README.md`
- `recipes/glasses/halo-glance-pager/input.lisp`
- `recipes/glasses/halo-glance-pager/recipe.toml`
- `recipes/glasses/review-in-space/README.md`
- `recipes/glasses/review-in-space/input.lisp`
- `recipes/glasses/review-in-space/recipe.toml`
- `recipes/glasses/viture-two-rate/README.md`
- `recipes/glasses/viture-two-rate/input.lisp`
- `recipes/glasses/viture-two-rate/recipe.toml`
- `recipes/glasses/voice-site/README.md`
- `recipes/glasses/voice-site/input.lisp`
- `recipes/glasses/voice-site/recipe.toml`
- `recipes/gpu-math/chapter.toml`
- `recipes/gpu-math/modeled-matrix-ode-femm/README.md`
- `recipes/gpu-math/modeled-matrix-ode-femm/expected.txt`
- `recipes/gpu-math/modeled-matrix-ode-femm/input.lisp`
- `recipes/gpu-math/modeled-matrix-ode-femm/recipe.toml`
- `recipes/interference/chapter.toml`
- `recipes/interference/modeled-study/README.md`
- `recipes/interference/modeled-study/expected.txt`
- `recipes/interference/modeled-study/input.lisp`
- `recipes/interference/modeled-study/recipe.toml`
- `recipes/music-algorithms/chapter.toml`
- `recipes/music-algorithms/foundry-plan/README.md`
- `recipes/music-algorithms/foundry-plan/expected.txt`
- `recipes/music-algorithms/foundry-plan/input.lisp`
- `recipes/music-algorithms/foundry-plan/recipe.toml`
- `recipes/serial-music/chapter.toml`
- `recipes/serial-music/index-discovery/purpose.md`
- `recipes/serial-music/index-discovery/recipe.toml`
- `recipes/serial-music/index-discovery/setup.rs`
- `recipes/serial-music/modal-realization/purpose.md`
- `recipes/serial-music/modal-realization/recipe.toml`
- `recipes/serial-music/modal-realization/setup.rs`
- `recipes/serial-music/reversible-completion/purpose.md`
- `recipes/serial-music/reversible-completion/recipe.toml`
- `recipes/serial-music/reversible-completion/setup.rs`
- `recipes/serial-music/row-matrix-analysis/purpose.md`
- `recipes/serial-music/row-matrix-analysis/recipe.toml`
- `recipes/serial-music/row-matrix-analysis/setup.rs`
- `recipes/watch/book.toml`
- `recipes/watch/chapter.toml`
- `recipes/watch/dual-quorum/README.md`
- `recipes/watch/dual-quorum/input.lisp`
- `recipes/watch/dual-quorum/recipe.toml`
- `recipes/watch/glance-pager/README.md`
- `recipes/watch/glance-pager/input.lisp`
- `recipes/watch/glance-pager/recipe.toml`
- `recipes/watch/hold-last/README.md`
- `recipes/watch/hold-last/input.lisp`
- `recipes/watch/hold-last/recipe.toml`
- `recipes/watch/privacy-reaper/README.md`
- `recipes/watch/privacy-reaper/input.lisp`
- `recipes/watch/privacy-reaper/recipe.toml`
## Worked Examples
### `feature/sim-sdk/facade-runtime`
Specimen `spec-test/sim-sdk/crates/sim-conformance/tests/cli_boot` is checked by `cargo test`.
Source `crates/sim-conformance/tests/cli_boot.rs`:
```rust
#[path = "spec/cli_boot.rs"]
mod cli_boot;
```
### `feature/sim-sdk/genai-feature-bundles`
Specimen `spec-test/sim-sdk/src/feature_contract_tests` is checked by `cargo test`.
Source `src/feature_contract_tests.rs`:
```rust
mod cfg_sentinels;
mod facade_thinness;
mod glasses;
mod support;
mod watch;
use support::{
assert_all_feature_metadata_has_no_invalid_dependency_warnings,
assert_crate_cargo_tomls_do_not_contain, assert_dep_edges_reference_optional_dependencies,
assert_feature_includes, collect_cfg_features, collect_declared_features,
collect_feature_dependencies, collect_optional_dependencies, repo_root,
};
const PUBLIC_FACADE_ALIASES: &[(&str, &str)] = &[
("agent-runner-core", "lib_agent_runner_core"),
("agent-runner-http", "lib_agent_runner_http"),
("agent-runner-process", "lib_agent_runner_process"),
("discrete", "lib_discrete"),
("view", "lib_view"),
("view-agent", "lib_view_agent"),
("view-bridge", "lib_view_bridge"),
("view-codec", "lib_view_codec"),
("view-daw", "lib_view_daw"),
("view-doc", "lib_view_doc"),
("view-math", "lib_view_math"),
("web-layout", "lib_web_layout"),
("web-wasm-frame", "lib_view_wasm_frame"),
];
#[test]
fn declared_features_match_cfg_usage() {
let root = repo_root();
let cargo_toml = include_str!("../Cargo.toml");
let declared = collect_declared_features(cargo_toml);
let used = collect_cfg_features(&root);
assert_eq!(
declared, used,
"declared features must match cfg(feature = ...) usage in src/ and tests/"
);
}
#[test]
fn default_features_support_readme_quickstart() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(
&features,
"default",
&["core", "shape", "codec-lisp", "numbers-f64"],
);
}
#[test]
fn device_feature_installs_reference_base_and_recipes() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(&features, "device", &["device-reference", "cookbook"]);
}
#[test]
fn public_facade_alias_table_mentions_declared_features() {
let declared = collect_declared_features(include_str!("../Cargo.toml"));
let missing = PUBLIC_FACADE_ALIASES
.iter()
.filter(|(feature, _)| !declared.contains(*feature))
.collect::<Vec<_>>();
assert!(
missing.is_empty(),
"public facade aliases must reference declared features: {missing:?}"
);
}
#[test]
fn feature_dep_edges_reference_optional_dependencies() {
let cargo_toml = include_str!("../Cargo.toml");
let features = collect_feature_dependencies(cargo_toml);
let optional_dependencies = collect_optional_dependencies(cargo_toml);
assert_dep_edges_reference_optional_dependencies(&features, &optional_dependencies);
}
#[test]
fn all_feature_metadata_has_no_ignored_optional_dependencies() {
assert_all_feature_metadata_has_no_invalid_dependency_warnings(&repo_root());
}
const REQUIRED_PUBLIC_GATES: &[&str] = &[
"cargo fmt --all --check",
"cargo test -p sim-conformance",
"cargo test --workspace",
"cargo clippy --workspace --all-targets -- -D warnings",
"cargo doc --workspace --no-deps",
"cargo clippy --workspace --all-features --all-targets -- -D warnings",
"cargo test --workspace --all-features",
"cargo run -p xtask -- simdoc --check",
];
#[test]
fn ci_and_public_checklists_name_required_gates() {
let checked_files = [
(
".github/workflows/ci.yml",
include_str!("../.github/workflows/ci.yml"),
),
("README.md", include_str!("../README.md")),
("CONTRIBUTING.md", include_str!("../CONTRIBUTING.md")),
(
".github/pull_request_template.md",
include_str!("../.github/pull_request_template.md"),
),
];
let missing = checked_files
.into_iter()
.flat_map(|(file, text)| {
REQUIRED_PUBLIC_GATES
.iter()
.filter(move |command| !text.contains(**command))
.map(move |command| format!("{file}: {command}"))
})
.collect::<Vec<_>>();
assert!(
missing.is_empty(),
"CI and public checklists must stay aligned with repos.toml gates: {missing:?}"
);
}
#[test]
fn r10_numeric_feature_implications_stay_wired() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(
&features,
"numbers-rk",
&["numbers-numeric", "numbers-tensor"],
);
assert_feature_includes(
&features,
"numbers-rational",
&["numbers-arith", "numbers-bigint", "numbers-core"],
);
assert_feature_includes(
&features,
"numbers-tensor-linalg",
&["numbers-tensor", "numbers-cas"],
);
assert_feature_includes(
&features,
"numbers-tensor-cmplxf",
&["numbers-tensor", "numbers-complex", "numbers-f64"],
);
assert_feature_includes(
&features,
"numbers-codec",
&[
"numbers-core",
"numbers-f64",
"numbers-i64",
"numbers-bool",
"numbers-fixed",
"numbers-float",
"numbers-bigint",
"numbers-rational",
"numbers-complex",
"numbers-exotic",
"numbers-cas",
"numbers-func",
"numbers-numeric",
"numbers-rk",
"numbers-quad",
"numbers-tensor",
"numbers-tensor-bcast",
"numbers-tensor-linalg",
"numbers-tensor-bit",
"numbers-tensor-f64",
"numbers-tensor-i64",
"numbers-tensor-rat64",
"numbers-tensor-cmplxf",
],
);
assert_feature_includes(
&features,
"numbers-prelude",
&[
"numbers-ad",
"numbers-arith",
"numbers-core",
"numbers-f64",
"numbers-i64",
"numbers-rational",
"numbers-complex",
"numbers-bool",
"numbers-fixed",
"numbers-float",
"numbers-bigint",
"numbers-exotic",
"numbers-cas",
"numbers-cas-diff",
"numbers-cas-eval",
"numbers-func",
"numbers-numeric",
"numbers-rk",
"numbers-quad",
"numbers-tensor",
"numbers-tensor-bcast",
"numbers-tensor-linalg",
"numbers-tensor-bit",
"numbers-tensor-f64",
"numbers-tensor-i64",
"numbers-tensor-rat64",
"numbers-tensor-cmplxf",
"numbers-codec",
],
);
}
#[test]
fn r12_logic_feature_implications_stay_wired() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(&features, "logic", &["logic-core", "logic-numbers"]);
assert_feature_includes(&features, "logic-agent", &["logic-core", "agent"]);
assert_feature_includes(&features, "logic-server", &["logic-core", "server"]);
assert_feature_includes(&features, "logic-wasm", &["logic-core", "wasm"]);
assert_feature_includes(
&features,
"logic-numbers",
&[
"logic-core",
"numbers-arith",
"numbers-f64",
"numbers-i64",
"numbers-rational",
],
);
}
#[rustfmt::skip] const MCP_STREAM_DEPS: &[&str] = &["mcp", "stream-core", "stream-fabric", "stream-combinators", "sim-lib-mcp/stream", "sim-lib-mcp/progress"];
#[rustfmt::skip] const MCP_HTTP_DEPS: &[&str] = &["mcp-stream", "server", "server-net-http", "sim-lib-mcp/http"];
const MCP_SAMPLING_DEPS: &[&str] = &["mcp", "agent-runner-core", "sim-lib-mcp/sampling"];
#[test]
fn g6_mcp_feature_implications_stay_wired() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
let cases: &[(&str, &[&str])] = &[
("mcp", &["dep:sim-lib-mcp", "codec-mcp", "core", "shape"]),
("mcp-skill", &["mcp", "skill", "sim-lib-mcp/skill"]),
("mcp-stdio", &["mcp", "sim-lib-mcp/stdio"]),
("mcp-stream", MCP_STREAM_DEPS),
("mcp-http", MCP_HTTP_DEPS),
("mcp-client", &["mcp-skill", "sim-lib-mcp/client"]),
("mcp-sampling", MCP_SAMPLING_DEPS),
("mcp-cassette", &["mcp", "sim-lib-mcp/cassette"]),
("mcp-binary", &["mcp-stdio"]),
(
"skill-serve",
&["skill-mcp", "mcp-skill", "server", "sim-lib-skill/serve"],
),
];
for (feature, expected) in cases {
assert_feature_includes(&features, feature, expected);
}
}
// conformance: GenAI SDK feature bundles keep base, local, and provider closures explicit.
#[test]
fn genai_feature_bundles_select_base_local_and_provider_closures() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(
&features,
"genai",
&["agent", "bridge", "codec-json", "cookbook"],
);
assert_feature_includes(
&features,
"genai-local",
&[
"genai",
"agent-runner-process",
"agent-runner-ollama",
"agent-runner-http",
],
);
assert_feature_includes(
&features,
"genai-provider",
&["genai", "agent-runner-http-tls"],
);
let base = features.get("genai").expect("genai feature");
for excluded in [
"agent-runner-process",
"agent-runner-ollama",
"agent-runner-http",
"agent-runner-http-tls",
] {
assert!(
!base.contains(excluded),
"`genai` should not directly enable `{excluded}`"
);
}
}
#[test]
fn r11_music_stack_feature_implications_stay_wired() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(
&features,
"pitch",
&[
"pitch-core",
"pitch-set",
"pitch-scale",
"pitch-chord",
"pitch-namer",
"pitch-dissonance",
"pitch-shapes",
],
);
assert_feature_includes(
&features,
"pitch-namer",
&[
"pitch-namer-forte",
"pitch-namer-jazz",
"pitch-namer-roman",
"pitch-namer-riemann",
"pitch-set",
"pitch-scale",
"pitch-chord",
],
);
assert_feature_includes(
&features,
"midi",
&[
"midi-core",
"midi-smf",
"midi-live",
"midi-sysex",
"midi-shapes",
],
);
assert_feature_includes(&features, "midi-sysex", &["midi-core"]);
assert_feature_includes(
&features,
"music",
&[
"music-core",
"music-combinators",
"music-analysis",
"music-transform",
"music-lower",
"music-lift",
"music-notation",
"music-shapes",
"pitch",
"midi",
],
);
assert_feature_includes(
&features,
"sound",
&[
"sound-core",
"sound-spectrum",
"sound-timbre",
"sound-tuning",
"sound-dissonance",
"sound-bridge",
"sound-render",
"sound-shapes",
"pitch",
"midi",
],
);
assert_feature_includes(
&features,
"music-stack",
&[
"pitch",
"midi",
"music",
"sound",
"sound-gm",
"sound-audio-lift",
"sound-music",
],
);
assert_feature_includes(&features, "sound-music", &["sound", "music"]);
assert_feature_includes(
&features,
"sound-audio-lift",
&["sound-spectrum", "sound-tuning", "pitch"],
);
assert_feature_includes(&features, "sound-gm", &["sound-timbre"]);
assert_feature_includes(&features, "pitch-wasm-frame", &["pitch", "wasm"]);
assert_feature_includes(&features, "midi-wasm-frame", &["midi", "wasm"]);
assert_feature_includes(&features, "stream-host", &["stream-midi"]);
assert_feature_includes(&features, "music-wasm-frame", &["music", "wasm"]);
assert_feature_includes(
&features,
"sound-wasm-frame",
&[
"sim-lib-sound-wasm-frame/sound-music",
"sound",
"sound-music",
"wasm",
],
);
assert_feature_includes(
&features,
"music-stack-wasm-frame",
&[
"music-stack",
"pitch-wasm-frame",
"midi-wasm-frame",
"music-wasm-frame",
"sound-wasm-frame",
],
);
}
#[test]
fn music_algorithm_features_preserve_focused_and_grouped_selection() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(&features, "signal", &["dep:sim-lib-numbers-signal"]);
assert_feature_includes(
&features,
"music-algorithms",
&[
"signal",
"dep:sim-lib-discrete-search",
"dep:sim-lib-pitch-ratio",
],
);
assert_feature_includes(
&features,
"music-inference",
&[
"music-algorithms",
"dep:sim-lib-music-consonance",
"dep:sim-lib-music-counterpoint",
],
);
for (feature, dependency) in [
("discrete-search", "dep:sim-lib-discrete-search"),
("pitch-ratio", "dep:sim-lib-pitch-ratio"),
("music-consonance", "dep:sim-lib-music-consonance"),
("music-counterpoint", "dep:sim-lib-music-counterpoint"),
] {
assert_feature_includes(&features, feature, &[dependency]);
}
let exports = include_str!("music_algorithm_exports.rs");
assert!(!exports.contains("MeanDialect"));
assert!(!exports.contains("compile_counterpoint_csp"));
assert!(!exports.contains("CounterpointCsp"));
}
#[test]
fn serial_music_features_preserve_curated_grouping() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(&features, "serial-core", &["dep:sim-lib-serial-core"]);
assert_feature_includes(
&features,
"pitch-serial",
&["dep:sim-lib-pitch-serial", "serial-core", "pitch-core"],
);
assert_feature_includes(
&features,
"serial-music",
&[
"dep:sim-lib-music-serial",
"pitch-serial",
"music-consonance",
"music-notation",
"music-shapes",
"pitch-shapes",
"cookbook",
],
);
}
#[test]
fn r11_production_crate_dependency_boundaries_stay_wired() {
let root = repo_root();
assert_crate_cargo_tomls_do_not_contain(
&root,
"sim-lib-pitch-",
&["sim-lib-midi-", "sim-lib-music-", "sim-lib-sound-"],
);
assert_crate_cargo_tomls_do_not_contain(
&root,
"sim-lib-midi-",
&["sim-lib-pitch-", "sim-lib-music-", "sim-lib-sound-"],
);
assert_crate_cargo_tomls_do_not_contain(&root, "sim-lib-music-", &["sim-lib-sound-"]);
}
#[test]
fn r10_femm_feature_implications_stay_wired() {
let features = collect_feature_dependencies(include_str!("../Cargo.toml"));
assert_feature_includes(&features, "femm-geometry", &["femm-core"]);
assert_feature_includes(&features, "femm-material", &["femm-core", "numbers-ad"]);
assert_feature_includes(&features, "femm-mesh", &["femm-geometry", "femm-material"]);
assert_feature_includes(&features, "femm-assembly", &["femm-space", "numbers-ad"]);
assert_feature_includes(&features, "femm-solve", &["femm-core", "numbers-complex"]);
assert_feature_includes(
&features,
"femm-flow",
&[
"femm-core",
"femm-assembly",
"femm-solve",
"numbers-numeric",
],
);
assert_feature_includes(
&features,
"femm-physics",
&["femm-core", "femm-assembly", "numbers-complex"],
);
assert_feature_includes(&features, "femm-post", &["femm-core", "femm-physics"]);
assert_feature_includes(
&features,
"femm-field",
&["femm-core", "femm-post", "numbers-func", "numbers-tensor"],
);
assert_feature_includes(
&features,
"femm-function",
&["femm-core", "femm-field", "numbers-func"],
);
assert_feature_includes(
&features,
"femm-sensitiv",
&["femm-core", "femm-function", "femm-solve", "numbers-ad"],
);
assert_feature_includes(
&features,
"femm-tape",
&["femm-core", "femm-function", "femm-solve"],
);
assert_feature_includes(
&features,
"femm-ode",
&["femm-core", "femm-tape", "numbers-rk", "numbers-tensor"],
);
assert_feature_includes(
&features,
"femm-codec",
&[
"femm-core",
"femm-geometry",
"femm-material",
"femm-mesh",
"femm-space",
"femm-assembly",
"femm-solve",
"femm-flow",
"femm-physics",
"femm-post",
"femm-field",
"femm-function",
"femm-sensitiv",
"femm-tape",
"femm-ode",
"numbers-codec",
],
);
assert_feature_includes(&features, "femm-fixtures", &["femm-prelude"]);
assert_feature_includes(
&features,
"femm-prelude",
&[
"femm-core",
"femm-geometry",
"femm-material",
"femm-mesh",
"femm-space",
"femm-assembly",
"femm-solve",
"femm-flow",
"femm-physics",
"femm-post",
"femm-field",
"femm-function",
"femm-sensitiv",
"femm-tape",
"femm-ode",
"femm-codec",
"numbers-prelude",
],
);
}
```
Specimen `spec-test/sim-sdk/src/runtime/cookbook_directory` is checked by `cargo test`.
Source `src/runtime/cookbook_directory.rs`:
```rust
//! sim-nest's product cookbook loadable-lib directory.
//!
//! `sim-lib-cookbook` keeps a small standalone fixture directory. The umbrella
//! crate owns the product directory because only this crate sees the
//! constellation feature graph without adding back-edges to the cookbook lib.
use std::sync::Arc;
use sim_cookbook::EmbeddedDir;
use sim_kernel::{CodecId, Lib};
use sim_lib_cookbook::{
ConfigProvider, CookbookConfig, LoadableLibConfig, LoadableLibList, LoadableLibResolver,
ResolvedLoadable,
};
#[macro_use]
mod audio_stream;
#[macro_use]
mod codecs;
#[macro_use]
mod compute;
#[macro_use]
mod data;
#[macro_use]
mod device;
#[macro_use]
mod femm;
#[macro_use]
mod glasses;
#[macro_use]
mod interference;
#[macro_use]
mod music;
#[macro_use]
mod numbers;
#[macro_use]
mod runtime_libs;
#[macro_use]
mod watch;
macro_rules! loadable_libs {
($m:ident) => {
cookbook_directory_codecs!($m);
cookbook_directory_compute!($m);
cookbook_directory_numbers!($m);
cookbook_directory_runtime_libs!($m);
cookbook_directory_femm!($m);
cookbook_directory_interference!($m);
cookbook_directory_glasses!($m);
cookbook_directory_music!($m);
cookbook_directory_audio_stream!($m);
cookbook_directory_data!($m);
cookbook_directory_device!($m);
cookbook_directory_watch!($m);
};
}
/// Product default cookbook config for the enabled sim-nest feature set.
pub fn default_cookbook_config() -> CookbookConfig {
CookbookConfig {
minimum_loaded: vec!["codec/lisp".to_owned(), "core".to_owned()],
loadable_libs: loadable_rows(),
}
}
/// Resolve the product default directory for the enabled sim-nest feature set.
pub fn default_loadable_libs() -> (LoadableLibList, Vec<String>) {
ConfigProvider::new(default_cookbook_config(), &SimNestCookbookResolver).loadable_libs()
}
/// Loadable-lib ids compiled into a `cookbook-all` build.
#[cfg(feature = "cookbook-all")]
pub fn cookbook_all_lib_ids() -> Vec<&'static str> {
let mut ids = Vec::new();
macro_rules! push_id {
($id:literal, $title:literal, $feature:literal, $recipes:expr, $make:expr) => {
#[cfg(feature = $feature)]
{
let _ = $title;
ids.push($id);
}
};
}
loadable_libs!(push_id);
ids
}
fn loadable_rows() -> Vec<LoadableLibConfig> {
let mut rows = Vec::new();
macro_rules! push_row {
($id:literal, $title:literal, $feature:literal, $recipes:expr, $make:expr) => {
#[cfg(feature = $feature)]
{
let _ = $title;
rows.push(row($id));
}
};
}
loadable_libs!(push_row);
rows
}
fn row(id: &str) -> LoadableLibConfig {
LoadableLibConfig {
id: id.to_owned(),
source: format!("sim-nest:{id}"),
}
}
/// Resolver over the loadable libs linked into this sim-nest build.
pub struct SimNestCookbookResolver;
impl LoadableLibResolver for SimNestCookbookResolver {
fn resolve(&self, source: &str, id: &str) -> Option<ResolvedLoadable> {
if source != format!("sim-nest:{id}") {
return None;
}
macro_rules! resolve_if {
($row_id:literal, $title:literal, $feature:literal, $recipes:expr, $make:expr) => {
#[cfg(feature = $feature)]
if id == $row_id {
return Some(resolved($title, $recipes, $make));
}
};
}
loadable_libs!(resolve_if);
None
}
}
#[allow(dead_code)]
fn codec_id(offset: u32) -> CodecId {
const PRODUCT_CODEC_BASE: u32 = 10_000;
CodecId(PRODUCT_CODEC_BASE + offset)
}
fn resolved<F>(title: &str, recipes: Option<EmbeddedDir>, make: F) -> ResolvedLoadable
where
F: Fn() -> Box<dyn Lib + Send + Sync> + Send + Sync + 'static,
{
ResolvedLoadable {
title: title.to_owned(),
recipes,
factory: Arc::new(make),
}
}
#[cfg(all(test, feature = "interference", feature = "cookbook"))]
mod interference_tests {
use sim_cookbook::recipes_from_embedded;
#[test]
fn interference_directory_preserves_dependency_order_and_recipes() {
let (directory, diagnostics) = super::default_loadable_libs();
assert!(diagnostics.is_empty(), "unresolved rows: {diagnostics:?}");
let ids = directory
.entries()
.iter()
.map(|entry| entry.id.as_str())
.collect::<Vec<_>>();
let records = position(&ids, "interference/records");
let runtime = position(&ids, "interference/runtime");
let compute = position(&ids, "interference/compute");
assert!(records < runtime && runtime < compute);
for (id, recipe) in [
(
"interference/runtime",
"interference-runtime/01-basics/two-source-cancellation",
),
(
"interference/compute",
"interference-compute/01-basics/modeled-resident-study",
),
] {
let recipes = directory
.entry(id)
.and_then(|entry| entry.recipes)
.unwrap_or_else(|| panic!("{id} recipes"));
let cards = recipes_from_embedded(recipes).unwrap();
assert!(
cards.iter().any(|card| card.id == recipe),
"{id} should expose {recipe}"
);
}
}
fn position(ids: &[&str], expected: &str) -> usize {
ids.iter()
.position(|id| *id == expected)
.unwrap_or_else(|| panic!("missing {expected} directory row"))
}
}
// conformance: GenAI SDK bundle cookbook rows resolve the agent and bridge libraries.
#[cfg(all(test, feature = "genai"))]
mod genai_tests {
use sim_cookbook::recipes_from_embedded;
#[test]
fn genai_bundle_resolves_agent_bridge_and_recipe() {
let (dir, diags) = super::default_loadable_libs();
assert!(diags.is_empty(), "unresolved rows: {diags:?}");
assert!(dir.entry("bridge").is_some(), "bridge row");
let agent = dir.entry("agent").expect("agent row");
let recipes = agent.recipes.expect("agent recipes");
let cards = recipes_from_embedded(recipes).expect("agent recipes parse");
assert!(
cards
.iter()
.any(|card| card.id == "agent/01-basics/genai-assembly"),
"agent cookbook row should include the GenAI assembly recipe"
);
}
}
#[cfg(all(test, feature = "cookbook-all"))]
mod tests {
use std::collections::{BTreeMap, BTreeSet};
#[test]
fn every_loadable_lib_has_a_directory_row() {
let cfg = super::default_cookbook_config();
assert_eq!(cfg.minimum_loaded, ["codec/lisp", "core"]);
let ids = super::cookbook_all_lib_ids();
let mut counts = BTreeMap::new();
for row in &cfg.loadable_libs {
*counts.entry(row.id.as_str()).or_insert(0usize) += 1;
assert_eq!(row.source, format!("sim-nest:{}", row.id));
}
for id in &ids {
assert_eq!(counts.get(id).copied(), Some(1), "{id} row count");
}
assert_eq!(counts.len(), ids.len());
let (dir, diags) = super::default_loadable_libs();
assert!(diags.is_empty(), "unresolved rows: {diags:?}");
let resolved = dir
.entries()
.iter()
.map(|entry| entry.id.as_str())
.collect::<BTreeSet<_>>();
for id in &ids {
assert!(
dir.entry(id).is_some(),
"loadable lib `{id}` missing a directory row"
);
assert!(
resolved.contains(id),
"loadable lib `{id}` missing a factory"
);
}
assert_eq!(dir.entries().len(), ids.len());
}
#[test]
fn cookbook_all_feature_matches_directory_features() {
let cargo_toml = include_str!("../../Cargo.toml");
let cookbook_features = parse_feature(cargo_toml, "cookbook-all");
let mut row_features = BTreeSet::new();
macro_rules! push_feature {
($id:literal, $title:literal, $feature:literal, $recipes:expr, $make:expr) => {
#[cfg(feature = $feature)]
{
let _ = ($id, $title);
row_features.insert($feature);
}
};
}
loadable_libs!(push_feature);
for feature in &row_features {
assert!(
cookbook_features.contains(*feature),
"`cookbook-all` does not enable `{feature}`"
);
}
let no_directory_rows = BTreeSet::from([
"citizen",
"cookbook",
"exec",
"gpu-math",
"interference",
"shape",
"discrete-rank",
"table-fs",
"table-http",
]);
for feature in cookbook_features {
assert!(
row_features.contains(feature) || no_directory_rows.contains(feature),
"`cookbook-all` enables `{feature}` without a loadable-lib directory row"
);
}
}
fn parse_feature<'a>(cargo_toml: &'a str, feature: &str) -> BTreeSet<&'a str> {
let prefix = format!("{feature} = [");
let line = cargo_toml
.lines()
.find(|line| line.starts_with(&prefix))
.expect("feature line");
line[prefix.len()..]
.trim_end_matches(']')
.split(',')
.map(str::trim)
.filter_map(|part| part.strip_prefix('"')?.strip_suffix('"'))
.collect()
}
}
```
### `feature/sim-sdk/gpu-math-composition`
Specimen `spec-test/sim-sdk/crates/sim-conformance/tests/spec/gpu_math` is checked by `cargo test`.
Source `crates/sim-conformance/tests/spec/gpu_math.rs`:
```rust
use sim::kernel::{Expr, Symbol};
use crate::support::CONFORMANCE_CONTRACT;
pub(crate) const GPU_MATH_PATH: &str = "crates/sim-conformance/tests/spec/gpu_math.rs";
#[test]
fn gpu_math_composition_reexports_canonical_components() {
assert_eq!(
GPU_MATH_PATH,
"crates/sim-conformance/tests/spec/gpu_math.rs"
);
assert!(CONFORMANCE_CONTRACT.contains(GPU_MATH_PATH));
assert_eq!(
sim::compute_model::compute_model_site_symbol().as_qualified_str(),
"site/compute/model"
);
assert_eq!(
sim::compute_femm::compute_femm_lib_symbol().as_qualified_str(),
"compute/femm-lib"
);
assert_eq!(
sim::numbers_tensor::tensor_site_symbol().as_qualified_str(),
"site/tensor"
);
assert_eq!(
sim::femm_solve::linear_solver_symbol().as_qualified_str(),
"femm/linear-solver"
);
}
#[test]
fn gpu_math_provider_swap_preserves_expression_structure() {
let modeled = gpu_math_expression(sim::compute_model::compute_model_site_symbol());
let automatic = gpu_math_expression(sim::compute_auto::compute_auto_site_symbol());
assert_eq!(
math_body(&modeled).canonical_key(),
math_body(&automatic).canonical_key()
);
assert_ne!(
placement(&modeled).canonical_key(),
placement(&automatic).canonical_key()
);
}
fn gpu_math_expression(site: Symbol) -> Expr {
Expr::Map(vec![
(
Expr::Symbol(Symbol::new("placement")),
Expr::Map(vec![(
Expr::Symbol(Symbol::new("site")),
Expr::Symbol(site),
)]),
),
(
Expr::Symbol(Symbol::new("math")),
Expr::List(vec![
Expr::Symbol(Symbol::qualified("tensor", "matmul")),
Expr::Symbol(Symbol::qualified("ode", "rk-fixed")),
Expr::Symbol(Symbol::qualified("femm", "resident-csr-solve")),
]),
),
])
}
fn math_body(expr: &Expr) -> &Expr {
map_value(expr, "math")
}
fn placement(expr: &Expr) -> &Expr {
map_value(expr, "placement")
}
fn map_value<'a>(expr: &'a Expr, key: &str) -> &'a Expr {
let Expr::Map(entries) = expr else {
panic!("expected map expression");
};
entries
.iter()
.find_map(|(candidate, value)| match candidate {
Expr::Symbol(symbol) if symbol.as_qualified_str() == key => Some(value),
_ => None,
})
.expect("map key present")
}
```
### `feature/sim-sdk/interference-composition`
Specimen `spec-test/sim-sdk/crates/sim-conformance/tests/spec/interference` is checked by `cargo test`.
Source `crates/sim-conformance/tests/spec/interference.rs`:
```rust
use std::sync::Arc;
use sim::{
interference_compute::{
InterferenceComputeLib, TensorStudyConfig, TensorStudySolver,
interference_compute_lib_symbol,
},
interference_core::{
Emitter, FieldAmplitude, Hertz, InterferenceProblem, MetresPerSecond, NepersPerMetre,
Point3M, PositiveMetres, Radians, SamplingPlane, ScalarMedium, SourceSet, UnitVector3,
},
interference_runtime::{
PlaneDescriptor, ProblemDescriptor, ScalarProjectionDescriptor, StudyDescriptor,
solve_function_symbol,
},
kernel::{
Args, CapabilityName, Consistency, Cx, Error, EvalFabric, EvalMode, EvalReply, EvalRequest,
Expr, NumberLiteral, ObjectCompat, Result, Symbol, Value,
},
lib_intent::{Origin, intent},
lib_view::{Operation, SurfaceCodec, surface},
view_interference::{
INTERFERENCE_PROJECT_CAPABILITY, INTERFERENCE_SOLVE_CAPABILITY, InterferenceSurfaceCodec,
},
};
use crate::support::{CONFORMANCE_CONTRACT, grant_capabilities, seated_cx};
pub(crate) const INTERFERENCE_PATH: &str = "crates/sim-conformance/tests/spec/interference.rs";
#[test]
fn interference_modeled_workflow_and_site_swap_compose_through_the_sdk() {
assert!(CONFORMANCE_CONTRACT.contains(INTERFERENCE_PATH));
let (mut cx, seat) = seated_cx();
grant_capabilities(
&seat,
&mut cx,
[
CapabilityName::new(INTERFERENCE_PROJECT_CAPABILITY),
CapabilityName::new(INTERFERENCE_SOLVE_CAPABILITY),
],
);
install_ci_sized_compute_provider(&mut cx);
cx.load_lib(&sim::compute_model::ComputeModelLib::new(
sim::compute_model::ModeledComputeProfile {
max_queue_depth: 64,
auto_flush_batches: true,
..sim::compute_model::ModeledComputeProfile::default()
},
))
.unwrap();
let solve = bound_solve_expression(&mut cx, 8, 8);
let solve_key = solve.canonical_key();
let modeled = solve_at_modeled_site(&mut cx, solve.clone());
assert_eq!(
modeled.evidence.provider,
Symbol::qualified("compute", "executor/model")
);
let codec = InterferenceSurfaceCodec::new();
let modeled_expr = modeled.as_expr(&mut cx).unwrap();
let scene = codec
.encode(&mut cx, &modeled_expr, &surface::preset("desktop").unwrap())
.unwrap();
assert!(sim::lib_scene::node_kind(&scene).is_some());
let project = checked_operation(
&codec,
&mut cx,
&modeled_expr,
edit(
&modeled_expr,
&["observable"],
Expr::Symbol(Symbol::new("phase")),
),
);
let projection = realize_operation(&mut cx, &project)
.object()
.downcast_ref::<ScalarProjectionDescriptor>()
.cloned()
.expect("project edit realizes the canonical projection record");
assert_eq!((projection.rows, projection.columns), (8, 8));
let model = checked_operation(
&codec,
&mut cx,
&modeled_expr,
edit(&modeled_expr, &["frequency"], number(686.0)),
);
let refreshed = realize_operation(&mut cx, &model)
.object()
.downcast_ref::<StudyDescriptor>()
.cloned()
.expect("model edit realizes a re-solved canonical Study");
assert_eq!(refreshed.problem.frequency_hz, 686.0);
let refreshed_expr = refreshed.as_expr(&mut cx).unwrap();
let refreshed_scene = codec
.encode(
&mut cx,
&refreshed_expr,
&surface::preset("desktop").unwrap(),
)
.unwrap();
assert!(sim::lib_scene::node_kind(&refreshed_scene).is_some());
let local = cx
.eval_expr(solve.clone())
.unwrap()
.object()
.downcast_ref::<StudyDescriptor>()
.cloned()
.expect("local placement returns a canonical Study");
assert_eq!(solve.canonical_key(), solve_key);
assert_ne!(local.evidence.provider, modeled.evidence.provider);
}
fn install_ci_sized_compute_provider(cx: &mut Cx) {
let default_provider = cx
.registry()
.libs()
.iter()
.find(|loaded| loaded.manifest.id == interference_compute_lib_symbol())
.map(|loaded| loaded.id)
.expect("standard install registered the interference compute library");
cx.unload_lib(default_provider).unwrap();
cx.load_lib(&InterferenceComputeLib::new(TensorStudySolver::new(
TensorStudyConfig {
min_accelerated_cells: 1,
..TensorStudyConfig::default()
},
)))
.unwrap();
}
fn bound_solve_expression(cx: &mut Cx, rows: usize, columns: usize) -> Expr {
let problem = InterferenceProblem::new(
Hertz::new(343.0).unwrap(),
ScalarMedium::new(
MetresPerSecond::new(343.0).unwrap(),
NepersPerMetre::new(0.01).unwrap(),
),
SourceSet::new(vec![Emitter::Point {
id: "sdk-source".to_owned(),
position: Point3M::from_metres(0.0, 0.0, 0.0).unwrap(),
amplitude_at_reference: FieldAmplitude::new(1.0).unwrap(),
phase: Radians::new(0.25).unwrap(),
}])
.unwrap(),
PositiveMetres::new(0.01).unwrap(),
);
let plane = SamplingPlane::new(
Point3M::from_metres(1.0, -0.125, -0.125).unwrap(),
UnitVector3::new(0.0, 1.0, 0.0).unwrap(),
UnitVector3::new(0.0, 0.0, 1.0).unwrap(),
PositiveMetres::new(0.25).unwrap(),
PositiveMetres::new(0.25).unwrap(),
rows,
columns,
)
.unwrap();
let problem_symbol = Symbol::qualified("sdk-conformance", "problem");
let plane_symbol = Symbol::qualified("sdk-conformance", "plane");
let problem_value = cx
.factory()
.opaque(Arc::new(ProblemDescriptor::from_problem(&problem)))
.unwrap();
let plane_value = cx
.factory()
.opaque(Arc::new(PlaneDescriptor::from_plane(plane)))
.unwrap();
cx.env_mut().define(problem_symbol.clone(), problem_value);
cx.env_mut().define(plane_symbol.clone(), plane_value);
Expr::Call {
operator: Box::new(Expr::Symbol(solve_function_symbol())),
args: vec![
Expr::Symbol(problem_symbol),
Expr::Symbol(plane_symbol),
Expr::Map(vec![
(
Expr::Symbol(Symbol::new("sampling")),
Expr::Symbol(Symbol::new("annotate")),
),
(
Expr::Symbol(Symbol::new("work-budget")),
Expr::Symbol(Symbol::new("default")),
),
]),
],
}
}
fn solve_at_modeled_site(cx: &mut Cx, expr: Expr) -> StudyDescriptor {
let site = cx
.registry()
.site_by_symbol(&sim::compute_model::compute_model_site_symbol())
.cloned()
.expect("modeled compute site is registered");
site.object()
.as_eval_fabric()
.expect("modeled compute Site implements EvalFabric")
.realize(cx, eval_request(expr))
.unwrap()
.value
.object()
.downcast_ref::<StudyDescriptor>()
.cloned()
.expect("modeled placement returns a canonical Study")
}
fn checked_operation(
codec: &InterferenceSurfaceCodec,
cx: &mut Cx,
base: &Expr,
submitted: Expr,
) -> Operation {
let draft = codec.decode(cx, base, &submitted).unwrap();
assert!(draft.committable, "submitted interference edit is valid");
codec.commit(cx, &draft).unwrap()
}
fn realize_operation(cx: &mut Cx, operation: &Operation) -> Value {
OperationFabric
.realize(
cx,
EvalRequest {
expr: operation.form.clone(),
result_shape: operation.result_shape.clone(),
required_capabilities: operation.required_capabilities.clone(),
..eval_request(Expr::Nil)
},
)
.unwrap()
.value
}
struct OperationFabric;
impl EvalFabric for OperationFabric {
fn realize(&self, cx: &mut Cx, request: EvalRequest) -> Result<EvalReply> {
for capability in &request.required_capabilities {
cx.require(capability)?;
}
let value = evaluate_operation(cx, request.expr)?;
if let Some(shape) = request.result_shape {
let matched = shape
.object()
.as_shape()
.expect("Operation result shape")
.check_value(cx, value.clone())?;
assert!(matched.accepted, "Operation result satisfies its Shape");
}
Ok(EvalReply {
value,
diagnostics: cx.take_diagnostics(),
trace: None,
})
}
}
fn evaluate_operation(cx: &mut Cx, form: Expr) -> Result<Value> {
let Expr::Call { operator, args } = form else {
return Err(Error::Eval(
"interference Operation must be a call".to_owned(),
));
};
let Expr::Symbol(function) = operator.as_ref() else {
return Err(Error::Eval(
"interference Operation requires a symbol operator".to_owned(),
));
};
let args = args
.iter()
.map(|arg| operation_argument(cx, arg))
.collect::<Result<Vec<_>>>()?;
cx.call_function(function, Args::new(args))
}
fn operation_argument(cx: &mut Cx, expr: &Expr) -> Result<Value> {
let Expr::Extension { tag, payload } = expr else {
return cx.eval_expr(expr.clone());
};
if *tag != Symbol::qualified("citizen", "read-construct") {
return cx.eval_expr(expr.clone());
}
let Expr::Vector(parts) = payload.as_ref() else {
return Err(Error::Eval(
"citizen read-construct payload must be a vector".to_owned(),
));
};
let Some((Expr::Symbol(class), args)) = parts.split_first() else {
return Err(Error::Eval(
"citizen read-construct must begin with a class symbol".to_owned(),
));
};
let args = args
.iter()
.map(|arg| sim::citizen::value_from_expr(cx, arg))
.collect::<Result<Vec<_>>>()?;
cx.read_construct(class, args)
}
fn edit(base: &Expr, path: &[&str], value: Expr) -> Expr {
intent(
"edit-field",
Origin::human(17),
vec![
("target", base.clone()),
(
"path",
Expr::List(
path.iter()
.map(|segment| Expr::Symbol(Symbol::new(*segment)))
.collect(),
),
),
("value", value),
],
)
}
fn number(value: f64) -> Expr {
Expr::Number(NumberLiteral {
domain: Symbol::new("f64"),
canonical: value.to_string(),
})
}
fn eval_request(expr: Expr) -> EvalRequest {
EvalRequest {
expr,
result_shape: None,
required_capabilities: Vec::new(),
deadline: None,
consistency: Consistency::LocalFirst,
mode: EvalMode::Eval,
answer_limit: None,
stream_buffer: None,
stream: false,
trace: false,
}
}
```
### `feature/sim-sdk/expression-tree-composition`
Specimen `spec-test/sim-sdk/crates/sim-conformance/tests/spec/expr_tree` is checked by `cargo test`.
Source `crates/sim-conformance/tests/spec/expr_tree.rs`:
```rust
use std::sync::Arc;
use sim::{
codec::{DecodePosition, DecodedForm, Input, decode_default_with_codec},
expr_tree::{
RECIPES, expr_tree_calculate_capability, expr_tree_mount_capability,
expr_tree_read_capability, expr_tree_write_capability, install_expr_tree_lib,
},
expr_tree_server::{ExpressionTreeServer, SessionId},
kernel::{
Consistency, Cx, EvalFabric, EvalMode, EvalRequest, Expr, NumberLiteral, ReadPolicy,
Symbol, Value,
},
lib_intent::{Origin, intent},
lib_server::{
DeterministicWallClock, EvalSite, ServerAddress, register_loopback_transport_endpoint,
},
lib_view::LensRegistry,
lib_web_bridge::{PhoneHost, RemoteTransport},
view_expr_tree::{
expression_tree_surface_codec_symbol, register_expression_tree_surface_codec,
},
};
use crate::support::{CONFORMANCE_CONTRACT, grant_capabilities, seated_cx};
pub(crate) const EXPR_TREE_PATH: &str = "crates/sim-conformance/tests/spec/expr_tree.rs";
const ADDRESS_THREAD: u64 = 17_029;
#[test]
fn expr_tree_recipe_restart_view_and_authority_compose_through_the_sdk() {
assert!(CONFORMANCE_CONTRACT.contains(EXPR_TREE_PATH));
let mut recipe_cx = full_runtime_cx();
let finite = eval_lisp(
&mut recipe_cx,
embedded_recipe("01-basics/finite-tree/setup.siml"),
);
let Expr::List(root_entries) = finite.object().as_expr(&mut recipe_cx).unwrap() else {
panic!("finite-tree recipe returns its bounded mixed-backend root");
};
assert_eq!(root_entries.len(), 3);
let finite_tree = eval_lisp(&mut recipe_cx, "(expr-tree/open \"recipe-finite-tree\")");
bind(&mut recipe_cx, "sdk-finite-tree", finite_tree);
assert_eq!(
eval_expr(
&mut recipe_cx,
"(expr-tree/ref sdk-finite-tree \"/measurements/trial-0001\")",
),
Expr::String("measured-value".to_owned())
);
let explanation = eval_lisp(
&mut recipe_cx,
embedded_recipe("02-calculation/automatic-and-directed/setup.siml"),
);
assert_eq!(
table_field_expr(&mut recipe_cx, &explanation, "status"),
Expr::Symbol(Symbol::qualified("expr-tree/status", "fresh"))
);
let calculation_tree = eval_lisp(
&mut recipe_cx,
"(expr-tree/open \"recipe-automatic-and-directed\")",
);
bind(&mut recipe_cx, "sdk-calculation-tree", calculation_tree);
assert_eq!(
eval_expr(
&mut recipe_cx,
"(expr-tree/ref sdk-calculation-tree \"/manual\")",
),
Expr::String("automatic-value".to_owned())
);
assert_eq!(
eval_expr(
&mut recipe_cx,
"(expr-tree/ref sdk-calculation-tree \"/cycle-a\")",
),
Expr::String("recovered".to_owned())
);
let address = ServerAddress::InProcess {
thread: ADDRESS_THREAD,
};
let active_server = Arc::new(new_server(address.clone(), 10));
let active_site: Arc<dyn EvalSite> = active_server.clone();
let endpoint = register_loopback_transport_endpoint(address.clone(), active_site).unwrap();
let mut creator = full_runtime_cx();
let session = active_server
.create_session(&mut creator, "sdk-expression-tree")
.unwrap();
assert_eq!(
realize_expr(
&active_server,
&mut creator,
runtime_call(
&session,
"new-cell",
vec![
Expr::String("/".to_owned()),
Expr::String("answer".to_owned()),
Expr::String("42".to_owned()),
],
),
),
Expr::String("/answer".to_owned())
);
let registry = view_registry();
let mut viewer_cx = read_runtime_cx();
let viewer_transport = connect(&mut viewer_cx, &address);
let mut viewer =
PhoneHost::with_surface_codec(viewer_transport, expression_tree_surface_codec_symbol());
let scene = viewer
.open(&mut viewer_cx, ®istry, session.resource())
.unwrap();
sim::lib_scene::validate_scene(&scene).unwrap();
let revision = active_server.revision(&session).unwrap();
let denied = viewer
.submit(
&mut viewer_cx,
®istry,
edit_source(&session, revision, "/answer", "forbidden"),
)
.unwrap_err();
assert!(
denied.to_string().contains("authority-denied"),
"server-backed view must preserve diminished read-only authority: {denied}"
);
assert_eq!(
realize_expr(
&active_server,
&mut creator,
runtime_call(&session, "ref", vec![Expr::String("/answer".to_owned())],),
),
Expr::String("42".to_owned())
);
drop(viewer);
drop(endpoint);
drop(active_server);
let restarted = Arc::new(new_server(address.clone(), 100));
let restarted_site: Arc<dyn EvalSite> = restarted.clone();
let _restarted_endpoint =
register_loopback_transport_endpoint(address.clone(), restarted_site).unwrap();
let mut restarted_cx = full_runtime_cx();
let stale = realize_expr(
&restarted,
&mut restarted_cx,
runtime_call(&session, "list", vec![Expr::String("/".to_owned())]),
);
assert_eq!(error_code(&stale).as_deref(), Some("unknown-session"));
let fresh = restarted
.create_session(&mut restarted_cx, "sdk-expression-tree-restarted")
.unwrap();
let mut reconnected_cx = read_runtime_cx();
let reconnected_transport = connect(&mut reconnected_cx, &address);
let mut reconnected = PhoneHost::with_surface_codec(
reconnected_transport,
expression_tree_surface_codec_symbol(),
);
let fresh_scene = reconnected
.open(&mut reconnected_cx, ®istry, fresh.resource())
.unwrap();
sim::lib_scene::validate_scene(&fresh_scene).unwrap();
}
fn embedded_recipe(path: &str) -> &'static str {
RECIPES
.iter()
.find_map(|(candidate, bytes)| {
(*candidate == path).then(|| {
std::str::from_utf8(bytes)
.unwrap_or_else(|error| panic!("embedded recipe {path} is not UTF-8: {error}"))
})
})
.unwrap_or_else(|| panic!("missing embedded expression-tree recipe {path}"))
}
fn full_runtime_cx() -> Cx {
runtime_cx(true)
}
fn read_runtime_cx() -> Cx {
runtime_cx(false)
}
fn runtime_cx(writable: bool) -> Cx {
let (mut cx, seat) = seated_cx();
let mut capabilities = vec![expr_tree_read_capability()];
if writable {
capabilities.extend([
expr_tree_write_capability(),
expr_tree_calculate_capability(),
expr_tree_mount_capability(),
]);
}
grant_capabilities(&seat, &mut cx, capabilities);
install_expr_tree_lib(&mut cx).unwrap();
cx
}
fn eval_lisp(cx: &mut Cx, source: &str) -> Value {
let decoded = decode_default_with_codec(
cx,
&Symbol::qualified("codec", "lisp"),
Input::Text(source.to_owned()),
ReadPolicy::default(),
DecodePosition::Eval,
)
.unwrap();
let expression = match decoded {
DecodedForm::Term(term) => Expr::from(term),
DecodedForm::Datum(datum) => Expr::from(datum),
};
cx.eval_expr(expression).unwrap()
}
fn eval_expr(cx: &mut Cx, source: &str) -> Expr {
eval_lisp(cx, source).object().as_expr(cx).unwrap()
}
fn bind(cx: &mut Cx, name: &str, value: Value) {
cx.env_mut().define(Symbol::new(name), value);
}
fn table_field_expr(cx: &mut Cx, table: &Value, name: &str) -> Expr {
table
.object()
.as_table_impl()
.expect("recipe explanation is a table")
.get(cx, Symbol::new(name))
.unwrap()
.object()
.as_expr(cx)
.unwrap()
}
fn new_server(address: ServerAddress, wall_start: u64) -> ExpressionTreeServer {
ExpressionTreeServer::new(
address,
vec![Symbol::qualified("codec", "lisp")],
Arc::new(DeterministicWallClock::new(wall_start, 1)),
Default::default(),
)
.unwrap()
}
fn request(expr: Expr) -> EvalRequest {
EvalRequest {
expr,
result_shape: None,
required_capabilities: Vec::new(),
deadline: None,
consistency: Consistency::LocalFirst,
mode: EvalMode::Eval,
answer_limit: None,
stream_buffer: None,
stream: false,
trace: false,
}
}
fn realize_expr(server: &ExpressionTreeServer, cx: &mut Cx, expr: Expr) -> Expr {
server
.realize(cx, request(expr))
.unwrap()
.value
.object()
.as_expr(cx)
.unwrap()
}
fn runtime_call(session: &SessionId, name: &str, args: Vec<Expr>) -> Expr {
let mut all = vec![Expr::Symbol(session.resource())];
all.extend(args);
Expr::Call {
operator: Box::new(Expr::Symbol(Symbol::qualified("expr-tree", name))),
args: all,
}
}
fn view_registry() -> LensRegistry {
let mut registry = LensRegistry::new();
register_expression_tree_surface_codec(&mut registry);
registry
}
fn connect(cx: &mut Cx, address: &ServerAddress) -> RemoteTransport {
let mut transport = RemoteTransport::local_server_address(
format!("in-process:{ADDRESS_THREAD}"),
address.clone(),
)
.with_offered_codecs(vec![Symbol::qualified("codec", "lisp")]);
transport.connect(cx).unwrap();
transport
}
fn edit_source(session: &SessionId, revision: u64, path: &str, source: &str) -> Expr {
intent(
"edit-field",
Origin::human(revision),
vec![
("target", target(session, revision, path)),
("path", Expr::List(vec![Expr::String("source".to_owned())])),
("value", Expr::String(source.to_owned())),
],
)
}
fn target(session: &SessionId, revision: u64, path: &str) -> Expr {
Expr::Map(vec![
(
Expr::Symbol(Symbol::new("tree")),
Expr::Symbol(session.resource()),
),
(
Expr::Symbol(Symbol::new("revision")),
Expr::Number(NumberLiteral {
domain: Symbol::new("u64"),
canonical: revision.to_string(),
}),
),
(
Expr::Symbol(Symbol::new("path")),
Expr::String(path.to_owned()),
),
])
}
fn error_code(expr: &Expr) -> Option<String> {
let Expr::Map(entries) = expr else {
return None;
};
entries.iter().find_map(|(key, value)| match (key, value) {
(Expr::Symbol(key), Expr::Symbol(value)) if key.as_qualified_str() == "error" => {
Some(value.name.to_string())
}
_ => None,
})
}
```
### `feature/sim-sdk/music-algorithm-composition`
Specimen `spec-test/sim-sdk/crates/sim-conformance/tests/spec/music_algorithms` is checked by `cargo test`.
Source `crates/sim-conformance/tests/spec/music_algorithms.rs`:
```rust
use sim::{discrete_search, music_consonance, music_counterpoint, pitch_ratio, signal};
use crate::support::CONFORMANCE_CONTRACT;
pub(crate) const MUSIC_ALGORITHMS_PATH: &str =
"crates/sim-conformance/tests/spec/music_algorithms.rs";
const FOUNDRY_LOAD_RECIPE: &str =
include_str!("../../../../recipes/music-algorithms/foundry-plan/input.lisp");
#[test]
fn frozen_music_candidate_graph_composes_through_the_sdk() {
assert!(CONFORMANCE_CONTRACT.contains(MUSIC_ALGORITHMS_PATH));
let transform = signal::TransformPlan::new(signal::TransformKind::Fft, 4);
transform
.validate()
.expect("explicit signal transform plan");
let control = discrete_search::SearchControl::default()
.with_max_work(500_000)
.with_max_frontier(20_000)
.with_max_results(8)
.with_seed(42);
assert_eq!(control.max_work, Some(500_000));
assert_eq!(control.max_frontier, Some(20_000));
assert_eq!(control.max_results, Some(8));
assert_eq!(control.seed, 42);
let fifth = pitch_ratio::PitchRatio::new(3, 2).expect("exact fifth");
assert_eq!((fifth.numerator(), fifth.denominator()), (3, 2));
assert_eq!(
music_consonance::ConsonancePolicy::default()
.pitch_models
.len(),
4
);
music_counterpoint::RuleSet::open()
.validate()
.expect("open counterpoint rules");
for library in [
"sim-lib-numbers-signal",
"sim-lib-discrete-search",
"sim-lib-pitch-ratio",
"sim-lib-music-consonance",
"sim-lib-music-counterpoint",
] {
assert!(
FOUNDRY_LOAD_RECIPE.contains(&format!("(load \"{library}\")")),
"foundry recipe must load {library}"
);
}
for plan_fact in [
"(music/algorithm-plan",
":analysis '(pitch-track beat key chords)",
":transform '(voice-lead harmonize counterpoint)",
":render '(smf wav)",
":budget {:work 500000 :frontier 20000 :results 8 :seed 42}",
"(realize plan :at 'local)",
] {
assert!(
FOUNDRY_LOAD_RECIPE.contains(plan_fact),
"foundry recipe must retain {plan_fact}"
);
}
}
```
### `feature/sim-sdk/serial-music-composition`
Specimen `recipe/sim-sdk/serial-music/row-matrix-analysis` is checked by `xtask check-recipes`.
Source `recipes/serial-music/row-matrix-analysis/recipe.toml`:
```toml
id = "row-matrix-analysis"
title = "Analyze a strict row family and matrix through the SDK facade"
codec = "rust"
setup = "setup.rs"
purpose = "purpose.md"
order = 10
tags = ["serial", "tone-row", "matrix", "sdk", "rust", "framework"]
requires = ["serial-music"]
```
Specimen `recipe/sim-sdk/serial-music/modal-realization` is checked by `xtask check-recipes`.
Source `recipes/serial-music/modal-realization/recipe.toml`:
```toml
id = "modal-realization"
title = "Realize one immutable serial plan through a registry-backed modal spine"
codec = "rust"
setup = "setup.rs"
purpose = "purpose.md"
order = 20
tags = ["serial", "modal", "adaptation", "sdk", "rust", "framework"]
requires = ["serial-music"]
```
Specimen `recipe/sim-sdk/serial-music/reversible-completion` is checked by `xtask check-recipes`.
Source `recipes/serial-music/reversible-completion/recipe.toml`:
```toml
id = "reversible-completion"
title = "Complete a serial statement reversibly through the SDK facade"
codec = "rust"
setup = "setup.rs"
purpose = "purpose.md"
order = 30
tags = ["serial", "completion", "reversible", "sdk", "rust", "framework"]
requires = ["serial-music"]
```
Specimen `recipe/sim-sdk/serial-music/index-discovery` is checked by `xtask check-recipes`.
Source `recipes/serial-music/index-discovery/recipe.toml`:
```toml
id = "index-discovery"
title = "Check serial facade feature and route discovery in the generated SDK index"
codec = "rust"
setup = "setup.rs"
purpose = "purpose.md"
order = 40
tags = ["serial", "index", "discovery", "sdk", "rust", "docs"]
requires = ["serial-music"]
```
Specimen `spec-test/sim-sdk/crates/sim-conformance/tests/spec/serial_music` is checked by `cargo test`.
Source `crates/sim-conformance/tests/spec/serial_music.rs`:
```rust
use std::collections::BTreeMap;
use std::sync::Arc;
use sim::discrete_search::{NeverInterrupt, SearchControl};
use sim::lib_music_core::{Articulation, Channel, Note, ObjectId, Pitch, StaffNote, Time};
use sim::lib_pitch_core::PitchClass;
use sim::serial_music::{
adaptation::default_realizer_registry,
completion::{
CompletionCandidate, CompletionRequest, NoteAddition, SerialCompletionAllowances,
SerialCompletionRequest, complete_serial,
},
practice::{
BuiltInPracticeRule, DeclaredWaivers, EventPlacement, OrdinalRef, PlannedSerialEvent,
PracticeId, PracticeRuleId, RowInstanceId, SerialEventId, SerialOrigin, SerialPlan,
SerialPractice, SerialRole, StrictEventSpec, StrictRealizationContext, StructuralLicense,
StructuralReadingId, realize_strict,
},
theory::{
ROW_MATRIX_SIZE, RowFamily, RowFamilySet, RowLabelConvention, RowMatrix, RowOperation,
ToneRow,
},
};
use crate::support::CONFORMANCE_CONTRACT;
pub(crate) const SERIAL_MUSIC_PATH: &str = "crates/sim-conformance/tests/spec/serial_music.rs";
const ROW_MATRIX_RECIPE: &str =
include_str!("../../../../recipes/serial-music/row-matrix-analysis/setup.rs");
const MODAL_RECIPE: &str =
include_str!("../../../../recipes/serial-music/modal-realization/setup.rs");
const COMPLETION_RECIPE: &str =
include_str!("../../../../recipes/serial-music/reversible-completion/setup.rs");
const SDK_FEATURES: &str = include_str!("../../../../features.toml");
#[test]
fn serial_music_facade_claims_reversibility_parity_and_discovery()
-> Result<(), Box<dyn std::error::Error>> {
assert!(CONFORMANCE_CONTRACT.contains(SERIAL_MUSIC_PATH));
assert!(SDK_FEATURES.contains("feature/sim-sdk/serial-music-composition"));
assert!(SDK_FEATURES.contains("route/compose-serial-music-from-sdk"));
let row = op25_row()?;
let family = RowFamilySet::of(&row);
assert_eq!(family.aliases().len(), 48);
let matrix = RowMatrix::new(&row, RowLabelConvention::FirstLastPitch);
assert_eq!(
matrix.render_data().cells().len(),
ROW_MATRIX_SIZE * ROW_MATRIX_SIZE
);
for snippet in [
"sim::serial_music::theory",
"RowFamilySet",
"RowMatrix",
"default_realizer_registry",
"complete_serial",
] {
assert!(
ROW_MATRIX_RECIPE.contains(snippet)
|| MODAL_RECIPE.contains(snippet)
|| COMPLETION_RECIPE.contains(snippet)
);
}
let plan = serial_plan()?;
let specs = strict_specs()?;
let realization = realize_strict(&plan, &StrictRealizationContext::new(specs))?;
let practice = SerialPractice::new(
PracticeId::new("practice/sdk-conformance-serial")?,
vec![
Arc::new(BuiltInPracticeRule::aggregate(PracticeRuleId::new(
"rule/aggregate",
)?)),
Arc::new(BuiltInPracticeRule::order(PracticeRuleId::new(
"rule/order",
)?)),
Arc::new(BuiltInPracticeRule::repeats(PracticeRuleId::new(
"rule/repeats",
)?)),
],
);
let result = complete_serial(
&realization,
&practice,
&DeclaredWaivers::default(),
&SerialCompletionRequest {
completion: CompletionRequest {
candidates: vec![CompletionCandidate::Note(NoteAddition {
note: note(
"voice/high",
"added-e",
64,
Time::from_integer(0),
quarter(),
),
})],
min_candidates: 1,
max_candidates: Some(1),
pitch_ranges: Vec::new(),
},
allowances: SerialCompletionAllowances::default(),
},
SearchControl::default(),
&NeverInterrupt,
)?;
assert_eq!(result.structural_plan, plan);
assert_eq!(result.structural_before, result.structural_after);
assert!(
result
.sounding_after
.entries()
.iter()
.any(|entry| entry.rule_id.as_str() == "rule/repeats")
);
let mut context = StrictRealizationContext::new(strict_specs()?);
context.modal_scale = Some(sim::lib_pitch_scale::PlayerScale::from_scale(
sim::lib_pitch_scale::Scale::dorian(PitchClass::C),
));
let registry = default_realizer_registry();
let modal = registry.realize_named("realizer/modal-degree-cycle", &plan, &context)?;
assert_eq!(modal.plan(), &plan);
assert!(modal.spine_report().is_some());
let missing = registry.realize_named("realizer/sdk-missing", &plan, &context);
let detail = format!("{missing:?}");
assert!(detail.contains("sdk-missing"));
Ok(())
}
fn op25_row() -> Result<ToneRow, Box<dyn std::error::Error>> {
Ok(ToneRow::try_from_classes([
PitchClass::E,
PitchClass::F,
PitchClass::G,
PitchClass::CS,
PitchClass::FS,
PitchClass::DS,
PitchClass::GS,
PitchClass::D,
PitchClass::B,
PitchClass::C,
PitchClass::A,
PitchClass::AS,
])?)
}
fn serial_plan() -> Result<SerialPlan, Box<dyn std::error::Error>> {
let row = op25_row()?.apply(RowOperation::new(RowFamily::P, 0));
let row_id = RowInstanceId::new("row/op25/p0")?;
let license = StructuralLicense::new(
StructuralReadingId::new("reading/sdk-conformance-serial")?,
"sdk serial conformance reading",
)?;
let event =
|id: &str, ordinal: usize| -> Result<PlannedSerialEvent, Box<dyn std::error::Error>> {
Ok(PlannedSerialEvent {
id: SerialEventId::new(id)?,
ordinals: vec![OrdinalRef::new(row_id.clone(), ordinal)],
role: SerialRole::Structural,
origin: SerialOrigin::Structural {
rationale: "sdk serial conformance statement".to_owned(),
},
voice: ObjectId::new("voice/high")?,
placement: EventPlacement::independent(),
parents: Vec::new(),
licenses: vec![license.clone()],
})
};
SerialPlan::try_new(
[(row_id.clone(), row)].into_iter().collect(),
[
event("event/a", 0)?,
event("event/b", 1)?,
event("event/c", 2)?,
event("event/d", 3)?,
event("event/e", 4)?,
event("event/f", 5)?,
event("event/g", 6)?,
event("event/h", 7)?,
event("event/i", 8)?,
event("event/j", 9)?,
event("event/k", 10)?,
event("event/l", 11)?,
]
.into_iter()
.map(|event| (event.id.clone(), event))
.collect(),
[
("event/a", "event/b"),
("event/b", "event/c"),
("event/c", "event/d"),
("event/d", "event/e"),
("event/e", "event/f"),
("event/f", "event/g"),
("event/g", "event/h"),
("event/h", "event/i"),
("event/i", "event/j"),
("event/j", "event/k"),
("event/k", "event/l"),
]
.into_iter()
.map(|(before, after)| Ok((SerialEventId::new(before)?, SerialEventId::new(after)?)))
.collect::<Result<Vec<_>, Box<dyn std::error::Error>>>()?,
)
.map_err(Into::into)
}
fn strict_specs() -> Result<BTreeMap<SerialEventId, StrictEventSpec>, Box<dyn std::error::Error>> {
let channel = Channel::new(0)?;
[
"event/a", "event/b", "event/c", "event/d", "event/e", "event/f", "event/g", "event/h",
"event/i", "event/j", "event/k", "event/l",
]
.into_iter()
.map(|id| {
Ok((
SerialEventId::new(id)?,
StrictEventSpec::notes(4, quarter(), 96, channel, Articulation::Normal),
))
})
.collect()
}
fn quarter() -> Time {
Time::new(1, 4)
}
fn note(voice_id: &str, event: &str, pitch: u8, onset: Time, duration: Time) -> StaffNote {
StaffNote {
voice_id: ObjectId::new(voice_id).expect("voice id"),
note_id: ObjectId::new(format!("note/{event}")).expect("note id"),
event_id: ObjectId::new(format!("event/{event}")).expect("event id"),
onset,
note: Note::new(
duration,
Pitch::from_midi(pitch),
96,
Channel::new(0).expect("channel"),
Articulation::Normal,
)
.expect("note"),
}
}
```
### `feature/sim-sdk/device-recipes`
Specimen `spec-test/sim-sdk/crates/sim-conformance/tests/spec/surface_protocol` is checked by `cargo test`.
Source `crates/sim-conformance/tests/spec/surface_protocol.rs`:
```rust
//! Conformance for the VIEW_4 surface protocol: the universal surface codec.
//!
//! VIEW_4 frames a view as a reversible codec at the open `surface` output
//! position. This spec pins the three checkable properties of that contract,
//! all reached through the public `sim` facade:
//!
//! 1. ROUNDTRIP -- a no-op edit preserves the value, for several baseline kinds.
//! 2. PROJECTION DETERMINISM -- for every surface preset, encoding is
//! deterministic and yields a valid Scene; `project_for_preset` is likewise
//! deterministic.
//! 3. GOLDEN -- the exact projected Scene for the `cli` and `watch` presets is
//! locked, so a regression in projection is caught.
use std::sync::Arc;
use sim::{
kernel::{Cx, DefaultFactory, EagerPolicy, Expr, Symbol},
lib_scene::{node, sym, validate_scene},
lib_view::{
UniversalEditor, UniversalView,
codec::{PairCodec, SurfaceCodec, roundtrip_holds},
profiles::project_for_preset,
surface::{self, SURFACE_PRESETS},
},
};
/// A bare runtime context: the surface codec needs no installed libraries.
fn surface_cx() -> Cx {
Cx::new(Arc::new(EagerPolicy), Arc::new(DefaultFactory))
}
/// The universal default surface codec under test.
fn universal_codec() -> PairCodec {
PairCodec::new(
Arc::new(UniversalView),
Arc::new(UniversalEditor::writable()),
)
}
/// One representative value per baseline kind: a string, a nil, a list, a map.
fn baseline_values() -> Vec<Expr> {
vec![
Expr::String("hello".to_owned()),
Expr::Nil,
Expr::List(vec![
Expr::Nil,
Expr::Bool(true),
Expr::String("x".to_owned()),
]),
Expr::Map(vec![
(Expr::Symbol(Symbol::new("a")), Expr::Bool(true)),
(Expr::Symbol(Symbol::new("b")), Expr::Nil),
]),
]
}
#[test]
fn surface_codec_roundtrip_holds_for_baseline_values() {
let mut cx = surface_cx();
let codec = universal_codec();
for value in baseline_values() {
assert!(
roundtrip_holds(&mut cx, &codec, &value).unwrap(),
"a no-op edit must preserve {value:?}"
);
}
}
#[test]
fn surface_projection_is_deterministic_and_valid_for_every_preset() {
let mut cx = surface_cx();
let codec = universal_codec();
assert!(
!SURFACE_PRESETS.is_empty(),
"the surface preset catalog must not be empty"
);
for value in baseline_values() {
for name in SURFACE_PRESETS {
let caps = surface::preset(name).unwrap_or_else(|| panic!("preset {name} must exist"));
let first = codec.encode(&mut cx, &value, &caps).unwrap();
let second = codec.encode(&mut cx, &value, &caps).unwrap();
assert_eq!(first, second, "{name} encode must be deterministic");
validate_scene(&first)
.unwrap_or_else(|err| panic!("{name} produced an invalid scene: {err}"));
// The profile-level projection is likewise deterministic per preset.
let projected_once = project_for_preset(&first, name)
.unwrap_or_else(|| panic!("project_for_preset must know {name}"));
let projected_twice = project_for_preset(&first, name).unwrap();
assert_eq!(
projected_once, projected_twice,
"{name} profile projection must be deterministic"
);
}
}
}
#[test]
#[ignore = "requires the generated constellation meta-workspace surface dependency set"]
fn surface_projection_matches_golden_for_cli_and_watch() {
let mut cx = surface_cx();
let codec = universal_codec();
let value = Expr::Nil;
// `cli` is a dense surface: projection keeps the whole universal Scene.
let cli = surface::preset("cli").unwrap();
let cli_scene = codec.encode(&mut cx, &value, &cli).unwrap();
assert_eq!(
cli_scene,
golden_universal_nil(),
"cli projection of nil regressed"
);
// `watch` is a glance surface: projection keeps one child, recursively.
let watch = surface::preset("watch").unwrap();
let watch_scene = codec.encode(&mut cx, &value, &watch).unwrap();
assert_eq!(
watch_scene,
golden_watch_nil(),
"watch projection of nil regressed"
);
// The golden also proves the two surfaces project the same value differently.
assert_ne!(
cli_scene, watch_scene,
"a glance surface must reduce where a dense one does not"
);
}
/// A `scene/text` node carrying exactly `text`.
fn text_line(text: &str) -> Expr {
node("text", vec![("text", Expr::String(text.to_owned()))])
}
/// The full, unreduced universal Scene for `nil` (the dense/`cli` golden).
fn golden_universal_nil() -> Expr {
node(
"stack",
vec![
("id", sym("universal")),
("dir", sym("column")),
(
"children",
Expr::List(vec![
golden_summary_card_nil(),
node(
"box",
vec![
("role", sym("structure")),
("children", Expr::List(vec![text_line("value: nil")])),
],
),
node(
"box",
vec![
("role", sym("canonical-text")),
(
"children",
Expr::List(vec![
text_line("nil"),
node(
"field",
vec![
("input-kind", sym("text")),
("value", Expr::String("nil".to_owned())),
("target", Expr::Nil),
("path", Expr::List(vec![])),
("readonly", Expr::Bool(false)),
],
),
]),
),
],
),
node(
"stack",
vec![
("role", sym("operations")),
("dir", sym("column")),
(
"children",
Expr::List(vec![
golden_action_button("copy", "Copy"),
golden_action_button("edit", "Edit"),
]),
),
],
),
]),
),
],
)
}
/// The summary card region of the universal Scene for `nil`.
fn golden_summary_card_nil() -> Expr {
node(
"box",
vec![
("role", sym("summary")),
(
"children",
Expr::List(vec![
text_line("kind: nil"),
text_line("label: nil"),
node(
"badge",
vec![
("status", sym("ok")),
("label", Expr::String("round-trips".to_owned())),
],
),
]),
),
],
)
}
/// An operations-inspector action button targeting `nil`.
fn golden_action_button(control: &str, label: &str) -> Expr {
node(
"button",
vec![
("control", sym(control)),
("label", Expr::String(label.to_owned())),
("target", Expr::Nil),
],
)
}
/// The glance-reduced universal Scene for `nil` (the `watch` golden): the top
/// stack keeps its first child, and that child keeps its own first child.
fn golden_watch_nil() -> Expr {
node(
"stack",
vec![
("id", sym("universal")),
("dir", sym("column")),
(
"children",
Expr::List(vec![node(
"box",
vec![
("role", sym("summary")),
("children", Expr::List(vec![text_line("kind: nil")])),
],
)]),
),
],
)
}
```
### `feature/sim-sdk/conformance-contract`
Specimen `spec-test/sim-sdk/crates/sim-conformance/tests/spec` is checked by `cargo test`.
Source `crates/sim-conformance/tests/spec.rs`:
```rust
//! Executable conformance checks for the architecture claims in `SIM.md`.
//!
//! The stream-cassette assertions validate the in-memory `to_expr`/`from_expr`
//! serialization round-trip and the structural invariants a cassette must
//! satisfy to be publishable as a golden fixture. They do not compare against a
//! committed `.simcassette` corpus on disk; `validate_golden_fixture` checks a
//! cassette's invariants against a target publish path without reading a file.
use std::sync::Arc;
use sim::{
codec::{Input, decode_with_codec},
kernel::{
Args, CapabilitySet, Cx, DefaultFactory, ExportKind, ExportState, Expr, LibSource,
LibTarget, NeedPolicy, NumberLiteral, ReadPolicy, Symbol, TrustLevel,
macro_expand_eval_capability, read_construct_capability, read_eval_capability,
},
};
#[path = "conformance_support/mod.rs"]
mod conformance_support;
#[path = "spec/expr_tree.rs"]
mod expr_tree;
#[path = "spec/forge_author.rs"]
mod forge_author;
#[path = "spec/forge_eval.rs"]
mod forge_eval;
#[path = "spec/gpu_math.rs"]
mod gpu_math;
#[path = "spec/instrument_streams.rs"]
mod instrument_streams;
#[path = "spec/interference.rs"]
mod interference;
#[path = "spec/music_algorithms.rs"]
mod music_algorithms;
#[path = "spec/rust_intelligence.rs"]
mod rust_intelligence;
#[path = "spec/serial_music.rs"]
mod serial_music;
#[path = "spec/stream_matrix.rs"]
mod stream_matrix;
#[path = "spec/support.rs"]
mod support;
#[path = "spec/surface_protocol.rs"]
mod surface_protocol;
use support::*;
#[test]
fn sim_md_declares_conformance_backing() {
let contract = normalized_conformance_contract();
assert!(contract.contains("`sim-conformance`"));
assert!(contract.contains("public facade only"));
assert!(contract.contains("stream transport conformance"));
assert!(contract.contains(stream_matrix::MATRIX_PATH));
}
#[test]
fn every_general_codec_roundtrips_every_expr_variant() {
let mut cx = cx();
let exprs = expr_corpus();
assert_expr_coverage(&exprs);
for codec in codec_symbols() {
for expr in &exprs {
let encoded = encode_once(&mut cx, &codec, expr);
let decoded = decode_once(&mut cx, &codec, encoded);
assert_eq!(
decoded, *expr,
"codec {codec} failed to round-trip {expr:?}"
);
}
}
}
#[test]
fn every_registered_class_exposes_callable_class_protocol() {
let cx = cx();
let class_symbols = cx.registry().classes().keys().cloned().collect::<Vec<_>>();
assert!(!class_symbols.is_empty());
let mut checked_class_protocol = std::collections::BTreeSet::new();
let mut marker_exports = std::collections::BTreeSet::new();
for symbol in class_symbols {
let class = cx.resolve_class(&symbol).unwrap();
if class.object().as_class().is_some() {
checked_class_protocol.insert(symbol.clone());
assert!(
class.object().as_callable().is_some(),
"{symbol} must be callable as its constructor"
);
} else {
marker_exports.insert(symbol.clone());
}
}
for symbol in [
q("core", "Class"),
q("core", "Function"),
q("core", "Number"),
] {
assert!(
checked_class_protocol.contains(&symbol),
"{symbol} must expose the full class protocol"
);
}
assert!(marker_exports.contains(&q("numbers", "tensor-literal")));
}
#[test]
fn public_class_constructor_constructs_instance() {
let mut cx = cx();
let lib = marker_class_lib(&mut cx);
cx.load_lib(&lib).unwrap();
let value = cx
.call_class(&marker_symbol(), Args::new(Vec::new()))
.unwrap();
let class = value.object().class(&mut cx).unwrap();
assert_eq!(
class.object().as_expr(&mut cx).unwrap(),
Expr::Symbol(marker_symbol())
);
}
#[test]
fn number_domains_named_by_sim_parse_and_promote_through_lattice() {
let mut cx = cx();
for (text, domain) in [
("1.5", q("numbers", "f64")),
("42", q("numbers", "i64")),
("1/2", q("numbers", "rational")),
("1000000000000000000000000", q("numbers", "bigint")),
("1+2i", q("numbers", "complex")),
] {
let literal = cx.parse_number_literal(text).unwrap().unwrap();
assert_eq!(literal.domain, domain, "{text} parsed into wrong domain");
}
let value = cx
.call_function(
&q("math", "add"),
Args::new(vec![
cx.factory()
.number_literal(q("numbers", "f64"), "1.5".to_owned())
.unwrap(),
cx.factory()
.number_literal(q("numbers", "complex"), "0.5+2i".to_owned())
.unwrap(),
]),
)
.unwrap();
assert_eq!(
value.object().as_expr(&mut cx).unwrap(),
Expr::Number(NumberLiteral {
domain: q("numbers", "complex"),
canonical: "2+2i".to_owned(),
})
);
assert_lattice_reaches(&cx, q("numbers", "i64"), q("numbers", "rational"));
assert_lattice_reaches(&cx, q("numbers", "bigint"), q("numbers", "rational"));
assert_lattice_reaches(&cx, q("numbers", "complex"), q("numbers", "cas"));
}
#[test]
fn read_eval_is_capability_and_trust_gated_separately_from_read_construct() {
let (mut cx, seat) = seated_cx();
let denied = decode_with_codec(
&mut cx,
&q("codec", "lisp"),
Input::Text("#eval(1)".to_owned()),
ReadPolicy::default(),
);
assert!(matches!(
denied,
Err(sim::kernel::Error::CapabilityDenied { capability })
if capability == read_eval_capability()
));
let untrusted = decode_with_codec(
&mut cx,
&q("codec", "lisp"),
Input::Text("#eval(1)".to_owned()),
ReadPolicy {
trust: TrustLevel::Untrusted,
capabilities: CapabilitySet::new().grant(read_eval_capability()),
},
);
assert!(matches!(
untrusted,
Err(sim::kernel::Error::TrustDenied { capability, trust })
if capability == read_eval_capability() && trust == TrustLevel::Untrusted
));
grant_capability(&seat, &mut cx, macro_expand_eval_capability());
let allowed = decode_with_codec(
&mut cx,
&q("codec", "lisp"),
Input::Text("#eval(1)".to_owned()),
ReadPolicy {
trust: TrustLevel::HostInternal,
capabilities: CapabilitySet::new().grant(read_eval_capability()),
},
)
.unwrap();
match allowed {
Expr::Number(number) => assert_eq!(number.canonical, "1"),
other => panic!("expected read-eval number, got {other:?}"),
}
let lib = marker_class_lib(&mut cx);
cx.load_lib(&lib).unwrap();
let read_construct_policy = ReadPolicy {
trust: TrustLevel::HostInternal,
capabilities: CapabilitySet::new().grant(read_construct_capability()),
};
let read_construct_denied = decode_with_codec(
&mut cx,
&q("codec", "lisp"),
Input::Text("#(ConformanceMarker)".to_owned()),
ReadPolicy::default(),
);
assert!(matches!(
read_construct_denied,
Err(sim::kernel::Error::CapabilityDenied { capability })
if capability == read_construct_capability()
));
grant_capability(&seat, &mut cx, read_construct_capability());
decode_with_codec(
&mut cx,
&q("codec", "lisp"),
Input::Text("#(ConformanceMarker)".to_owned()),
read_construct_policy.clone(),
)
.unwrap();
let read_eval_inside_construct = decode_with_codec(
&mut cx,
&q("codec", "lisp"),
Input::Text("#(ConformanceMarker #eval(1))".to_owned()),
read_construct_policy,
);
assert!(matches!(
read_eval_inside_construct,
Err(sim::kernel::Error::CapabilityDenied { capability })
if capability == read_eval_capability()
));
}
#[test]
fn eval_policies_named_by_runtime_exist() {
let mut cx = Cx::new(Arc::new(NeedPolicy), Arc::new(DefaultFactory));
sim::runtime::install_core_runtime(&mut cx);
let policies = cx
.call_function(&q("core", "eval-policies"), Args::new(Vec::new()))
.unwrap();
let Expr::List(entries) = policies.object().as_expr(&mut cx).unwrap() else {
panic!("expected eval policy entries");
};
for policy in ["eager", "lazy", "lazy-by-need", "strict-by-shape", "hybrid"] {
assert!(entries.iter().any(|entry| {
table_value(entry, &Symbol::new("id")) == Some(&Expr::Symbol(q("core", policy)))
}));
}
}
#[test]
fn loader_backends_named_by_runtime_are_available() {
let mut cx = cx();
let registry = sim::loaders::standard_loader_registry();
let host_lib = marker_class_lib(&mut cx);
let manifest = registry
.inspect_manifest(&mut cx, LibSource::Host(Box::new(host_lib)))
.unwrap();
assert_eq!(manifest.target, LibTarget::HostRegistered);
assert_loader_selected(
registry.load_lib(&mut cx, sim::loaders::path_source("missing.l8b")),
"binary-precompiled-lib",
);
assert_loader_selected(
registry.load_lib(&mut cx, sim::loaders::path_source("missing.lisp")),
"lisp-source",
);
assert_loader_selected(
registry.load_lib(
&mut cx,
sim::loaders::path_source(format!("missing.{}", std::env::consts::DLL_EXTENSION)),
),
"native-dylib",
);
let wasm_registry = sim::loaders::standard_loader_registry_with_wasm(Arc::new(
sim::wasm_abi::InMemoryWasmRuntime::new(),
));
assert_loader_selected(
wasm_registry.load_lib(&mut cx, sim::loaders::path_source("missing.wasm")),
"wasm-abi-module",
);
}
#[test]
fn wasm_abi_v1_executes_functions_and_marks_richer_exports_unsupported() {
let mut cx = cx();
let lib = StubWasmExportsLib {
exports: vec![
sim::wasm_abi::WasmExport::Function {
symbol: q("wasm-test", "call"),
},
sim::wasm_abi::WasmExport::Class {
symbol: q("wasm-test", "Class"),
constructor: None,
},
sim::wasm_abi::WasmExport::Codec {
symbol: q("codec", "wasm-test"),
},
sim::wasm_abi::WasmExport::Shape {
symbol: q("wasm-test", "Shape"),
},
sim::wasm_abi::WasmExport::NumberDomain {
symbol: q("numbers", "wasm-test"),
},
],
};
cx.load_lib(&lib).unwrap();
let function = cx.resolve_function(&q("wasm-test", "call")).unwrap();
assert!(function.object().as_callable().is_some());
let loaded = cx.registry().lib(&q("wasm-test", "abi")).unwrap();
assert_export_state(
loaded,
ExportKind::FUNCTION,
q("wasm-test", "call"),
|state| matches!(state, ExportState::Resolved { .. }),
);
for (kind, symbol, reason) in [
(
ExportKind::CLASS,
q("wasm-test", "Class"),
"class runtime exports",
),
(
ExportKind::CODEC,
q("codec", "wasm-test"),
"codec runtime exports",
),
(
ExportKind::SHAPE,
q("wasm-test", "Shape"),
"shape runtime exports",
),
(
ExportKind::NUMBER_DOMAIN,
q("numbers", "wasm-test"),
"number-domain runtime exports",
),
] {
assert_export_state(
loaded,
kind,
symbol,
|state| matches!(state, ExportState::Unsupported { reason: found } if found.contains(reason)),
);
}
assert!(CONFORMANCE_CONTRACT.contains("wasm ABI scope"));
}
#[test]
fn conformance_contract_describes_current_scope() {
let contract = normalized_conformance_contract();
for phrase in [
"codec totality",
"class semantics",
"number-domain replaceability",
"capability gating",
"eval policy",
"loader behavior",
"reversible library lifecycle",
"boot receipt replay",
"wasm ABI scope",
"stream transport conformance",
] {
assert!(
contract.contains(phrase),
"missing conformance scope phrase: {phrase}"
);
}
}
#[test]
fn stream_cassettes_replay_and_round_trip_through_codecs_and_publish_invariants() {
use sim::lib_server::FrameEnvelope;
use sim::lib_stream_combinators::{Stream, record_cassette_bang, replay_cassette};
use sim::lib_stream_core::{
ClockDomain, StreamMedia, StreamPacket, StreamValue, TransportProfile,
stream_remote_network_capability,
};
use sim::lib_stream_fabric::{
cassette_to_stream_frames, stream_frames_to_cassette, stream_frames_to_stream,
stream_to_frames,
};
use sim::lib_stream_host::{FakeBackend, HostBackendRegistry, HostCallbackCassette};
use sim::lib_web_bridge::{FixtureTransport, Transport};
let mut serde_cx = cx();
let midi_items = vec![midi_item(0), midi_item(240)];
let memory = Stream::pull(
conformance_metadata(
"stream/conformance-memory",
StreamMedia::Midi,
ClockDomain::MidiTick,
),
midi_items.clone(),
);
let cassette = record_cassette_bang(&memory, TransportProfile::lan_midi_control()).unwrap();
assert_eq!(
replay_cassette(&cassette).unwrap().take_packets(4).unwrap(),
midi_items
);
assert_publishable_fixture(
&mut serde_cx,
&cassette,
"fixtures/streams/golden/conformance-midi.simcassette",
);
let mut registry = HostBackendRegistry::new();
registry.register(FakeBackend::new()).unwrap();
let opened = registry
.open(FakeBackend::data_request(4).unwrap())
.unwrap();
let mut host = HostCallbackCassette::new();
host.record_packet(StreamPacket::data(
q("stream/data", "expr"),
Expr::String("host callback".to_owned()),
));
let shared_host = host
.to_stream_cassette(
opened.config().metadata(),
TransportProfile::remote_stream_fabric(),
)
.unwrap();
HostCallbackCassette::from_stream_cassette(&shared_host)
.unwrap()
.replay(opened.queue())
.unwrap();
assert_eq!(opened.queue().drain(4).unwrap().len(), 1);
let (mut fabric_cx, fabric_seat) = seated_cx();
grant_capability(
&fabric_seat,
&mut fabric_cx,
stream_remote_network_capability(),
);
let server_stream = StreamValue::pull(
conformance_metadata(
"stream/conformance-server",
StreamMedia::Midi,
ClockDomain::MidiTick,
),
vec![midi_item(0), midi_item(240)],
);
let frames = stream_to_frames(&mut fabric_cx, &server_stream, q("codec", "lisp")).unwrap();
let server_cassette = stream_frames_to_cassette(&mut fabric_cx, &frames).unwrap();
let replay_frames = cassette_to_stream_frames(
&mut fabric_cx,
&server_cassette,
q("codec", "lisp"),
FrameEnvelope::default(),
)
.unwrap();
let server_replay = stream_frames_to_stream(&mut fabric_cx, &replay_frames).unwrap();
assert_eq!(server_replay.take_packets(4).unwrap().len(), 2);
let pcm_items = vec![pcm_item(1.0), pcm_item(-1.0)];
let pcm_stream = StreamValue::pull(
conformance_metadata(
"stream/conformance-web",
StreamMedia::Pcm,
ClockDomain::BrowserFrame,
),
pcm_items.clone(),
);
let preview = sim::lib_stream_file::stream_to_cassette(
&pcm_stream,
TransportProfile::lan_buffered_audio_preview(),
)
.unwrap();
let preview_stream = sim::lib_stream_file::cassette_expr_to_stream(&preview.to_expr()).unwrap();
assert_eq!(preview_stream.take_packets(4).unwrap(), pcm_items);
let mut web = FixtureTransport::new()
.with_finite_stream(preview.metadata().clone(), preview.items().unwrap());
let mut web_cx = cx();
let inspector = web
.stream_subscribe(&mut web_cx, preview.metadata().id())
.unwrap();
assert_eq!(inspector.buffered, 2);
assert_eq!(
web.stream_read(&mut web_cx, preview.metadata().id(), 4)
.unwrap()
.len(),
2
);
assert_publishable_fixture(
&mut serde_cx,
&preview,
"fixtures/streams/golden/web-preview.simcassette",
);
}
/// Asserts a cassette is a publishable golden fixture and survives serialization.
///
/// First checks the structural invariants a cassette must satisfy to be
/// published as a golden fixture at `target_path` (finite trace, sequenced
/// envelopes, replay- or preview-only transport, and no unredacted payload or
/// host-device name). No `.simcassette` file is read; `validate_golden_fixture`
/// validates the in-memory cassette against the target path. Then it exercises
/// the real regression guard: the cassette's `to_expr`/`from_expr` serialization
/// round-trips losslessly through the general-purpose lisp codec.
fn assert_publishable_fixture(
cx: &mut Cx,
cassette: &sim::lib_stream_core::StreamCassette,
target_path: &str,
) {
cassette
.validate_golden_fixture(target_path)
.unwrap_or_else(|err| panic!("{target_path}: cassette fails publish invariants: {err:?}"));
assert_cassette_round_trips(cx, cassette, target_path);
}
/// Round-trips a cassette through `to_expr` -> lisp codec -> `from_expr`.
///
/// Asserts the serialized form survives the codec byte-for-structure and that
/// deserialization reconstructs an equal cassette form. A regression in the
/// cassette format or the lisp codec fails this guard.
fn assert_cassette_round_trips(
cx: &mut Cx,
cassette: &sim::lib_stream_core::StreamCassette,
label: &str,
) {
let expr = cassette.to_expr();
let encoded = encode_once(cx, &q("codec", "lisp"), &expr);
let decoded = decode_once(cx, &q("codec", "lisp"), encoded);
assert_eq!(
decoded, expr,
"{label}: cassette serialization did not survive the lisp codec"
);
let restored = sim::lib_stream_core::StreamCassette::from_expr(&decoded)
.unwrap_or_else(|err| panic!("{label}: cassette failed to deserialize: {err:?}"));
assert_eq!(
restored.to_expr(),
expr,
"{label}: cassette did not deserialize to an equal form"
);
}
#[test]
fn stream_security_capabilities_limits_and_redaction_are_conformant() {
use sim::lib_stream_core::{
ClockDomain, StreamCassette, StreamItem, StreamMedia, StreamPacket, StreamRedactionFinding,
StreamRemoteLimits, StreamSecurityPolicy, StreamStats, TransportProfile,
stream_redaction_finding_symbols, stream_security_capability_names,
};
assert_eq!(
stream_security_capability_names()
.into_iter()
.map(|capability| capability.as_str().to_owned())
.collect::<Vec<_>>(),
vec![
"stream.open",
"stream.read",
"stream.push",
"stream.cancel",
"stream.stats",
"stream.remote.preview",
"stream.remote.render",
"stream.lan.midi",
"stream.host.device",
"stream.remote.network",
]
);
assert_eq!(
stream_redaction_finding_symbols()
.into_iter()
.map(|symbol| symbol.as_qualified_str())
.collect::<Vec<_>>(),
vec![
"stream/redaction/private-path",
"stream/redaction/host-name",
"stream/redaction/absolute-path",
"stream/redaction/credential",
"stream/redaction/patch-bank-payload",
"stream/redaction/large-binary-data",
]
);
let limits = StreamRemoteLimits::default();
assert_eq!(limits.max_frame_payload_bytes, 1024 * 1024);
assert_eq!(limits.max_stream_frames, 1024);
assert_eq!(limits.max_inflight_frames, 64);
assert_eq!(limits.max_duration_ms, 60_000);
assert_eq!(limits.max_rate_hz, 120);
assert_eq!(limits.max_binary_payload_bytes, 256 * 1024);
assert_eq!(limits.effective_frame_limit(), 1024);
assert!(
limits
.validate_profile(&TransportProfile::remote_stream_fabric())
.is_ok()
);
assert!(
limits
.validate_profile(&TransportProfile::realtime_local_audio())
.is_err()
);
let policy = StreamSecurityPolicy::default();
assert_eq!(
policy.finding_for_expr(&Expr::String("token=abc123".to_owned())),
Some(StreamRedactionFinding::Credential)
);
assert_eq!(
policy.finding_for_expr(&Expr::String("https://sim.example/stream".to_owned())),
Some(StreamRedactionFinding::HostName)
);
let cassette = StreamCassette::from_items(
conformance_metadata(
"stream/conformance-security",
StreamMedia::Data,
ClockDomain::ServerFrame,
),
vec![StreamItem::new(StreamPacket::data(
q("stream/data", "expr"),
Expr::Map(vec![
(
Expr::Symbol(Symbol::new("path")),
Expr::String("private-path=session.mid".to_owned()),
),
(
Expr::Symbol(Symbol::new("bank")),
Expr::String("dx7 patch-bank payload".to_owned()),
),
]),
))],
TransportProfile::remote_stream_fabric(),
StreamStats::default(),
)
.unwrap();
// The unredacted cassette must fail the publish invariants (it carries a
// private path and a patch-bank payload). Redacting it produces a
// publishable golden fixture that also survives the serialization round-trip.
assert!(
cassette
.validate_golden_fixture("fixtures/streams/golden/conformance-security.simcassette")
.is_err()
);
let mut serde_cx = cx();
assert_publishable_fixture(
&mut serde_cx,
&cassette.redacted().unwrap(),
"fixtures/streams/golden/conformance-security.simcassette",
);
}
fn conformance_metadata(
id: &str,
media: sim::lib_stream_core::StreamMedia,
clock: sim::lib_stream_core::ClockDomain,
) -> sim::lib_stream_core::StreamMetadata {
sim::lib_stream_core::StreamMetadata::new(
Symbol::new(id),
media,
sim::lib_stream_core::StreamDirection::Source,
clock.symbol(),
sim::lib_stream_core::BufferPolicy::bounded(8).unwrap(),
)
}
fn midi_item(ticks: i64) -> sim::lib_stream_core::StreamItem {
sim::lib_stream_core::StreamItem::new(sim::lib_stream_core::StreamPacket::Midi(
sim::lib_stream_core::MidiPacket::new(vec![
sim::lib_stream_core::MidiPacketEvent::new(ticks, 480, vec![0x90, 60, 100]).unwrap(),
])
.unwrap(),
))
}
fn pcm_item(value: f32) -> sim::lib_stream_core::StreamItem {
sim::lib_stream_core::StreamItem::new(sim::lib_stream_core::StreamPacket::Pcm(
sim::lib_stream_core::PcmPacket::f32(1, 1, vec![value]).unwrap(),
))
}
```