diff --git a/assets/README.md b/assets/README.md new file mode 100644 index 00000000..918d4674 --- /dev/null +++ b/assets/README.md @@ -0,0 +1,20 @@ +# Assets + +## `demo.cast` / `demo.svg` + +`demo.svg` (embedded in the root `README.md`) is rendered from `demo.cast`, an +[asciinema v2](https://docs.asciinema.org/manual/asciicast/v2/) recording. + +The cast is staged (hand-authored timings), but **every output line must match +the real CLI byte for byte** — the scaffold lines `zuke setup --yes` prints, the +`--list` format (plain text, two-space column padding), and the executor's run +output (an 80-wide `═` header block per target, a blank line after each +target's footer, the Build Summary table, and the closing verdict line). When +the renderer or `zuke setup` output changes, re-verify each frame against a +real run and update the cast in the same PR. + +Render the SVG with [svg-term-cli](https://github.com/marionebl/svg-term-cli): + +```sh +npx svg-term-cli --in assets/demo.cast --out assets/demo.svg --window +``` diff --git a/assets/demo.cast b/assets/demo.cast index c50a9d91..c8612e0e 100644 --- a/assets/demo.cast +++ b/assets/demo.cast @@ -1,111 +1,132 @@ -{"version":2,"width":90,"height":30,"timestamp":1719045600,"env":{"SHELL":"/bin/bash","TERM":"xterm-256color"}} +{"version":2,"width":90,"height":30,"timestamp":1755079380,"env":{"SHELL":"/bin/bash","TERM":"xterm-256color"}} [0.6,"o","\u001b[32m❯\u001b[0m "] -[1.05,"o","d"] -[1.09,"o","e"] -[1.13,"o","n"] -[1.17,"o","o"] -[1.21,"o"," "] -[1.25,"o","r"] -[1.29,"o","u"] -[1.33,"o","n"] -[1.37,"o"," "] -[1.41,"o","-"] -[1.45,"o","A"] -[1.49,"o"," "] -[1.53,"o","j"] -[1.57,"o","s"] -[1.61,"o","r"] -[1.65,"o",":"] -[1.69,"o","@"] -[1.73,"o","z"] -[1.77,"o","u"] -[1.81,"o","k"] -[1.85,"o","e"] -[1.89,"o","/"] -[1.93,"o","c"] -[1.97,"o","l"] -[2.01,"o","i"] -[2.05,"o"," "] -[2.09,"o","s"] -[2.13,"o","e"] -[2.17,"o","t"] -[2.21,"o","u"] -[2.25,"o","p"] -[2.64,"o","\r\n"] -[3.14,"o","\u001b[32m✓\u001b[0m Scaffolded \u001b[1mzuke.ts\u001b[0m, ./zuke, ./zuke.ps1, deno.json\r\n"] -[3.89,"o","\u001b[32m❯\u001b[0m "] -[4.34,"o","c"] -[4.38,"o","a"] -[4.42,"o","t"] -[4.46,"o"," "] -[4.5,"o","z"] -[4.54,"o","u"] -[4.58,"o","k"] -[4.62,"o","e"] -[4.66,"o","."] -[4.7,"o","t"] -[4.74,"o","s"] -[5.13,"o","\r\n"] -[5.43,"o","\u001b[90mimport\u001b[0m { Build, target, run } \u001b[90mfrom\u001b[0m \"jsr:@zuke/core\";\r\n"] -[5.48,"o","\u001b[90mimport\u001b[0m { DenoTasks } \u001b[90mfrom\u001b[0m \"jsr:@zuke/deno\";\r\n"] -[5.53,"o","\r\n"] -[5.58,"o","\u001b[90mclass\u001b[0m \u001b[33mPipeline\u001b[0m \u001b[90mextends\u001b[0m Build {\r\n"] -[5.63,"o"," lint = target().executes(() => DenoTasks.lint());\r\n"] -[5.68,"o"," test = target().dependsOn(\u001b[36mthis.lint\u001b[0m) \u001b[90m// a reference, not \"lint\"\u001b[0m\r\n"] -[5.73,"o"," .executes(() => DenoTasks.test((s) => s.allowAll()));\r\n"] -[5.78,"o","}\r\n"] -[5.83,"o","\r\n"] -[5.88, "o", "\u001b[90mawait\u001b[0m run(Pipeline);\r\n"] -[6.78,"o","\u001b[32m❯\u001b[0m "] -[7.23,"o","."] -[7.27,"o","/"] -[7.31,"o","z"] -[7.35,"o","u"] -[7.39,"o","k"] -[7.43,"o","e"] -[7.47,"o"," "] -[7.51,"o","-"] -[7.55,"o","-"] -[7.59,"o","l"] -[7.63,"o","i"] -[7.67,"o","s"] -[7.71,"o","t"] -[8.1,"o","\r\n"] -[8.5,"o","\u001b[1mTargets:\u001b[0m\r\n"] -[8.62,"o"," lint Lint the workspace\r\n"] -[8.74,"o"," test Run the test suite \u001b[90m(depends on: lint)\u001b[0m\r\n"] -[9.55,"o","\u001b[32m❯\u001b[0m "] -[10,"o","."] -[10.04,"o","/"] -[10.08,"o","z"] -[10.12,"o","u"] -[10.16,"o","k"] -[10.2,"o","e"] -[10.24,"o"," "] -[10.28,"o","t"] -[10.32,"o","e"] -[10.36,"o","s"] -[10.4,"o","t"] -[10.79,"o","\r\n"] -[11.29,"o","\u001b[2m════════════════════════════════════════════════════════════════════════════════\u001b[0m\r\n"] -[11.34,"o","\u001b[1m\u001b[36mlint\u001b[0m\r\n"] -[11.39,"o","\u001b[2m════════════════════════════════════════════════════════════════════════════════\u001b[0m\r\n"] -[11.84,"o","\u001b[32m✔\u001b[0m lint \u001b[2msucceeded in 0.1s\u001b[0m\r\n"] -[12.19,"o","\u001b[2m════════════════════════════════════════════════════════════════════════════════\u001b[0m\r\n"] -[12.24,"o","\u001b[1m\u001b[36mtest\u001b[0m\r\n"] -[12.29,"o","\u001b[2m════════════════════════════════════════════════════════════════════════════════\u001b[0m\r\n"] -[12.64,"o","\u001b[2mrunning 3 tests\u001b[0m\r\n"] -[12.69,"o","\u001b[32mok\u001b[0m | 3 passed | 0 failed \u001b[2m(0.8s)\u001b[0m\r\n"] -[13.19,"o","\u001b[32m✔\u001b[0m test \u001b[2msucceeded in 0.8s\u001b[0m\r\n"] -[13.69,"o","\r\n"] -[13.75,"o","\u001b[1mBuild Summary\u001b[0m\r\n"] -[13.81,"o","\u001b[2m───────────────────────────\u001b[0m\r\n"] -[13.87,"o","\u001b[1mTarget Status Duration\u001b[0m\r\n"] -[13.93,"o","\u001b[2m───────────────────────────\u001b[0m\r\n"] -[13.99,"o","lint \u001b[32mSucceeded\u001b[0m 0.1s\r\n"] -[14.05,"o","test \u001b[32mSucceeded\u001b[0m 0.8s\r\n"] -[14.11,"o","\u001b[2m───────────────────────────\u001b[0m\r\n"] -[14.17,"o","\u001b[1mTotal \u001b[0m \u001b[1m 0.9s\u001b[0m\r\n"] -[14.23,"o","\r\n"] -[14.29,"o","\u001b[1m\u001b[32m✔ Build succeeded — 2/2 targets in 0.9s · 2026-06-23 12:00\u001b[0m\r\n"] -[15.75,"o","\u001b[32m❯\u001b[0m "] +[1.09,"o","d"] +[1.13,"o","e"] +[1.17,"o","n"] +[1.21,"o","o"] +[1.25,"o"," "] +[1.29,"o","r"] +[1.33,"o","u"] +[1.37,"o","n"] +[1.41,"o"," "] +[1.45,"o","-"] +[1.49,"o","A"] +[1.53,"o"," "] +[1.57,"o","j"] +[1.61,"o","s"] +[1.65,"o","r"] +[1.69,"o",":"] +[1.73,"o","@"] +[1.77,"o","z"] +[1.81,"o","u"] +[1.85,"o","k"] +[1.89,"o","e"] +[1.93,"o","/"] +[1.97,"o","c"] +[2.01,"o","l"] +[2.05,"o","i"] +[2.09,"o"," "] +[2.13,"o","s"] +[2.17,"o","e"] +[2.21,"o","t"] +[2.25,"o","u"] +[2.29,"o","p"] +[2.33,"o"," "] +[2.37,"o","-"] +[2.41,"o","-"] +[2.45,"o","y"] +[2.49,"o","e"] +[2.53,"o","s"] +[2.88,"o","\r\n"] +[3.78,"o","Scaffolding Zuke into the current directory:\r\n"] +[4.03,"o"," create zuke.ts\r\n"] +[4.15,"o"," create zuke\r\n"] +[4.27,"o"," create zuke.ps1\r\n"] +[4.39,"o"," create zuke.json\r\n"] +[4.51,"o"," create deno.json\r\n"] +[4.63,"o"," create .gitignore\r\n"] +[4.93,"o","Done — 6 file(s) written. Next: ./zuke\r\n"] +[5.83,"o","\u001b[32m❯\u001b[0m "] +[6.32,"o","c"] +[6.36,"o","a"] +[6.4,"o","t"] +[6.44,"o"," "] +[6.48,"o","z"] +[6.52,"o","u"] +[6.56,"o","k"] +[6.6,"o","e"] +[6.64,"o","."] +[6.68,"o","t"] +[6.72,"o","s"] +[7.07,"o","\r\n"] +[7.47,"o","\u001b[90mimport\u001b[0m { Build, run, target } \u001b[90mfrom\u001b[0m \"jsr:@zuke/core@^1\";\r\n"] +[7.52,"o","\u001b[90mimport\u001b[0m { DenoTasks } \u001b[90mfrom\u001b[0m \"jsr:@zuke/deno@^1\";\r\n"] +[7.57,"o","\r\n"] +[7.62,"o","\u001b[90mclass\u001b[0m \u001b[33mPipeline\u001b[0m \u001b[90mextends\u001b[0m Build {\r\n"] +[7.67,"o"," lint = target()\r\n"] +[7.72,"o"," .description(\"Lint the workspace\")\r\n"] +[7.77,"o"," .executes(() => DenoTasks.lint());\r\n"] +[7.82,"o","\r\n"] +[7.87,"o"," test = target()\r\n"] +[7.92,"o"," .description(\"Run the test suite\")\r\n"] +[7.97,"o"," .dependsOn(\u001b[36mthis.lint\u001b[0m) \u001b[90m// a reference, not \"lint\"\u001b[0m\r\n"] +[8.02,"o"," .executes(() => DenoTasks.test((s) => s.allowAll()));\r\n"] +[8.07,"o","}\r\n"] +[8.12,"o","\r\n"] +[8.17,"o","\u001b[90mawait\u001b[0m run(Pipeline);\r\n"] +[9.17,"o","\u001b[32m❯\u001b[0m "] +[9.66,"o","."] +[9.7,"o","/"] +[9.74,"o","z"] +[9.78,"o","u"] +[9.82,"o","k"] +[9.86,"o","e"] +[9.9,"o"," "] +[9.94,"o","-"] +[9.98,"o","-"] +[10.02,"o","l"] +[10.06,"o","i"] +[10.1,"o","s"] +[10.14,"o","t"] +[10.49,"o","\r\n"] +[10.89,"o","Targets:\r\n"] +[10.94,"o"," lint Lint the workspace\r\n"] +[10.99,"o"," test Run the test suite (depends on: lint)\r\n"] +[11.99,"o","\u001b[32m❯\u001b[0m "] +[12.48,"o","."] +[12.52,"o","/"] +[12.56,"o","z"] +[12.6,"o","u"] +[12.64,"o","k"] +[12.68,"o","e"] +[12.72,"o"," "] +[12.76,"o","t"] +[12.8,"o","e"] +[12.84,"o","s"] +[12.88,"o","t"] +[13.23,"o","\r\n"] +[13.73,"o","\u001b[2m════════════════════════════════════════════════════════════════════════════════\u001b[0m\r\n"] +[13.78,"o","\u001b[1m\u001b[36mlint\u001b[0m\r\n"] +[13.83,"o","\u001b[2m════════════════════════════════════════════════════════════════════════════════\u001b[0m\r\n"] +[14.73,"o","Checked 24 files\r\n"] +[15.03,"o","\u001b[32m✔\u001b[0m lint \u001b[2msucceeded in 1.2s\u001b[0m\r\n"] +[15.08,"o","\r\n"] +[15.43,"o","\u001b[2m════════════════════════════════════════════════════════════════════════════════\u001b[0m\r\n"] +[15.48,"o","\u001b[1m\u001b[36mtest\u001b[0m\r\n"] +[15.53,"o","\u001b[2m════════════════════════════════════════════════════════════════════════════════\u001b[0m\r\n"] +[16.03,"o","running 3 tests from ./tests/pipeline_test.ts\r\n"] +[17.43,"o","\u001b[32mok\u001b[0m | 3 passed | 0 failed \u001b[2m(1.9s)\u001b[0m\r\n"] +[17.73,"o","\u001b[32m✔\u001b[0m test \u001b[2msucceeded in 2.4s\u001b[0m\r\n"] +[17.78,"o","\r\n"] +[18.18,"o","\u001b[1mBuild Summary\u001b[0m\r\n"] +[18.24,"o","\u001b[2m───────────────────────────\u001b[0m\r\n"] +[18.3,"o","\u001b[1mTarget Status Duration\u001b[0m\r\n"] +[18.36,"o","\u001b[2m───────────────────────────\u001b[0m\r\n"] +[18.42,"o","lint \u001b[32mSucceeded\u001b[0m 1.2s\r\n"] +[18.48,"o","test \u001b[32mSucceeded\u001b[0m 2.4s\r\n"] +[18.54,"o","\u001b[2m───────────────────────────\u001b[0m\r\n"] +[18.6,"o","\u001b[1mTotal \u001b[0m \u001b[1m 3.6s\u001b[0m\r\n"] +[18.66,"o","\r\n"] +[18.72,"o","\u001b[1m\u001b[32m✔ Build succeeded — 2/2 targets in 3.6s · 2026-08-13 10:03\u001b[0m\r\n"] +[19.92,"o","\u001b[32m❯\u001b[0m "] +[23.42,"o","\u001b[0m"] diff --git a/assets/demo.svg b/assets/demo.svg index 676340cc..18492ae1 100644 --- a/assets/demo.svg +++ b/assets/demo.svg @@ -1 +1 @@ -denodenorundenorun-Adenorun-Ajsr:@zuke/clidenorun-Ajsr:@zuke/clisetupScaffoldedzuke.ts,./zuke,./zuke.ps1,deno.jsoncatcatzuke.tsimport{Build,target,run}from"jsr:@zuke/core";import{DenoTasks}from"jsr:@zuke/deno";classPipelineextendsBuild{lint=target().executes(()=>DenoTasks.lint());test=target().dependsOn(this.lint)//areference,not"lint".executes(()=>DenoTasks.test((s)=>s.allowAll()));}awaitrun(Pipeline);.././z./zu./zuk./zuke./zuke--listTargets:lintLinttheworkspacetestRunthetestsuite(dependson:lint)./zuketest════════════════════════════════════════════════════════════════════════════════lintlintsucceededin0.1stestrunning3testsok|3passed|0failed(0.8s)testsucceededin0.8sBuildSummary───────────────────────────TargetStatusDurationlintSucceeded0.1stestSucceeded0.8sTotal0.9sBuildsucceeded2/2targetsin0.9s·2026-06-2312:00ddedendenordenorudenorun-denorun-Ajdenorun-Ajsdenorun-Ajsrdenorun-Ajsr:denorun-Ajsr:@denorun-Ajsr:@zdenorun-Ajsr:@zudenorun-Ajsr:@zukdenorun-Ajsr:@zukedenorun-Ajsr:@zuke/denorun-Ajsr:@zuke/cdenorun-Ajsr:@zuke/cldenorun-Ajsr:@zuke/clisdenorun-Ajsr:@zuke/clisedenorun-Ajsr:@zuke/clisetdenorun-Ajsr:@zuke/clisetuccacatzcatzucatzukcatzukecatzuke.catzuke.t./zuke-./zuke--./zuke--l./zuke--li./zuke--lis./zuket./zukete./zuketes \ No newline at end of file +denodenorundenorun-Adenorun-Ajsr:@zuke/clidenorun-Ajsr:@zuke/clisetupdenorun-Ajsr:@zuke/clisetup--yesScaffoldingZukeintothecurrentdirectory:createzuke.tscreatezukecreatezuke.ps1createzuke.jsoncreatedeno.jsoncreate.gitignoreDone6file(s)written.Next:./zukecatcatzuke.tsimport{Build,run,target}from"jsr:@zuke/core@^1";import{DenoTasks}from"jsr:@zuke/deno@^1";classPipelineextendsBuild{lint=target().description("Linttheworkspace").executes(()=>DenoTasks.lint());test=target().description("Runthetestsuite").dependsOn(this.lint)//areference,not"lint".executes(()=>DenoTasks.test((s)=>s.allowAll()));}awaitrun(Pipeline);.././z./zu./zuk./zuke./zuke--listTargets:lintLinttheworkspacetestRunthetestsuite(dependson:lint)./zuketest════════════════════════════════════════════════════════════════════════════════lintChecked24fileslintsucceededin1.2stestrunning3testsfrom./tests/pipeline_test.tsok|3passed|0failed(1.9s)testsucceededin2.4sBuildSummary───────────────────────────TargetStatusDurationlintSucceeded1.2stestSucceeded2.4sTotal3.6sBuildsucceeded2/2targetsin3.6s·2026-08-1310:03ddedendenordenorudenorun-denorun-Ajdenorun-Ajsdenorun-Ajsrdenorun-Ajsr:denorun-Ajsr:@denorun-Ajsr:@zdenorun-Ajsr:@zudenorun-Ajsr:@zukdenorun-Ajsr:@zukedenorun-Ajsr:@zuke/denorun-Ajsr:@zuke/cdenorun-Ajsr:@zuke/cldenorun-Ajsr:@zuke/clisdenorun-Ajsr:@zuke/clisedenorun-Ajsr:@zuke/clisetdenorun-Ajsr:@zuke/clisetudenorun-Ajsr:@zuke/clisetup-denorun-Ajsr:@zuke/clisetup--denorun-Ajsr:@zuke/clisetup--ydenorun-Ajsr:@zuke/clisetup--yeccacatzcatzucatzukcatzukecatzuke.catzuke.t./zuke-./zuke--./zuke--l./zuke--li./zuke--lis./zuket./zukete./zuketes \ No newline at end of file