feat(template): rename lez-framework to spel; delegate scaffolding to spel init - #199
feat(template): rename lez-framework to spel; delegate scaffolding to spel init#199vpavlin wants to merge 7 commits into
Conversation
Updates the two pinned defaults in `constants.rs`: - DEFAULT_LEZ: v0.2.0-rc1 (35d8df0) → v0.1.2 (cf3639d), the first published LEZ release. - DEFAULT_SPEL: v0.2.0-rc.5 (1db7c5f) → v0.5.0 (73fc462), released today and aligned with LEZ v0.1.2. Circuits version (0.4.1) is unchanged — LEZ v0.1.2's flake.lock pins the same circuits commit (d6cf41f) as before. Closes logos-co/ecosystem#128 (upgrade spel + scaffold to pin LEZ v0.1.2). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…el init ## What changed - `lgs new --template spel` (new) calls `spel init <name> --lez-tag <DEFAULT_LEZ.tag>` to scaffold the project, then layers scaffold.toml and AI skills on top. Scaffold no longer owns any SPEL template files. - `lgs new --template lez-framework` prints a deprecation warning and maps to `spel`. Existing projects with `framework.kind = "lez-framework"` in scaffold.toml continue to work unchanged. - `FRAMEWORK_KIND_SPEL = "spel"` added to constants. - `lgs build idl` for spel projects delegates to the vendored spel binary (`spel generate-idl`) instead of scaffold's internal IDL pipeline. - `lgs build client` for spel projects delegates to `spel ffi-gen`. - Deploy-cache IDL hashing treats `spel` projects the same as `lez-framework` (IDL is a required deploy artifact). - `templates/lez-framework/` removed entirely — spel init is the authoritative scaffolder for framework projects. - `skills/lez-framework-template/` renamed to `skills/spel-template/` with updated content using spel vocabulary (#[spel_program], spel.toml, make targets, spel CLI commands). ## Why The `lez-framework` template in scaffold was broken (still referenced jimmy-claw/lez-framework) and duplicated template logic that belongs to spel. Scaffold's role is now minimal: scaffold.toml, AI skills, and version pinning — program scaffolding is owned by spel. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Replaces the broken in-tree lez-framework template with a thin delegation to the external spel CLI for scaffolding framework projects. Scaffold now only owns version pinning, scaffold.toml, and AI skills; program scaffolding (Cargo workspace, IDL gen, FFI gen) is handled by spel init/spel generate-idl/spel ffi-gen. The legacy lez-framework template name remains accepted but emits a deprecation warning and is silently mapped to spel.
Changes:
- New
--template spel(and deprecation aliaslez-framework) shells out tospel initand layers scaffold state on top; LEZ pin downgraded tov0.1.2, spel pin bumped tov0.5.0. lgs build idlandlgs build clientdelegate tospel generate-idl/spel ffi-genfor spel projects; deploy-cache hashing now requires an IDL for bothlez-frameworkandspelkinds.- Deleted the entire
templates/lez-framework/tree and renamedskills/lez-framework-template/→skills/spel-template/with rewritten content.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/commands/new.rs | Splits cmd_new_inner into cmd_new_spel (delegates to spel init) and cmd_new_default; adds find_spel_on_path and build_scaffold_config helpers. |
| src/commands/build.rs | Adds FRAMEWORK_KIND_SPEL branch that runs IDL gen but skips client gen (left to project Makefile). |
| src/commands/idl.rs | Routes spel projects to spel generate-idl; updates error message to mention spel. |
| src/commands/client.rs | Routes spel projects to spel ffi-gen and std::process::exit(0)s mid-helper; updates error message. |
| src/commands/run_state.rs | Treats both lez-framework and spel projects as IDL-required when computing program hashes. |
| src/commands/init.rs | Test updated to expect spel-template skill in place of lez-framework-template. |
| src/constants.rs | Adds FRAMEWORK_KIND_SPEL; bumps DEFAULT_SPEL to v0.5.0 and changes DEFAULT_LEZ to v0.1.2. |
| src/template/project.rs | Removes the lez-framework-specific overlay test and drops the variant from the no-self-patch test. |
| src/template/skills.rs | Test updated for renamed skill directory. |
| templates/lez-framework/** | Entire template tree deleted. |
| skills/lez-framework-template/SKILL.md | Deleted. |
| skills/spel-template/SKILL.md | New skill describing the spel-based workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| FRAMEWORK_KIND_SPEL => { | ||
| // For spel projects, FFI/client gen is handled by `spel ffi-gen` | ||
| // (or the project Makefile's `make ffi`). Delegate directly. | ||
| cmd_spel(vec!["ffi-gen".to_string()])?; | ||
| std::process::exit(0); | ||
| } |
Addressed Copilot review comment: `std::process::exit(0)` inside a helper returning `DynResult<Project>` was surprising and bypassed caller cleanup. Spel dispatch now happens at call-site in `build_clients_for_current_project` and `generate_clients_from_current_idl` before reaching the lez-framework-only `require_lez_framework_project` helper. Also fixes two rustfmt failures flagged by CI on this branch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three CLI tests expected old `lez-framework`-only error strings and the old `lez-framework-template` skill name. Updated to match the new error messages (which now mention both `spel` and `lez-framework`) and the renamed `spel-template` skill. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| let cwd = env::current_dir()?; | ||
| let status = std::process::Command::new(&spel_bin) | ||
| .arg("init") | ||
| .arg(&cmd.name) | ||
| .arg("--lez-tag") | ||
| .arg(DEFAULT_LEZ.tag) | ||
| .current_dir(&cwd) | ||
| .status() | ||
| .context("failed to launch spel init")?; | ||
| if !status.success() { | ||
| anyhow::bail!("spel init failed"); | ||
| } |
| fn find_spel_on_path() -> anyhow::Result<std::path::PathBuf> { | ||
| let path_var = std::env::var_os("PATH").unwrap_or_default(); | ||
| for dir in std::env::split_paths(&path_var) { | ||
| let candidate = dir.join("spel"); | ||
| if candidate.is_file() { | ||
| return Ok(candidate); | ||
| } | ||
| } | ||
|
|
||
| Ok(()) | ||
| anyhow::bail!("spel not found on PATH") | ||
| } |
| other => { | ||
| bail!("unsupported template `{other}`. Expected `default` or `lez-framework`.") | ||
| bail!("unsupported template `{other}`. Expected `default` or `spel`.") | ||
| } |
| // spel init created `target/`; layer scaffold state on top. | ||
| fs::create_dir_all(target.join(".scaffold/state"))?; | ||
| fs::create_dir_all(target.join(".scaffold/logs"))?; | ||
|
|
||
| let cfg = build_scaffold_config(cmd, FRAMEWORK_KIND_SPEL, bootstrap_cache); | ||
| write_text(&target.join("scaffold.toml"), &serialize_config(&cfg)?)?; | ||
| ensure_scaffold_in_gitignore(target)?; | ||
| apply_skills(target)?; |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Error message for unknown template now mentions the deprecated `lez-framework` alias so users know it exists. - `--lez-path` combined with `--template spel` now fails with a clear message (was silently recorded in scaffold.toml but never forwarded to `spel init`). - `--vendor-deps` combined with `--template spel` now fails with a clear message (was silently writing non-existent paths into scaffold.toml). - `find_spel_on_path` now also probes `spel.exe` on Windows. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| let template_variant = match cmd.template.as_str() { | ||
| FRAMEWORK_KIND_DEFAULT | FRAMEWORK_KIND_LEZ_FRAMEWORK => cmd.template.clone(), | ||
| FRAMEWORK_KIND_DEFAULT => cmd.template.clone(), | ||
| FRAMEWORK_KIND_SPEL => cmd.template.clone(), | ||
| FRAMEWORK_KIND_LEZ_FRAMEWORK => { | ||
| eprintln!( | ||
| "warning: template `lez-framework` is deprecated; use `--template spel` instead." | ||
| ); | ||
| FRAMEWORK_KIND_SPEL.to_string() | ||
| } | ||
| other => { | ||
| bail!("unsupported template `{other}`. Expected `default` or `lez-framework`.") | ||
| bail!( | ||
| "unsupported template `{other}`. \ | ||
| Expected `default` or `spel` (or the deprecated alias `lez-framework`)." | ||
| ) | ||
| } |
| let spel_bin = find_spel_on_path().context( | ||
| "spel binary not found on PATH.\n\ | ||
| Install it first:\n \ | ||
| cargo install --git https://github.com/logos-co/spel.git --tag v0.5.0 spel", | ||
| )?; |
| fn find_spel_on_path() -> anyhow::Result<std::path::PathBuf> { | ||
| let path_var = std::env::var_os("PATH").unwrap_or_default(); | ||
| for dir in std::env::split_paths(&path_var) { | ||
| let candidate = dir.join("spel"); | ||
| if candidate.is_file() { | ||
| return Ok(candidate); | ||
| } | ||
| // On Windows executables carry a .exe suffix. | ||
| #[cfg(target_os = "windows")] | ||
| { | ||
| let candidate_exe = dir.join("spel.exe"); | ||
| if candidate_exe.is_file() { | ||
| return Ok(candidate_exe); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Ok(()) | ||
| anyhow::bail!("spel not found on PATH") |
| // Both lez-framework and spel projects require an IDL file at deploy time. | ||
| let is_lez_framework = matches!( | ||
| project.config.framework.kind.as_str(), | ||
| FRAMEWORK_KIND_LEZ_FRAMEWORK | FRAMEWORK_KIND_SPEL | ||
| ); |
- Install hint in find_spel_on_path error now uses DEFAULT_SPEL.tag instead of a hard-coded version string that would drift on bumps. - check_spel_version() warns when the installed spel version does not match DEFAULT_SPEL.tag, so mismatches surface before `lgs setup`. - available_templates() now includes "spel" explicitly; after removing the lez-framework template directory it was no longer discoverable from disk, so --template help advertised only "default". - Renamed is_lez_framework -> requires_idl in run_state.rs; the old name implied the flag only covered lez-framework, but it also matches spel. Updated the inline comment at the use site to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| let stdout = String::from_utf8_lossy(&output.stdout); | ||
| if !stdout.contains(DEFAULT_SPEL.tag) { | ||
| eprintln!( | ||
| "warning: installed spel version ({}) does not match the expected {} pinned by scaffold.\n\ | ||
| This may cause unexpected behaviour. Install the pinned version with:\n \ | ||
| cargo install --git https://github.com/logos-co/spel.git --tag {} spel", | ||
| stdout.trim(), | ||
| DEFAULT_SPEL.tag, | ||
| DEFAULT_SPEL.tag, | ||
| ); | ||
| } |
| let spel_bin = find_spel_on_path().with_context(|| { | ||
| format!( | ||
| "spel binary not found on PATH.\n\ | ||
| Install it first:\n \ | ||
| cargo install --git https://github.com/logos-co/spel.git --tag {} spel", | ||
| DEFAULT_SPEL.tag | ||
| ) | ||
| })?; | ||
| check_spel_version(&spel_bin); | ||
|
|
||
| if cmd.lez_path.is_some() { | ||
| anyhow::bail!( | ||
| "`--lez-path` is not supported with `--template spel`.\n\ | ||
| `spel init` fetches LEZ via `--lez-tag`; a local path override is not forwarded.\n\ | ||
| Use `--template default` if you need a local LEZ checkout." | ||
| ); | ||
| } | ||
| if cmd.vendor_deps { | ||
| anyhow::bail!( | ||
| "`--vendor-deps` is not supported with `--template spel`.\n\ | ||
| Vendoring is managed by `spel init` and `lgs setup`, not by scaffold directly.\n\ | ||
| Use `--template default` if you need vendored deps." | ||
| ); | ||
| } |
| anyhow::bail!("spel init failed"); | ||
| } | ||
|
|
||
| // spel init created `target/`; layer scaffold state on top. |
|
@vpavlin wow, copilot really tried hard to review your PR |
|
is it ready to review? quickly tried:
|
Review + hands-on dogfoodingReviewed the diff and then actually ran the affected flows end-to-end (built the CLI, installed 🔴 Blocker 1 —
|
| Producer / consumer | Path |
|---|---|
scaffold scaffold.toml framework.idl.path |
idl/ → expects idl/<stem>.json |
deploy-cache hashing (run_state.rs ~L118, tightened in this PR) |
reads idl/<stem>.json, bails if missing for spel |
spel spel.toml / make idl |
<root>/spelproj-idl.json |
spel generate-idl (what lgs build idl invokes) |
prints IDL to stdout, writes no file |
Reproduced in a generated spel project (vendored spel binary in place):
lgs build idl→ runsspel generate-idl, dumps JSON to stdout, creates no file, exits 0.src/commands/idl.rsreturnscmd_spel(["generate-idl"]), andcmd_speluses.status()(inherits stdout) — it never redirects toidl/<stem>.jsonthe way the lez-framework branch writes its IDL.lgs build client→spel ffi-gen→Error reading IDL '…/spelproj-idl.json': No such file or directory, exit 1.lgs deploy/lgs run→compute_program_hashesrequiresidl/<stem>.json→ would bail: "expected IDL file …/idl/spelproj.json … is missing; runlgs build idlfirst" — andlgs build idlnever produces it. Dead end.
So the Test Plan item "lgs build idl … calls spel generate-idl" is true but functionally useless: nothing is persisted, and the deploy gate this PR adds then makes deploy impossible. Fix: capture spel generate-idl stdout → write idl/<stem>.json (as the lez-framework branch does), or point framework.idl.path at spel's <root>/spelproj-idl.json convention and teach run_state to read that name.
🔴 Blocker 2 — circuits pin (0.4.1) is incompatible with the bumped spel/LEZ pins (they need 0.4.2)
constants.rs bumps DEFAULT_LEZ → v0.1.2 and DEFAULT_SPEL → v0.5.0 but leaves DEFAULT_CIRCUITS_VERSION = "0.4.1".
- Both LEZ v0.1.2's and spel v0.5.0's
Cargo.lockpulllogos-blockchainrev1da154c…, whose build script asserts circuitsv0.4.2. - Reproduced:
cargo install --git …/spel.git --tag v0.5.0 spelagainst circuits 0.4.1 → panic: "The logos-blockchain-circuits directory … is version 'v0.4.1', but version 'v0.4.2' is expected." setup.rsprovisions circuits at the 0.4.1 pin and uses it for the LEZ-sequencer, wallet and vendored-spel builds.lgs buildwas observed downloading…/v0.4.1/…before the (long) sequencer build — it hits the same assertion.
The doc comment derives 0.4.1 from LEZ's flake.lock (nix), but scaffold builds via Cargo, which needs 0.4.2. Net effect: lgs setup / lgs build fail on a clean machine for both default and spel projects. The comment even says "bump this in lock-step with DEFAULT_LB_PIN / DEFAULT_LEZ." Fix: DEFAULT_CIRCUITS_VERSION = "0.4.2" and verify a from-scratch lgs setup.
🟠 Medium
3. check_spel_version warns on every spel project, even when correct. spel --version (v0.5.0) prints usage to stderr and exits 1 with empty stdout; new.rs greps output.stdout for "v0.5.0" → always false. Live output during lgs new --template spel:
warning: installed spel version () does not match the expected v0.5.0 pinned by scaffold.
Note the empty (). Read stderr too (or call a real version subcommand) before deciding to warn.
4. cache_root portability regression — affects default too. The build_scaffold_config extraction changed the no---cache-root default from String::new() to the absolute bootstrap path (new.rs ~L292). Confirmed: a generated default project's scaffold.toml now contains cache_root = "/root/.cache/logos-scaffold". The deleted comment explicitly kept it empty "so scaffold.toml stays portable." This machine-specific path now ships in every committed config, not just spel.
🟡 Low
5. Flag-validation ordering. --vendor-deps / --lez-path with --template spel report "spel not found on PATH" instead of the intended "flag not supported" error, because find_spel_on_path() / check_spel_version run before the flag checks in cmd_new_spel. Validate args first (fail fast regardless of environment).
6. Generated project's spel deps don't match the recorded pin. spel init (called with only --lez-tag) emits spelproj_ffi → spel-framework-core tag="v0.4.0" and examples → branch="main", while scaffold.toml records spel v0.5.0. branch="main" is a moving target that defeats the reproducible pinning that's scaffold's job. Consider passing --spel-tag to match. (Partly upstream, but it's the seam this PR introduces.)
7. No test coverage for the new path. There are no new-command integration tests at all, and cmd_new_spel / the deprecation mapping / the flag-bail paths are untested; the removed lez_framework_overlay unit test wasn't replaced.
8. Doc/UX nits. skills/spel-template/SKILL.md L116-118 uses bare spel -- initialize … (the -- is the lgs passthrough separator), contradicting its own gotcha to use lgs spel -- …; L105 says "lgs build runs make build" (it runs scaffold's workspace build, not make). lgs new --template spel prints two separate "Next steps" blocks (spel's + scaffold's).
Flows exercised
new --template default ✅ (cache_root regression) · new --template spel ✅ delegates (warning #3, IDL #1, deps #6) · new --template lez-framework ✅ deprecation→spel · bad template ✅ correct error · spel + --vendor-deps/--lez-path default, spel · build idl 🔴 stdout, no file · build client 🔴 missing IDL · build/setup 🔴 circuits skew · deploy-cache requires IDL 🔴 would bail · init skills→spel-template ✅ · 342 unit + changed integration tests ✅.
Bottom line: the headline happy path (lgs new --template spel → buildable, deployable project) doesn't work today — it breaks at lgs setup (circuits 0.4.1 vs 0.4.2) and again at lgs build idl/deploy (IDL location). Both look like small, targeted fixes.
🤖 Reviewed via hands-on dogfooding in a fresh environment. Generated with Claude Code.
danisharora099
left a comment
There was a problem hiding this comment.
LGTM on the direction - spel owns scaffolding, scaffold owns pins/orchestration. Agree with @weboko: IDL output doesn’t land where deploy expects, and circuits 0.4.1 vs 0.4.2 blocks setup on a clean box. Fix those two (+ cache_root / version warning if easy)
weboko
left a comment
There was a problem hiding this comment.
Review — reviewed via end-to-end dogfooding (installed pinned spel v0.5.0) + code read
I built the branch, installed the pinned spel v0.5.0 (cargo install --git …/spel.git --tag v0.5.0), and dogfooded the template flows against it.
Verified working ✅
lgs new --template speldelegates tospel init <name> --lez-tag v0.1.2, then layersscaffold.toml(framework.kind = "spel") + AI skills (incl.spel-template). Resulting tree is a proper spel project (spel.toml,*_core,*_ffi,methods,Makefile). The exact invocation matches spel v0.5.0'sinitinterface.--template defaultunchanged;--template lez-frameworkprints the deprecation warning and maps to spel; unknown templates error clearly.--lez-path/--vendor-depsare rejected for--template spelwith actionable messages; missing-spel prints the exactcargo installcommand.- Backward compat is sound: the
lez-frameworkkind is still handled inbuild/idl/client/run_state(deploy now requires an IDL for both spel and lez-framework — good). - Builds clean; 342 lib + 159 CLI tests pass on the branch base.
🐞 Confirmed bug — check_spel_version always warns (reproduced live)
check_spel_version runs spel --version and checks stdout.contains(DEFAULT_SPEL.tag). But spel v0.5.0 has no --version: it exits 1 and prints usage to stderr, leaving stdout empty. So the check is always false and every lgs new --template spel prints — even with the correctly-pinned spel:
warning: installed spel version () does not match the expected v0.5.0 pinned by scaffold.
The empty () makes it self-evidently wrong and will erode trust in the warning. Please detect the version via a command spel actually supports (or drop/redesign the check). A substring match on a v-prefixed tag is also fragile if spel ever prints 0.5.0 without the v.
📄 DOGFOODING.md not updated (required for this change)
This PR renames the primary framework template lez-framework → spel but does not touch DOGFOODING.md. On current master, DOGFOODING.md has ~12 references to lez-framework — an entire L1–L4 scenario series plus E3 and the invalid-template error listing (default, lez-framework). Since this is a user-facing template rename + delegation change, those scenarios need to be migrated to --template spel (including the new spel-on-PATH prerequisite and the spel generate-idl / ffi-gen delegation semantics). Please update DOGFOODING.md as part of this PR.
🔀 Staleness / rebase
The branch is a month old on an old base and conflicts with master in idl.rs, new.rs, constants.rs, tests/cli.rs. Note the constants.rs pin bump (LEZ v0.1.2 / spel v0.5.0) already landed on master via #198, so that portion of the diff is now redundant — the rebase should drop it. Please rebase and re-run the template scenarios.
Minor
find_spel_on_pathre-implementscrate::process::which; considerwhich("spel")for consistency (it already handles the.execase).- Architecture question for maintainers:
--template spelnow requires a separatelycargo installedspelon PATH, unlike the self-containeddefaulttemplate. Given master vendors + builds spel duringlgs setup, is a global spel prerequisite atnewtime the intended UX, or shouldnewbootstrap/point at the vendored spel? Worth aligning before this lands.
Not approving — comments only. The direction (minimal scaffold role, delegate scaffolding to spel init) is reasonable and the happy path works end-to-end; the version-check bug + DOGFOODING update + rebase are the blockers I'd want resolved first.
weboko
left a comment
There was a problem hiding this comment.
Independent re-review — spel delegation works, but the PR is not mergeable as-is and the version check is confirmed broken
Built the branch, installed the pinned spel v0.5.0 (cargo install --git …/spel.git --tag v0.5.0, with logos-blockchain-circuits v0.4.1), put it on PATH, and dogfooded the delegation live.
Verified working ✅
lgs new --template spel <name>delegates tospel init, producing a proper spel project —spel.toml,<name>_core,<name>_ffi,methods/,Makefile,examples/— and correctly pins LEZ v0.1.2 (cf3639d8) + spel v0.5.0 (73fc462e), then layersscaffold.tomland AI skills (.claude/skills/,.cursor/rules/,AGENTS.md, incl. the newspel-templateskill). The delegation itself is sound.
🚫 Blocker — not mergeable, and superseded-in-part by work that has since landed
- GitHub reports this PR
mergeable: false/mergeable_state: dirty. Its merge-base is 2026-06-02 (#85), i.e. it predates the substantial spel-as-build-tool integration that has since landed onmaster(DEFAULT_SPEL,[repos.spel],check_spel_lez_alignment,SPEL_BIN_REL_PATH, spel rows indoctor, etc.). This PR deletestemplates/lez-framework/**andskills/lez-framework-template/, but on currentmasterthelez-frameworkvariant is still a live code path (FRAMEWORK_KIND_LEZ_FRAMEWORKinnew.rs). It needs a rebase ontomasterand explicit reconciliation of the framework-kind story before it can merge or be meaningfully re-reviewed.
🐞 Confirmed bug (reproduced live) — check_spel_version always warns, with an empty version string
check_spel_version runs spel --version and tests stdout.contains(DEFAULT_SPEL.tag). I confirmed against the real pinned binary that spel v0.5.0 has no --version: it exits 1, prints usage to stderr, and leaves stdout empty. So "".contains("v0.5.0") is always false and every lgs new --template spel prints a spurious warning — even with the exact pinned version installed. Live output:
warning: installed spel version () does not match the expected v0.5.0 pinned by scaffold.
Note the empty () — the message interpolates stdout.trim(), which is empty. There is also no spel version subcommand (it just prints usage). The check needs a real version-detection mechanism (or should be dropped) — as written it is pure false-positive noise on the happy path.
📄 Docs — DOGFOODING.md not updated for the new flow
This PR introduces a whole new scaffolding path (--template spel → spel init) but does not add any DOGFOODING.md coverage for it, and master's DOGFOODING.md has no --template spel scenario either. Given the significance of the new flow, a dogfooding scenario should be added.
Recommendation
The core delegation is good and worth landing, but not approvable in its current state: (1) rebase onto current master and reconcile with the already-merged spel plumbing / the still-live lez-framework path; (2) fix check_spel_version (spel has no --version); (3) add a DOGFOODING.md scenario for --template spel.
Status update — now conflicted, and the template conflicts are modify/delete against the CI fix in
|
Re-review on the new base (
|
DOGFOODING.md |
What this PR breaks |
|---|---|
| L172–175 | The entire L1–L4 scenario table is defined as lez-framework, invoked via new --template lez-framework |
| L178 | E3 (AI skills) runs new --template lez-framework; this PR renames the skill dir to skills/spel-template/ |
| L665, L926 | Literal shell lines: "$SCAFFOLD_BIN" new dogfood-lez --template lez-framework |
| L936 | Asserts the invalid-template error lists (default, lez-framework) — now (default, spel), so the documented expectation is simply wrong |
| L124 | Says the lez-framework guest compiles C and therefore needs the risc0 C++ toolchain — unverified for spel init output, and a prerequisite users hit hard if it changed |
L1–L4 are exactly the scenarios this PR changes, and they are the ones I offered to run. I could not: see below.
Blocker — --template spel requires a global spel, which contradicts scaffold's core property
This is the finding I'd most like a response on. Verified on a clean machine with the branch built:
$ which spel
(not found)
$ lgs create demo-spel --template spel
error: spel binary not found on PATH.
Install it first:
cargo install --git https://github.com/logos-co/spel.git --tag v0.5.0 spel: spel not found on PATH
cmd_new_spel calls find_spel_on_path() (src/commands/new.rs:346), which only walks PATH. But scaffold's stated contract — the one lgs --help advertises and #226 is currently rewriting the README around — is "setup builds the pinned sequencer, wallet, and spel toolchain locally: no global installs, portable across machines and CI." setup puts spel at project-local SPEL_BIN_REL_PATH (target/release/spel), never on PATH.
So there's a genuine ordering gap: create needs spel before setup exists to build it, and because setup's spel is project-local, even a user with ten scaffold projects still has no spel on PATH for the eleventh. The only way through is the global cargo install --git the error suggests — an unpinned-by-scaffold, machine-global toolchain, which is precisely what the rest of the design avoids.
The fix looks like it's already half-wired: cmd_new_spel receives bootstrap_cache but only passes it to build_scaffold_config. cmd_new_default in the same file already demonstrates the pattern — it clones LEZ at DEFAULT_LEZ.sha into ~/.cache/logos-scaffold/repos/lez/<sha> on demand (I watched it do exactly that during dogfooding). Fetching and building spel at DEFAULT_SPEL.sha into the same bootstrap cache would keep the pin authoritative, keep the "no global installs" property, make CI reproducible, and let check_spel_version become an assertion instead of a warning.
As it stands I could not run L1–L4 against the spel path at all without a global install, so the scenario set this PR changes remains unexercised end to end — by me, and (given tests/cli.rs grew only 19 lines and no test covers cmd_new_spel's delegation) by the test suite.
Smaller things
Copy-paste-hostile error. The message above concatenates the anyhow context and its source, so the suggested command runs straight into the error text:
cargo install --git https://github.com/logos-co/spel.git --tag v0.5.0 spel: spel not found on PATH
A user selecting that line copies ... spel: spel not found on PATH. Since this is the first thing every spel user will hit, it's worth restructuring so the command is on its own line, or dropping the redundant spel not found on PATH source.
check_spel_version is a substring test. src/commands/new.rs:333 does stdout.contains(DEFAULT_SPEL.tag), so v0.5.0 also matches a spel 0.5.01/v0.5.0-rc1 build, and any future v0.5.0 prefix collision. Given the header comment above it explicitly worries about "hard-to-diagnose mismatches", parsing the version and comparing exactly would match the stated intent.
Backward compatibility is handled well — worth saying. --template lez-framework still works and warns:
warning: template `lez-framework` is deprecated; use `--template spel` instead.
and FRAMEWORK_KIND_LEZ_FRAMEWORK is retained with a deprecation comment for existing scaffold.toml files. The --lez-path / --vendor-deps rejections are explicit and explain the alternative. That part of the ergonomics is good.
Build status
The branch builds and tests clean on its own base — cargo build --release clean, cargo test --locked --release 501 green (342 lib + 159 CLI), zero failures. So nothing here is about the code being broken in isolation; it's about the rebase, the docs, and the bootstrap gap.
Where this leaves it
Not mergeable as-is, and the gap has widened rather than narrowed since June. Before the next pass I'd want, in rough priority order:
- A decision on the global-
spelbootstrap — I'd argue for fetching the pinned spel into the bootstrap cache, consistent with howcmd_new_defaultalready handles LEZ. DOGFOODING.mdupdated (L1–L4, E3, the two script lines, the L936 assertion, and the L124 C++ prerequisite re-verified againstspel initoutput) plus the 4 README references — the ask from 2026-06-02.- Confirmation that
spel initatv0.5.0emits a program at least as current as post-#224templates/lez-framework/, before the seven deletes are accepted. - The rebase onto
7523ee2(12 conflicts, 8 of themmodify/delete), then a freshrender-and-buildrun. - Test coverage for
cmd_new_spel— currently none.
Happy to re-run L1–L4 end to end the moment the bootstrap question is settled; that's the check that would actually catch a missing #224-equivalent in the spel output.
(Comment only, not an approval.)
Generated by Claude Code
New finding on the current base (
|
Re-review: needs a rebase before it can be judged, and two design points to settle firstEnvironment: Nix 2.35.2, Rust 1.94.1, r0vm 3.0.5 + risc0 guest toolchains (rust I could not evaluate this one the way I evaluated the others, because it does not merge and cannot be built against current master. Flagging the mechanical state first, then two things I'd want settled before a rebase, so the rebase only has to happen once. The branch is 12 conflicts and 37 master commits behindHead is
The modify/delete class is the awkward one: master has kept actively developing the template this PR removes, so those aren't mechanical resolutions — someone has to decide, per file, whether master's newer content should be ported into 1. DOGFOODING.md is not touched, and this PR invalidates 14 references in itThis is the gap I'd fix first, because it's mechanical and it defines the acceptance criteria for everything else. Master's runbook references
A template rename plus a delegation to an external scaffolder is squarely "major user-facing behavior materially changed" under the runbook's own maintenance note. L1–L4 need to be rewritten against 2. Requiring
|
Delta since my 2026-08-25 review: master's docs were rebuilt under this branch, so the doc-update scope grewNo new commits here — head is still I picked this back up because Mechanical state: unchanged in shape, further behindStill 12 conflicts, still 8 of them New: this PR now breaks two things in the primary README#253 rewrote 1. The quick start's first command is the deprecated alias. cargo install logos-scaffold
lgs new my-app --template lez-frameworkThat is now the headline example a new user copies. After this PR, 2. A relative link in the README points at a file this PR deletes. See the [LEZ Framework template README](./templates/lez-framework/README.md)
for details.That is a dead link on the repo's front page, not just stale prose. Whatever replaces it has to point somewhere Also new:
|
New findings from a code-level pass — two of them change the rebase plan, so they are worth having before the rebaseNo new commits here (head is still My 2026-08-25 and 2026-08-27 reviews stand in full and I am not restating them. This pass is different: I stopped waiting on the rebase and read the delegation against current Environment: Nix 2.35.2, Rust 1.94.1, r0vm 3.0.5, risc0 guest toolchains rust 1. The
|
Follow-up: I finished provisioning and ran the pinned
|
|
sorry, my bot went nuts on your PR and I think this is not needed, no? @vpavlin ? do you want me to pick it up? |
Summary
lgs new --template spel(new default for framework projects) callsspel init <name> --lez-tag <lez-tag>, then layersscaffold.tomland AI skills on top. Scaffold owns no SPEL template files.lgs new --template lez-frameworkprints a deprecation warning and maps tospel. Existingscaffold.tomlfiles withframework.kind = "lez-framework"continue to work.FRAMEWORK_KIND_SPEL = "spel"added to constants.lgs build idlon spel projects delegates tospel generate-idl(vendored binary).lgs build clienton spel projects delegates tospel ffi-gen.lez-frameworkandspelprojects.templates/lez-framework/deleted — the template referencedjimmy-claw/lez-framework(broken) and duplicated logic that belongs in spel.skills/lez-framework-template/renamed →skills/spel-template/with updated content (spel vocabulary:#[spel_program],spel.toml,maketargets, spel CLI).Why
The
lez-frameworktemplate was broken (wrong repo, old macros) and maintained a parallel scaffolding path to whatspel initalready does correctly. This change makes scaffold's role minimal: version pinning,scaffold.toml, and AI skills — program scaffolding belongs to spel.Closes logos-co/ecosystem#128 (scaffold now uses released spel for framework projects).
Test plan
lgs new my-project --template spelsucceeds withspelon PATH and produces a buildable projectlgs new my-project --template lez-frameworkprints deprecation warning and produces same resultlgs new my-project(default) still uses thedefaulttemplate (bare LEZ, no change)lgs build idlin a spel project callsspel generate-idlvia the vendored binarycargo test --lib)🤖 Generated with Claude Code