diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 6f6dc3f..5384799 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -42,7 +42,7 @@ jobs: - uses: actions/checkout@v6 with: repository: spore-lang/spore - ref: ef627c785e355a70551af5e4f4d85230996ce8d9 + ref: d96212aa5a4cfe24759c21d8690642adfd357018 path: _spore - uses: dtolnay/rust-toolchain@stable @@ -58,38 +58,68 @@ jobs: - name: Format Spore files run: | - # `src/host.sp` is the package host entry; validate it via package/example flows, - # not standalone file-mode formatting. - paths=(examples src/basic_cli) + # `src/host.sp` is a legacy compatibility shim; validate package-backed behavior + # via the example and platform modules rather than standalone file-mode checks. + # Standalone file examples + find examples -maxdepth 1 -name '*.sp' -type f | sort | xargs _spore/target/release/spore format + # Project-mode examples (format their src files) + if [ -d examples/hello-app/src ]; then + find examples/hello-app/src -name '*.sp' -type f | sort | xargs _spore/target/release/spore format + fi + # Platform API modules + find src/basic_cli -name '*.sp' -type f | sort | xargs _spore/target/release/spore format + # Check tests if they exist if [ -d tests ]; then - paths+=(tests) + find tests -name '*.sp' -type f | sort | xargs _spore/target/release/spore format fi - find "${paths[@]}" -name '*.sp' -type f | sort | xargs _spore/target/release/spore format - git diff --exit-code -- "${paths[@]}" + git diff --exit-code - name: Check Spore files run: | - # `src/host.sp` is the package host entry; validate it via package/example flows, - # not standalone file-mode checks. - paths=(examples src/basic_cli) + # `src/host.sp` is a legacy compatibility shim; validate package-backed behavior + # via the example and platform modules rather than standalone file-mode checks. + # Standalone file examples + find examples -maxdepth 1 -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore check + # Platform API modules + find src/basic_cli -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore check + # Project-mode examples: validate with spore check + if [ -d examples/hello-app ]; then + echo "✓ Checking project-mode example examples/hello-app/src/main.sp" + _spore/target/release/spore check examples/hello-app/src/main.sp + fi + # Check tests if they exist if [ -d tests ]; then - paths+=(tests) + find tests -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore check fi - find "${paths[@]}" -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore check - name: Build Spore files run: | - # `src/host.sp` is the package host entry; validate it via package/example flows, - # not standalone file-mode builds. - paths=(examples src/basic_cli) + # `src/host.sp` is a legacy compatibility shim; validate package-backed behavior + # via the example and platform modules rather than standalone file-mode builds. + # Standalone file examples + find examples -maxdepth 1 -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore build + # Platform API modules + find src/basic_cli -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore build + # Project-mode examples: validate with spore build + if [ -d examples/hello-app ]; then + echo "✓ Building project-mode example examples/hello-app/src/main.sp" + _spore/target/release/spore build examples/hello-app/src/main.sp + fi + # Check tests if they exist if [ -d tests ]; then - paths+=(tests) + find tests -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore build fi - find "${paths[@]}" -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore build - - name: Run hello example + - name: Run standalone hello example run: _spore/target/release/spore run examples/hello.sp + - name: Run project-mode hello-app example + run: | + if [ -d examples/hello-app ]; then + echo "✓ Running project-mode example examples/hello-app/src/main.sp" + _spore/target/release/spore run examples/hello-app/src/main.sp + fi + - name: Run Spore spec tests run: | if [ ! -d tests ]; then diff --git a/README.md b/README.md index 6a2c0fc..a39077e 100644 --- a/README.md +++ b/README.md @@ -29,20 +29,50 @@ Operating System ## Quick Start +The canonical project-mode structure is demonstrated in `examples/hello-app/`: + +**examples/hello-app/spore.toml:** +```toml +[package] +name = "hello-app" +version = "0.1.0" +type = "application" +spore-version = ">=0.1.0" + +[project] +platform = "basic-cli" +default-entry = "app" + +[entries.app] +path = "main.sp" + +[capabilities] +allow = ["Compute"] + +[dependencies] +basic-cli = { path = "../.." } +``` + +**examples/hello-app/src/main.sp:** ```spore -/// A simple "Hello World" using the basic-cli platform. +import basic_cli.stdout as stdout + fn main() -> () uses [Console] { - println("Hello from Spore basic-cli!") + println("Hello from a project-mode Spore application!") + return } ``` +**Run the project:** ```bash -spore check examples/hello.sp -spore build examples/hello.sp -spore run examples/hello.sp +cd examples/hello-app +spore check src/main.sp +spore run src/main.sp ``` -This repository currently keeps `examples/` limited to files that PR CI validates today. +This is a real package-backed application. The in-repo example points `basic-cli` at `../..`; projects generated by `spore new` vendor the package and use `vendor/basic-cli` instead. The formatter currently normalizes the import to `import basic_cli.stdout as stdout`, while `println` still resolves directly in scope. + +For quick experiments, you can also run standalone `.sp` files (see `examples/hello.sp`), but production applications should use the project-mode structure above. ## Project Structure @@ -50,7 +80,7 @@ This repository currently keeps `examples/` limited to files that PR CI validate basic-cli/ ├── spore.toml # Platform manifest ├── src/ -│ ├── host.sp # Compatibility runtime entry point +│ ├── host.sp # Legacy compatibility shim │ ├── platform_contract.sp │ └── basic_cli/ # Spore API modules, checked and built in CI │ ├── stdout.sp # Standard output operations @@ -75,13 +105,14 @@ The current Platform contract MVP is intentionally split across two artifacts: - a hole-backed `main` function carries the authoritative startup signature - `main_for_host` is the Platform-owned adapter that receives the application startup function -Applications targeting `basic-cli` must implement the same startup function name/signature in their entry module. When the compiler starts reading Platform contracts from packages, `spec` items attached to the Platform contract and the application implementation will both have to hold. +Applications targeting `basic-cli` must implement the same startup function name/signature in their entry module. The current compiler already resolves the package's `[platform]` metadata and `src/platform_contract.sp` to validate that startup shape. Runtime support is currently specialized to package-backed `basic-cli`: imported `basic_cli.*` foreign functions route through the built-in basic-cli host profile, while generic `handles` enforcement and startup `spec` stacking are still follow-up work. -`src/host.sp` remains as a compatibility copy of the adapter while the compiler still hardcodes platform startup behavior. +`src/host.sp` remains as a compatibility copy of the adapter for older references; current manifest-backed projects use `src/platform_contract.sp`. ## Tutorial Contract -- `examples/` is for truthful, CI-validated examples only. +- `examples/hello-app/` is the **canonical project-mode example** — it is formatted, checked, built, and run in CI. +- `examples/hello.sp` is a minimal standalone file for quick experiments (also validated in CI). - `src/basic_cli/` is the API surface for the platform modules themselves. - `src/platform_contract.sp` is the package-owned startup contract surface. - Only add `tests/` when the repo has real Spore-side regression coverage worth running with `spore test`. @@ -105,7 +136,9 @@ Following Spore's [SEP-0003 (Effect Capability System)](https://github.com/spore 🚧 **Early development** — API is unstable and subject to change. -At the moment, the validated example is `examples/hello.sp`. More ambitious host-backed demos such as environment/file workflows should stay out of `examples/` until the current platform import/runtime architecture supports them honestly. +The canonical example is the **package-backed project-mode** `examples/hello-app/` application. It already validates and runs with `[project].platform = "basic-cli"`, an in-repo path dependency, and `import basic_cli.stdout`. + +The standalone file example (`examples/hello.sp`) stays around for quick experiments. The main remaining platform gaps are generic `handles` enforcement, startup `spec` stacking, and lifting the runtime from its current explicit `basic-cli` host profile to a more general package-backed mechanism. ## License diff --git a/examples/hello-app/spore.toml b/examples/hello-app/spore.toml new file mode 100644 index 0000000..e58d081 --- /dev/null +++ b/examples/hello-app/spore.toml @@ -0,0 +1,18 @@ +[package] +name = "hello-app" +version = "0.1.0" +type = "application" +spore-version = ">=0.1.0" + +[project] +platform = "basic-cli" +default-entry = "app" + +[entries.app] +path = "main.sp" + +[capabilities] +allow = ["Compute"] + +[dependencies] +basic-cli = { path = "../.." } diff --git a/examples/hello-app/src/main.sp b/examples/hello-app/src/main.sp new file mode 100644 index 0000000..cd90a79 --- /dev/null +++ b/examples/hello-app/src/main.sp @@ -0,0 +1,12 @@ +/// Canonical package-backed application example for basic-cli. +/// +/// This mirrors the formatted `spore new` scaffold: import the +/// platform module explicitly and call `println` directly from the +/// imported basic-cli surface. +/// Application entry point matching the platform contract. +import basic_cli.stdout as stdout + +fn main() -> () uses [Console] { + println("Hello from a project-mode Spore application!") + return +} diff --git a/src/host.sp b/src/host.sp index 67191fd..23aed47 100644 --- a/src/host.sp +++ b/src/host.sp @@ -1,6 +1,6 @@ -/// Compatibility startup adapter. -/// Keep this entry in sync with `platform_contract.sp` until the compiler reads -/// `[platform].contract-module` directly. +/// Legacy compatibility adapter. +/// Manifest-backed projects resolve `main_for_host` from `platform_contract.sp`; +/// keep this shim in sync for older references. pub fn main_for_host(app_main: () -> ()) -> () { app_main() return