Walkthrough
Follow along in your own environment. Copy the commands and adapt them to match your setup.
Complete the one-time setup so that command -v pico points at this repository’s bin/pico and not at /usr/bin/pico (the Alpine/nano text editor).
This lab uses the local-scratch-dir sandbox provider — a scoped local scratch directory plus a PATH allowlist, not a container — exactly like the Hello World Pico Sandcastle lab. Container-backed providers are tracked as a Sandcastle curriculum follow-up. Only the workspace.sandboxProvider field in the generated EngineeringTask changes when they land; the walkthrough below stays the same.
Step 1 — Inspect the Crossplane request
From the root of your local clone, open labs/compose-sandcastle-request/downloads/xr-request.yaml:
cat labs/compose-sandcastle-request/downloads/xr-request.yamlThe XR is an XHelloWorldPico — the same apiVersion and kind used by labs/hello-pico-on-kubernetes/downloads/05-xr.yaml. The greeting is deliberately different from Hello, Pico! so you can see the Sandcastle honour whatever the request asks for.
Step 2 — Compose the EngineeringTask (Crossplane side)
Run the simulated composition against the XR:
bash labs/compose-sandcastle-request/downloads/compose.sh \
labs/compose-sandcastle-request/downloads/xr-request.yaml \
work/compose-sandcastle-requestExpected tail of the output:
compose: wrote work/compose-sandcastle-request/task/engineering-task.yaml (kind=EngineeringTask name=greetings-de greeting=Hallo\,\ Pico\! branch=sandcastle/hello-world-pico-greetings-de)
compose: the composition wrote no code and touched no repository.
Inspect the emitted EngineeringTask:
cat work/compose-sandcastle-request/task/engineering-task.yamlThe task is a declarative record of construction work, not a copy of the XR. It carries the greeting under spec.inputs.greeting, names the target branch under spec.target.branch, and keeps spec.requestedBy as a provenance pointer back to the XR — no code has been written.
Step 3 — Run the Sandcastle against the EngineeringTask
Run the driver against the task. It provisions the isolated workspace, copies the task file into the sandbox as the only compose-side input, runs the agent under a PATH allowlist, hands the branch back, and disposes of the workspace.
bash labs/compose-sandcastle-request/downloads/sandcastle-run.sh \
work/compose-sandcastle-request/task/engineering-task.yaml \
work/compose-sandcastle-requestExpected tail of the driver output:
[agent] inspect: greeting requested by task = Hallo, Pico!
[agent] validate: OK (parser accepted the rule)
[agent] compose: artifact prints Hallo, Pico!
[agent] commit: adding rules/hello.yaml on branch sandcastle/hello-world-pico-greetings-de
sandcastle-run: done. sandbox destroyed; durable artifacts under work/compose-sandcastle-request/results/
The [agent] lines come from sandcastle-agent.sh running inside the sandbox; the sandcastle-run: lines come from the driver running outside the sandbox. The agent never sees the XR — it only reads the task file mounted at ./.engineering-task.yaml.
Step 4 — Confirm the durable branch matches the request
After the driver returns, the sandbox is gone. Only the target repo and its captured evidence remain:
ls work/compose-sandcastle-request/
# → bin-allowlist results target-repo task
test ! -d work/compose-sandcastle-request/sandbox && echo "sandbox: disposed"Inspect the durable branch on the target repo:
git -C work/compose-sandcastle-request/target-repo \
log --oneline sandcastle/hello-world-pico-greetings-de
git -C work/compose-sandcastle-request/target-repo \
show sandcastle/hello-world-pico-greetings-de:rules/hello.yamlThe rule’s value: field matches spec.value from the XR — proof that the construction stage honoured the request.
The driver also recomposed the Pico from a fresh clone of the target branch. Confirm the greeting it captured matches what the XR asked for:
cat work/compose-sandcastle-request/results/pico-output.txt
# → Hallo, Pico!Step 5 — Run the automatable verification
Re-run the full path under the packaged verifier:
bash labs/compose-sandcastle-request/downloads/verify.shverify.sh runs compose.sh and sandcastle-run.sh and asserts:
- The generated EngineeringTask matches the reference shape on the fields that cross the compose → construct boundary.
sandcastle/hello-world-pico-<name>exists on the target repo withrules/hello.yamlcarrying the greeting the XR asked for.- Recomposing from a fresh clone of that branch prints the same greeting.
- The sandbox workspace is gone.
- The construction stage never saw the XR — no XR shape and no
.engineering-task.yamlleaked across the artifact boundary.
On success it exits 0 and prints a line beginning with verify: OK — branch=....
Try it with a different greeting
Change spec.value in xr-request.yaml and re-run the three commands from Steps 2, 3 and 5. Nothing else changes: the composition emits a task carrying your new greeting, the Sandcastle constructs a branch whose rule uses that greeting, and verify.sh still exits 0.
Screenshot targets
Three terminal moments in this walkthrough make good screenshots for future revisions of the lab. They are catalogued in screenshots/README.md with intended filenames, capture regions, and alt text:
- Step 2 →
screenshots/01-compose-task.png—compose.sh’swrote ...engineering-task.yamlline and the emitted YAML. - Step 3 →
screenshots/02-agent-run.png— the agent’sgreeting requested by task = ...line andsandcastle-run: done.teardown line. - Step 5 →
screenshots/03-verify-ok.png— the finalverify: OK — branch=…line fromverify.sh.
No image files ship with this lab yet; the lab renders and runs without them.
Troubleshooting
- If
picoopens a text editor instead of running, your shell is still resolvingpicoto/usr/bin/pico. Re-run thePATHexport from one-time setup and confirm withcommand -v pico. - If
sandcastle-run.shfails at required host tool not on PATH: <name>, install that tool (or make it discoverable onPATH) and re-run. - If
verify.shfails at assertion 4 with “sandbox workspace should have been disposed”, the driver was interrupted mid-run. Deletework/compose-sandcastle-requestand re-run.
Next
Compare your result against the reference solution.