commit 6a4f55616684d0b595ef1e0479abfd8ab2152692
parent b7cf74e494e703864fefd4a873b1177341c31721
Author: triesap <tyson@radroots.org>
Date: Mon, 3 Aug 2026 12:14:17 +0000
sdk: migrate workspace consumers
- retire the xtask smoke consumer of removed SDK knowledge APIs
- keep only the final clean-host SDK smoke command surface
- record the intentional zero-dependent canonical workspace checkpoint
- defer separate CLI Studio mobile and daemon capsules to RCLD70
Diffstat:
3 files changed, 35 insertions(+), 228 deletions(-)
diff --git a/docs/implementation/SDK_WORKSPACE_CONSUMERS.md b/docs/implementation/SDK_WORKSPACE_CONSUMERS.md
@@ -0,0 +1,27 @@
+# SDK canonical-workspace consumer cutover
+
+Step 246 evaluated every Cargo package in the standalone SDK workspace before
+the ordinary-user facade was activated. Cargo metadata reports no package with
+a dependency on `radroots_sdk` at this checkpoint. That zero-dependent state is
+intentional:
+
+- `radroots` remains the pulled-forward, dependency-free scaffold until Steps
+ 250–253 establish its curated modules, builders, and feature forwarding.
+- binding and WASM packages consume their owning lower crates and do not route
+ through the native advanced-host SDK.
+- the xtask clean-host smoke now uses only the final `ClientBuilder` and
+ `ErrorKind` surface. Its predecessor knowledge smoke, which referenced
+ removed SDK features and prefixed types, is retired.
+- CLI, Studio, FFI/mobile, daemon, and other application capsules are separate
+ repositories/checkouts. Their ordered migrations remain assigned to Steps
+ 269–294 and are not folded into this standalone repository step.
+
+The package-owned predecessor examples and inactive integration sources under
+`crates/sdk` are not Cargo consumers because the manifest sets `autotests =
+false` and `autoexamples = false`. They remain quarantined only until the
+ordered documentation and package-surface cleanup in Steps 247–248; they are
+not compiled, exported, or authorized as compatibility APIs.
+
+No compatibility alias or feature was added for an external consumer. The
+next consumer edge created in this repository must be the exact `radroots ->
+radroots_sdk` dependency and forwarding contract specified for the facade.
diff --git a/tools/xtask/src/main.rs b/tools/xtask/src/main.rs
@@ -90,7 +90,7 @@ fn command_action(args: &[String]) -> Result<CommandAction<'_>, String> {
}
fn usage() -> String {
- "usage: cargo xtask architecture | cargo xtask architecture-ci | cargo xtask check-api-boundaries | cargo xtask check-dependency-boundaries | cargo xtask generate | cargo xtask generate ts | cargo xtask generate wasm [--package <key>] | cargo xtask generate package-metadata | cargo xtask check | cargo xtask smoke sdk-rust-local | cargo xtask smoke knowledge-rust-local | cargo xtask coverage run"
+ "usage: cargo xtask architecture | cargo xtask architecture-ci | cargo xtask check-api-boundaries | cargo xtask check-dependency-boundaries | cargo xtask generate | cargo xtask generate ts | cargo xtask generate wasm [--package <key>] | cargo xtask generate package-metadata | cargo xtask check | cargo xtask smoke sdk-rust-local | cargo xtask coverage run"
.to_owned()
}
diff --git a/tools/xtask/src/smoke.rs b/tools/xtask/src/smoke.rs
@@ -8,11 +8,7 @@ use crate::{
pub fn run(args: &[String]) -> Result<(), String> {
match args {
[target] if target == "sdk-rust-local" => sdk_rust_local(),
- [target] if target == "knowledge-rust-local" => knowledge_rust_local(),
- _ => Err(
- "usage: cargo xtask smoke sdk-rust-local | cargo xtask smoke knowledge-rust-local"
- .to_owned(),
- ),
+ _ => Err("usage: cargo xtask smoke sdk-rust-local".to_owned()),
}
}
@@ -86,36 +82,6 @@ radroots_sdk = {{ path = {sdk_path}, default-features = true }}
Ok(manifest)
}
-fn knowledge_rust_local() -> Result<(), String> {
- let root = workspace_root()?;
- let sdk_path = root.join("crates/sdk");
- let toolchain = resolve_rust_toolchain(&root)?;
- let nostr_version = exact_workspace_dependency_pin(&root.join("Cargo.toml"), "nostr")?;
- let tempdir =
- tempfile::tempdir().map_err(|error| format!("failed to create smoke tempdir: {error}"))?;
- write_consumer(
- &tempdir.path().join("Cargo.toml"),
- &sdk_path,
- &nostr_version,
- )?;
- let src_dir = tempdir.path().join("src");
- fs::create_dir_all(&src_dir)
- .map_err(|error| format!("failed to create {}: {error}", src_dir.display()))?;
- fs::write(src_dir.join("main.rs"), CONSUMER_MAIN)
- .map_err(|error| format!("failed to write smoke consumer main.rs: {error}"))?;
- let mut command = smoke_cargo_check_command(tempdir.path(), &toolchain);
- let status = command
- .status()
- .map_err(|error| format!("failed to run smoke cargo check: {error}"))?;
- if status.success() {
- Ok(())
- } else {
- Err(format!(
- "knowledge Rust local smoke failed with status {status}"
- ))
- }
-}
-
fn smoke_cargo_check_command(path: &Path, toolchain: &ResolvedRustToolchain) -> Command {
let mut command = Command::new(&toolchain.cargo);
command.arg("check").arg("--quiet").current_dir(path);
@@ -123,164 +89,6 @@ fn smoke_cargo_check_command(path: &Path, toolchain: &ResolvedRustToolchain) ->
command
}
-fn write_consumer(path: &Path, sdk_path: &Path, nostr_version: &str) -> Result<(), String> {
- let cargo_toml = render_consumer_manifest(sdk_path, nostr_version)?;
- fs::write(path, cargo_toml)
- .map_err(|error| format!("failed to write {}: {error}", path.display()))
-}
-
-fn render_consumer_manifest(sdk_path: &Path, nostr_version: &str) -> Result<String, String> {
- let sdk_path = serde_json::to_string(&sdk_path.to_string_lossy())
- .map_err(|error| format!("failed to render SDK path: {error}"))?;
- Ok(format!(
- r#"[package]
-name = "radroots_sdk_knowledge_smoke"
-version = "0.1.0"
-edition = "2024"
-publish = false
-
-[dependencies]
-radroots_sdk = {{ path = {sdk_path}, features = ["std", "serde", "serde_json", "nostr", "knowledge"] }}
-nostr = "{nostr_version}"
-"#
- ))
-}
-
-fn exact_workspace_dependency_pin(manifest_path: &Path, name: &str) -> Result<String, String> {
- let contents = fs::read_to_string(manifest_path)
- .map_err(|error| format!("failed to read {}: {error}", manifest_path.display()))?;
- let version = workspace_dependency_version_from(&contents, name)?;
- exact_dependency_pin(name, &version)
-}
-
-fn workspace_dependency_version_from(contents: &str, name: &str) -> Result<String, String> {
- let value = contents
- .parse::<toml::Value>()
- .map_err(|error| format!("failed to parse workspace manifest: {error}"))?;
- let dependency = value
- .get("workspace")
- .and_then(|workspace| workspace.get("dependencies"))
- .and_then(|dependencies| dependencies.get(name))
- .ok_or_else(|| format!("workspace dependency {name} is not defined"))?;
- if let Some(version) = dependency.as_str() {
- return Ok(version.to_owned());
- }
- dependency
- .get("version")
- .and_then(toml::Value::as_str)
- .map(str::to_owned)
- .ok_or_else(|| format!("workspace dependency {name} must define version"))
-}
-
-fn exact_dependency_pin(name: &str, version: &str) -> Result<String, String> {
- let trimmed = version.trim().strip_prefix('=').unwrap_or(version.trim());
- if !is_exact_crates_version(trimmed) {
- return Err(format!(
- "workspace dependency {name} must use a full exact version for smoke pinning: {version}"
- ));
- }
- Ok(format!("={trimmed}"))
-}
-
-fn is_exact_crates_version(version: &str) -> bool {
- let base = version
- .split_once(['-', '+'])
- .map_or(version, |(base, _)| base);
- let parts = base.split('.').collect::<Vec<_>>();
- parts.len() == 3
- && parts.iter().all(|part| {
- !part.is_empty() && part.chars().all(|character| character.is_ascii_digit())
- })
-}
-
-const CONSUMER_MAIN: &str = r#"use nostr::{EventBuilder, Keys, Kind, Tag, Timestamp};
-use radroots_event::envelope::EventEnvelopeParts;
-use radroots_sdk::knowledge::prelude::*;
-
-const CREATED_AT: u32 = 1_800_000_000;
-
-fn main() -> Result<(), Box<dyn std::error::Error>> {
- let keys = Keys::generate();
- let claim = claim_builder().build()?;
- let parts = claim_builder().build_event()?;
- let draft = claim_builder().build_draft(keys.public_key().to_hex(), CREATED_AT)?;
- let decoded = verify_and_decode_radroots_event(sign_parts(parts, &keys)?)?;
- let manifest = contract_manifest();
-
- assert_eq!(draft.contract_id, KNOWLEDGE_CLAIM_CONTRACT_ID);
- assert_eq!(manifest.contract_count, 11);
- match decoded {
- RadrootsDecodedEvent::KnowledgeClaim(parsed) => assert_eq!(parsed.data.data.text, claim.text),
- _ => return Err("expected knowledge claim".into()),
- }
- Ok(())
-}
-
-fn sign_parts(
- parts: Nip01EventWireParts,
- keys: &Keys,
-) -> Result<EventEnvelope, Box<dyn std::error::Error>> {
- let tags = parts
- .tags
- .into_iter()
- .map(Tag::parse)
- .collect::<Result<Vec<_>, _>>()?;
- let event = EventBuilder::new(Kind::Custom(parts.kind as u16), parts.content)
- .tags(tags)
- .custom_created_at(Timestamp::from_secs(u64::from(CREATED_AT)))
- .sign_with_keys(keys)?;
- Ok(EventEnvelope::new(EventEnvelopeParts {
- id: event.id.to_hex(),
- author: event.pubkey.to_hex(),
- created_at: event.created_at.as_secs(),
- kind: u32::from(event.kind.as_u16()),
- tags: event
- .tags
- .as_slice()
- .iter()
- .map(|tag| tag.as_slice().to_vec())
- .collect(),
- content: event.content,
- sig: event.sig.to_string(),
- })?)
-}
-
-fn hex_64(character: char) -> String {
- character.to_string().repeat(64)
-}
-
-fn event_ref(character: char, kind: u32) -> EventRef {
- EventRef {
- id: hex_64(character),
- author: radroots_identity::PublicKey::from_hex(
- "585591529da0bab31b3b1b1f986611cf5f435dca84f978c89ee8a40cca7103df",
- )
- .expect("fixture public key"),
- kind,
- d_tag: None,
- relays: Some(vec!["wss://relay.radroots.example".to_owned()]),
- }
-}
-
-fn claim_builder() -> RadrootsKnowledgeClaimBuilder {
- RadrootsKnowledgeClaimBuilder::new()
- .claim_type("practice_effect")
- .text("Cover crops improve soil structure.")
- .citation_span(KnowledgeCitationSpan {
- source_ref: event_ref('4', KIND_KNOWLEDGE_SOURCE),
- artifact_ref: None,
- page_start: Some(12),
- page_end: Some(13),
- section_path: vec!["chapter-1".to_owned()],
- quote_hash: Some(hex_64('5')),
- chunk_id: Some("chunk-1".to_owned()),
- })
- .topic("cover-crops")
- .applies_to("local-food")
- .author_asserted_confidence("medium")
-}
-"#;
-
const SDK_CONSUMER_MAIN: &str = r#"use radroots_sdk::{ClientBuilder, error::ErrorKind};
fn main() {
@@ -298,10 +106,12 @@ mod tests {
use crate::wasm::ResolvedRustToolchain;
- use super::{
- exact_dependency_pin, render_consumer_manifest, render_sdk_consumer_manifest,
- smoke_cargo_check_command, workspace_dependency_version_from,
- };
+ use super::{render_sdk_consumer_manifest, run, smoke_cargo_check_command};
+
+ #[test]
+ fn retired_sdk_knowledge_smoke_is_not_a_command_surface() {
+ assert!(run(&["knowledge-rust-local".to_owned()]).is_err());
+ }
#[test]
fn sdk_smoke_consumer_uses_final_api_and_local_lower_package_patches() {
@@ -321,36 +131,6 @@ mod tests {
}
#[test]
- fn smoke_consumer_manifest_uses_exact_direct_dependency_pin() {
- let manifest =
- render_consumer_manifest(Path::new("/tmp/radroots_sdk"), "=0.44.2").expect("manifest");
-
- assert!(manifest.contains("name = \"radroots_sdk_knowledge_smoke\""));
- assert!(manifest.contains("nostr = \"=0.44.2\""));
- assert!(!manifest.contains("nostr = \"0.44.2\""));
- }
-
- #[test]
- fn smoke_workspace_dependency_version_reads_table_version() {
- let version = workspace_dependency_version_from(
- r#"[workspace.dependencies]
-nostr = { version = "0.44.2" }
-"#,
- "nostr",
- )
- .expect("version");
-
- assert_eq!(version, "0.44.2");
- }
-
- #[test]
- fn smoke_dependency_pin_rejects_floating_major_version() {
- let error = exact_dependency_pin("nostr", "0.44").expect_err("floating version");
-
- assert!(error.contains("full exact version"));
- }
-
- #[test]
fn smoke_command_uses_resolved_cargo_path() {
let cargo = PathBuf::from("/tmp/rust-toolchain/bin/cargo");
let toolchain = ResolvedRustToolchain {