diff --git a/hemx-xtask/src/main.rs b/hemx-xtask/src/main.rs index 3d2b29b..39a0245 100644 --- a/hemx-xtask/src/main.rs +++ b/hemx-xtask/src/main.rs @@ -239,6 +239,14 @@ fn create_mobile_app_scaffold(destination: &Path) -> std::io::Result<()> { ] { replace_in_tree(destination, from, to)?; } + fs::write( + destination.join("README.md"), + "# hemx mobile app\n\nThis app was created by `cargo run -p hemx-xtask -- app new --mobile PATH`. It is a phone-first hemx starter with a real page/form/keyed partial/notice flow, typed host haptics/share calls, app-owned command/event/projection recovery truth, and inspectable mobile release-kit commands. The starter uses the Workout product flow as the first concrete app, but the command surface is owned by this app. req: ceremony/006\n\n## Run\n\n```sh\n./hemx-app dev\n```\n\nOpen the printed local URL. Set `HEMX_APP_ADDR=127.0.0.1:3030` if the default port is busy.\n\n## Test and build\n\n```sh\n./hemx-app test\n./hemx-app build\n./hemx-app doctor\n```\n\n## Mobile release kit\n\n```sh\nHEMX_APP_ORIGIN=https://app.example.com ./hemx-app mobile-release\nHEMX_APP_ORIGIN=https://app.example.com ./hemx-app mobile-verify\n```\n\nThe release kit writes inspectable Android/iOS metadata under `target/hemx-mobile/app`, records runtime/cache/offline/host capability policy, and reports external blockers for SDKs, signing, and store accounts without storing secrets or predicting store approval.\n\n## Boundaries\n\nUse this path for Rust-owned hypermedia apps that need installability, recovery, and a few explicit host capabilities. Do not treat it as a native UI framework, client store, plugin marketplace, or store-submission bot.\n", + )?; + fs::write( + destination.join("CREATED.md"), + "# Created hemx mobile app\n\nUse one app-owned command surface from this directory:\n\n```sh\n./hemx-app dev\n./hemx-app test\n./hemx-app build\nHEMX_APP_ORIGIN=https://app.example.com ./hemx-app mobile-release\nHEMX_APP_ORIGIN=https://app.example.com ./hemx-app mobile-verify\n./hemx-app doctor\n```\n\nThis app owns command/event/projection state and keeps Android/iOS SDKs, store submission targets, and signing outside the repo. req: ceremony/006 req: examples/006\n", + )?; fs::write( destination.join("MOBILE_STARTER.md"), "# Mobile hemx starter\n\nThis starter is the phone-first path exposed through `app new --mobile`: it has a real page/form/keyed partial/notice flow, typed host haptics/share calls returning through Rust handlers, app-owned command/event/projection recovery truth, and app-owned `hemx-app mobile-release` / `hemx-app mobile-verify` release-kit commands.\n\nThe starter uses the Workout product flow as a concrete first app, but its command surface, crate name, binary name, release output, and environment variables are owned by the created app. It deliberately does not add a hemx mobile framework, client store, signing secret owner, or store submission bot. req: ceremony/006 req: examples/006\n", @@ -1270,6 +1278,8 @@ mod tests { let _ = fs::remove_dir_all(&destination); create_mobile_app_scaffold(&destination).expect("create mobile app scaffold"); + let readme = fs::read_to_string(destination.join("README.md")).expect("readme"); + let created = fs::read_to_string(destination.join("CREATED.md")).expect("created docs"); let mobile_readme = fs::read_to_string(destination.join("MOBILE_STARTER.md")).expect("mobile docs"); let command = fs::read_to_string(destination.join("hemx-app")).expect("command"); @@ -1277,6 +1287,17 @@ mod tests { let template = fs::read_to_string(destination.join("templates/workout.heml")).expect("template"); + assert!(readme.contains("# hemx mobile app")); + assert!(readme.contains("./hemx-app dev")); + assert!( + readme.contains("HEMX_APP_ORIGIN=https://app.example.com ./hemx-app mobile-release") + ); + assert!(readme.contains("Do not treat it as a native UI framework")); + assert!(!readme.contains("cargo run -p hemx-xtask -- workout")); + assert!(!readme.contains("hemx-workout")); + assert!(created.contains("# Created hemx mobile app")); + assert!(created.contains("./hemx-app doctor")); + assert!(!created.contains("Created Workout app")); assert!(mobile_readme.contains("phone-first path")); assert!(mobile_readme.contains("typed host haptics/share calls")); assert!(mobile_readme.contains("command/event/projection recovery truth"));