English · Español
Solution 01 — just manifest reference¶
Read only after completing
../lab/01-write-the-justfile.mdand committing your attempt. Compare against this reference, not before.
Reference recipe¶
Append to /Justfile:
# Record a per-experiment manifest. Used by every numeric experiment from Phase 4+.
# Usage: just manifest <topic>
manifest topic:
#!/usr/bin/env bash
set -euo pipefail
safe_topic=$(printf '%s' "{{topic}}" | tr -c '[:alnum:]._-' '-' )
dir="experiments/$(date +%F)-${safe_topic}"
mkdir -p "$dir"
versions=$(uv run python -c "from utils.seeding import log_versions; import json; print(json.dumps(log_versions()))")
git_sha=$(git rev-parse HEAD 2>/dev/null || echo "no-git")
if git diff-index --quiet HEAD -- 2>/dev/null; then
git_dirty=false
else
git_dirty=true
fi
cpu=$(awk -F: '/^model name/{print $2; exit}' /proc/cpuinfo | sed 's/^ //')
kernel=$(uname -r)
os=$(. /etc/os-release && echo "$PRETTY_NAME")
cat > "$dir/manifest.json" <<JSON
{
"id": "$(date +%F)-${safe_topic}",
"git_sha": "${git_sha}",
"git_dirty": ${git_dirty},
"seed": 42,
"versions": ${versions},
"hardware": { "cpu": "${cpu}", "kernel": "${kernel}", "os": "${os}" },
"started_at": "$(date -u +%FT%TZ)"
}
JSON
echo "$dir/manifest.json"
Decisions made in this reference¶
set -euo pipefail— fail loudly on any error, undefined var, or pipeline failure. Without it, a missinggitwould silently producegit_sha: "".safe_topic— replace anything non-alphanumeric (plus.,_,-) with-. Preventstopic=foo;rm -rf .from injecting commands.#!/usr/bin/env bash— the recipe is a single bash script (just supports shebangs). This is cleaner than chaining commands with&&./proc/cpuinfo— Fedora-friendly CPU model extraction. Falls back gracefully if the file isn't there (would produce emptycpu, butset -eis on so we'd fail before producing a half-manifest — acceptable).started_atonly, nofinished_at— this recipe records the start manifest; the experiment script that consumes it updatesfinished_atandwall_secondswhen it's done. Coupling them would force every experiment to invokejust manifestand a finish step, which is awkward.- Idempotency: re-running the recipe with the same topic on the same day overwrites the manifest. Defensible: a re-run is a re-run. If you want history, use a different topic.
What I'd flag in a review¶
- The
versionsis captured outside the experiment process — so if your experiment script changes its venv state, the manifest is stale. Realrecord_manifestinsrc/utils/will be called inside the experiment, which is correct. This recipe is a quick ad-hoc tool. - No
pid,user,hostfields. Add them if you collaborate or run on shared hardware. - The recipe blocks on
gitbeing available. For a no-git checkout (rare), it falls back to"no-git"— acceptable for a curriculum, not for a regulated environment.
Reference test¶
Create tests/test_justfile.py:
import json
import re
import subprocess
from pathlib import Path
def test_manifest_recipe(tmp_path: Path, monkeypatch) -> None:
# The recipe writes inside the repo; we'd ideally redirect to tmp_path.
# For a curriculum exercise, asserting "the file exists and parses" is enough.
result = subprocess.run(
["just", "manifest", "lab-test"],
capture_output=True,
text=True,
check=True,
)
path = Path(result.stdout.strip())
assert path.exists()
assert path.suffix == ".json"
data = json.loads(path.read_text())
assert data["versions"]["python"].startswith("3.11")
assert re.fullmatch(r"[0-9a-f]{40}", data["git_sha"]) or data["git_sha"] == "no-git"
assert isinstance(data["git_dirty"], bool)
assert data["seed"] == 42
assert data["id"].endswith("lab-test")
Why this test is "good enough" rather than "perfect"¶
A perfect test would redirect the recipe to write under tmp_path. That requires either:
- A --dir parameter on the recipe (over-engineering for the curriculum).
- A chdir into tmp_path and a recipe that resolves paths relative to pwd (already the case — try it).
Either is fine. The version above is a smoke test; the second is a unit test. Pick based on how much friction you'll tolerate.
Comparison checklist¶
When diffing your version against this one, check:
- Did you quote
{{topic}}correctly? An unquoted${topic}allows path traversal (../../something). - Did you
mkdir -p(no error if exists) rather thanmkdir? - Did you set
git_dirtyas a real boolean in the JSON (not the string"true")? - Did you handle the no-git case?
- Did you embed versions as a nested object, not a stringified JSON?
If any "no" — note it in learners/borja/phase-00/notes/justfile-notes.md and decide whether to fix. Sometimes the answer is "my way is fine for the curriculum" — that's a valid conclusion.