← Lab Ready
API
Tokens

Run Lab Ready from your own code

Both metered lanes are available over HTTP and each returns one JSON object. The division of labour: the page takes capacity as the lowest of three ceilings, sizes coverage against its convention, sorts the prerequisites and checks the agenda, and picks the hands-on commitment, coverage, prerequisite path and network posture - all free, in labkit.js. The run writes the sheet or the note; the page then holds the reply to its own figures (labreply.js).

Base URL and the response shape

Every endpoint lives under https://api.skillsafe.ai/v1/app-api, and every response has one shape:

{ "ok": true,  "data":  { ... } }
{ "ok": false, "error": { "code": "...", "message": "..." } }

The token is minted for this app (the guest call takes {"slug":"lab-ready"}), so no slug header is needed afterwards. Send it as Authorization: Bearer …. The run body is the input object, sent bare.

StatusCodeMeaning
400validation_errorThe body is not a JSON object, or a required key (task, session, room, facts) is missing.
401unauthorizedNo token, or a stale one. Mint a guest token or sign in again.
402insufficient_creditsThe balance is under min_credits. Price with /estimate first.
403forbiddenA guest token tried to run: both lanes are metered and need a personal sign-in.
404not_foundUnknown job id.
429rate_limitedBack off and retry.
5xxserver_errorTransient. Retry with the same Idempotency-Key so a retry never double-bills.

The task field comes first

Two lanes - sheet (the per-session delivery sheet for the organizers) and preflight (the note participants receive before the day). A missing or unknown task is answered as sheet. Both lanes send the same four fields.

The input

FieldRequiredWhat
taskyessheet or preflight. If it is missing or neither, do sheet and set "task": "sheet".
sessionyesthe workshop, the room, what the exercise needs, the machines, the venue's network answer and the practices in place.
roomyesthe helpers and whether each knows the material, the prerequisites by class, and the agenda in order with its total.
factsyesthe page's menus with their rungs and picks, the coverage sizing, the capacity ceilings, the checks, the signals and every finding tagged [fix], [check] or [info], most urgent first.
retry_notenooptional; if present, your previous reply was unusable - follow it.

The rules the model applies

House rules

The replies

sheet

  1. summary - one sentence, at most 35 words: the most urgent finding and the first change.
  2. hands - pick (none, demo or full, the page's), reason (one sentence).
  3. capacity - number (the page's capacity), bound (the page's binding ceiling or ceilings: room, coverage, throughput), note (one sentence: what to do about the registrations).
  4. coverage - pick (solo, peer, roaming or stationed, the page's), needed (the page's figure, like "4-5" or "2"), basis (one sentence: the convention with its context), adjustment (one sentence: the adjustment for this room, labelled self-set).
  5. prereqs - pick (nothing, published, provisioned or both, the page's), knowledge, machine, accounts (each a list of the page's items in that class, copied; add "to be named" only where the page flags the class as missing), note (one sentence).
  6. network - pick (assume, declare, clear or remove, the page's), venue (one sentence: what the venue has answered, as the page says), note (one sentence).
  7. agenda - one object per block in the page's order: block (exactly), minutes (the page's number), note (one short sentence).
  8. materials - window (the page's access window, or "to be named"), note (one sentence: where the material lives afterwards).
  9. triggers - 2 to 4 objects: choice (one of hands, capacity, coverage, prereqs, network, agenda, materials), trigger (one sentence: the result next edition that would revise it - your design).
  10. checks - one object per delivery check in the page's order: check (the page's short name for it, exactly), pass (true or false, as the page says).
  11. signals - 2 or 3 short strings, the page's signals, each with what it would change next edition.
  12. caveats - at most 4 short strings: [fix] findings first in the page's order (the first four when there are more), then [check] findings in the page's order. [] when there are none of either.
{
  "task": "sheet",
  "summary": "one sentence",
  "hands": { "pick": "full", "reason": "one sentence" },
  "capacity": { "number": 30, "bound": ["coverage"], "note": "one sentence" },
  "coverage": { "pick": "roaming", "needed": "4-5", "basis": "one sentence", "adjustment": "one sentence" },
  "prereqs": { "pick": "published", "knowledge": ["an item"], "machine": ["an item"], "accounts": [], "note": "one sentence" },
  "network": { "pick": "declare", "venue": "one sentence", "note": "one sentence" },
  "agenda": [ { "block": "Setup check", "minutes": 20, "note": "one short sentence" } ],
  "materials": { "window": "1 month", "note": "one sentence" },
  "triggers": [ { "choice": "coverage", "trigger": "one sentence" } ],
  "checks": [ { "check": "Coverage", "pass": false } ],
  "signals": [ "what to record and what it changes" ],
  "caveats": [ "a caveat" ]
}

The page holds it to its own figures: the four picks, the capacity and its binding ceiling, the helper range, every prerequisite copied into its class, every agenda block with its minutes, the access window and the checks; no figure may appear that the input does not hold.

preflight

  1. title - a short heading naming the workshop.
  2. intro - one or two sentences: what the session is, its length in minutes, and that the setup check starts on time.
  3. knowledge, machine, accounts - each a list of short instructions, one per page item in that class, carrying the item's own words; [] when the page has none in that class. Never add a tool, version or account the page does not list.
  4. check_steps - 2 to 5 short steps a participant does before the day to confirm they are ready (your design, built only from the page's items and its network facts); for a provisioned environment, the steps confirm the login and the browser, not an install.
  5. network - one or two sentences, by the page's network pick: declare - the session needs the internet, and the fallback is their own data; clear - the session needs the internet, and the organizers are confirming the room's network with the venue; remove - the exercises run without a live connection; assume - the session uses the venue's network. When the page says participants download, install or sign in during the session, ask them to do it before the day.
  6. bring - 1 to 4 short items to bring (a charged laptop and its charger when they work on their own machine; nothing the page does not imply).
  7. after - one sentence: where questions go afterwards and how long the material stays available, as the page says (write "to be announced" where the page has none).
  8. note - one sentence, at most 30 words, for the organizers (not the participants): what to settle before this note is sent.
{
  "task": "preflight",
  "title": "a short heading",
  "intro": "one or two sentences",
  "knowledge": [ "an instruction" ],
  "machine": [ "an instruction" ],
  "accounts": [],
  "check_steps": [ "a step" ],
  "network": "one or two sentences",
  "bring": [ "an item" ],
  "after": "one sentence",
  "note": "one sentence"
}

The page requires every prerequisite carried in its own class with nothing added, the session length in the intro, two to five readiness steps (no install for a provisioned environment), the own-data fallback when the dependency is declared, and the access window.

Worked examples - every lane, every sample

These are the page's three free samples (fictional events and people; every figure is illustrative). Each input is exactly what the page sends; each reply is the saved reply the sample replays, shipped as the validating model wrote it; the last line is the page's own check. Every sample has both lanes.

Kubernetes from zero (a 3-hour conference lab) - sheet

180 minutes, 40 registrations; capacity 30, bound by coverage; roaming troubleshooter; published prerequisites; clear the room's network in writing; 1 of 6 checks.

Input:

{
 "task": "sheet",
 "session": "Workshop: Kubernetes from zero at Quillmoor Ops Days; booked length 180 minutes; 40 registrations; ticketed; a curriculum run every edition\nRoom: 36 seats; power at 24 seats; 1 instructor\nExercise: the skill can be acquired by reading no; installs on a participant's machine yes; accounts to sign up for yes; a live network service while it runs yes (the dependency can be removed no); participants download, install or sign in during the session yes; distinct workstations no\nMachines: every participant brings a capable machine they may install on yes; employer-managed laptops no; the organizer accepts a platform's terms and issues credentials no; minors present no\nVenue network: said \"it's fine\", nothing written; unusual protocol, port or device class needed no; prior edition: bandwidth failed\nPractice: pre-day check no; dry run on a fresh machine yes; two-colour sticky notes no; helpers briefed that participants type no; follow-up channel yes; material access window 1 month",
 "room": "Helpers (name | knows the material):\n  Ines | yes\n  Marco | no - logistics only\n  Lena | no - logistics only\n  Tom | yes\nPrerequisites as entered, by class:\n  knowledge: Comfortable in a terminal\n  machine: Docker Desktop 4.x running; kubectl 1.30 on the path\n  account: none - MISSING, the exercise needs one\nAgenda, in order (block | minutes | checkpoint | kind):\n1. Welcome | 10 | no | talk\n2. Setup check | 10 | no | check\n3. Exercise 1 - deploy a pod | 40 | yes | exercise\n4. Break | 10 | no | break\n5. Exercise 2 - services and ingress | 50 | no | exercise\n6. Exercise 3 - scaling | 45 | no | exercise\n7. Wrap-up | 15 | no | talk\nAgenda total: 180 of 180 minutes",
 "facts": "Hands-on: the page's pick is full; rungs No live hands-on available; Demonstration only available; Full hands-on default\nCoverage: the page's pick is roaming; rungs Solo instructor deleted; Structured peer pairing available; Roaming troubleshooter default; Stationed helpers per work area not yet; capable helpers 2, logistics-only 2; the convention asks for 4-5 capable helpers (one instructor - the reach is self-set)\nCapacity: Room ceiling 36; Coverage ceiling 30; Exercise throughput ceiling n/a; capacity 30, bound by coverage; power strips needed 2\nPrerequisites: the page's pick is published; rungs Nothing published deleted; Published prerequisites default; Provisioned environment only not yet; Both paths offered available\nNetwork: the page's pick is clear (removing the live dependency is promoted, but the exercise's dependency cannot be removed); rungs Assume the network holds deleted; Declare the dependency with a fallback default; Clear the room's network in writing promoted; Remove the live dependency promoted\nChecks (1 of 6): Coverage (Capable helpers meet the 1-per-8-10 convention, logistics volunteers not counted) MISSING; Capacity (Registrations sit inside the lowest of the three ceilings, and the binding one is named) MISSING; Prerequisites (Prerequisites cover knowledge, machine state and accounts, with a check participants run before the day whenever something must be installed or signed into) MISSING; Network (The venue's answer about this room's network is in writing) MISSING; Setup block (A machine check of at least 20 minutes sits inside the booked length) MISSING; Afterwards (The material has a home afterwards and a published access window) passed\nSignals to record: Ready at minute zero: the share of the room that finished the prerequisites before arriving (self-set); Confidence before and after: an \"I am confident in my ability to...\" rating for the skill taught (the Carpentries' convention - borrow the convention, not their figure); Help latency: how long a help flag stays up (self-set target)\nFindings (18):\n[fix] over_capacity (capacity): 40 registrations for a capacity of 30 (bound by the coverage ceiling) - cap the seats at 30 and keep a waitlist.\n[fix] under_covered (coverage): 2 capable helpers for 40 registrations - the Carpentries convention (two-day research-computing workshops, two instructors, helpers who know the tools) asks for 4-5.\n[fix] no_check_block (length): The machine check is 10 minutes - open with at least 20 minutes of checking machines even when prerequisites went out; prerequisites shrink that block, they never remove it.\n[fix] accounts_missing (prerequisites): The exercise needs an account, and no account is on the sheet - signup, email confirmation and employer SSO all land at minute zero, on the room's network, for everyone at once.\n[fix] verbal (network): The venue's answer is a verbal \"it's fine\" - get sustained bandwidth, the device count and the blocked protocols or device classes in writing; policy breaks sessions more often than bandwidth.\n[check] logistics (coverage): Marco, Lena know the logistics, not the material - they satisfy the arithmetic and supply no coverage; do not count them.\n[check] one_instructor (coverage): One instructor: the 1-per-8-10 convention assumes two - counting the instructor as one helper's reach during exercises is a self-set adjustment; say so.\n[check] power (room): Power at 24 of 30 seats - one power strip for every 3 learners means 2 more strips.\n[check] no_precheck (prerequisites): No check participants run before the day - ship one that confirms tools, versions, operating system, chip architecture and sign-ins.\n[check] prior (network): A prior edition's room network failed (bandwidth failed) - removing the live dependency is promoted.\n[check] checkpoints (room): No checkpoint for: Exercise 2 - services and ingress, Exercise 3 - scaling - a tagged branch or solutions folder per step lets a stuck participant rejoin at the next one.\n[check] typing (room): Brief helpers that the participant does the typing - a helper who takes the keyboard fixes the laptop and teaches nothing.\n[check] checks (measurement): Delivery checks: 1 of 6 (all self-set).\n[info] peer (coverage): Structured peer pairing (driver and navigator, swapped every 5-10 minutes) grows with the room - add it on top; plain role-free pairing loses focus.\n[info] account_persist (compliance): An account a participant creates because you told them to persists after the workshop, and you cannot delete it for them.\n[info] during (network): Participants download, install or sign in during the session: a whole room doing it at once is a load case - ask for pre-downloads before the day and carry an offline kit (USB sticks with the files and installers, a hub).\n[info] shared_exit (network): 40 laptops behind one venue address hit a registry's anonymous pull limit or an API key's quota together - plan for it.\n[info] stickies (room): Hand out two-colour sticky notes (blue and yellow, not red and green): one means \"I need help\", the other \"done\"."
}

Reply:

{
 "task": "sheet",
 "summary": "With 40 registrations against a capacity of 30 bound by coverage, cap the seats at 30 and keep a waitlist.",
 "hands": {
  "pick": "full",
  "reason": "The skill cannot be learned by reading, and the venue has not refused in writing despite the network dependency it cannot remove, so full hands-on remains the default."
 },
 "capacity": {
  "number": 30,
  "bound": [
   "coverage"
  ],
  "note": "40 registrations exceed the capacity of 30, so cap the seats at 30 and keep a waitlist."
 },
 "coverage": {
  "pick": "roaming",
  "needed": "4-5",
  "basis": "The Carpentries convention of one helper per 8 to 10 learners, drawn from two-day research-computing workshops and not counting the two instructors, sets the 4-5 figure for capable helpers here.",
  "adjustment": "With one instructor instead of the convention's two, counting the instructor as one helper's reach during exercises is a self-set adjustment."
 },
 "prereqs": {
  "pick": "published",
  "knowledge": [
   "Comfortable in a terminal"
  ],
  "machine": [
   "Docker Desktop 4.x running",
   "kubectl 1.30 on the path"
  ],
  "accounts": [
   "to be named"
  ],
  "note": "The exercise needs an account that is missing from the sheet, and no pre-day check exists to confirm readiness once one is named."
 },
 "network": {
  "pick": "clear",
  "venue": "The venue answered only verbally that it's fine, with nothing in writing.",
  "note": "Get the venue's sustained bandwidth, device count and any blocked protocols or device classes in writing, since an unclear verbal answer causes more session failures than bandwidth shortfalls do."
 },
 "agenda": [
  {
   "block": "Welcome",
   "minutes": 10,
   "note": "Opening talk, no checkpoint needed."
  },
  {
   "block": "Setup check",
   "minutes": 10,
   "note": "At 10 minutes this falls short of the 20-minute minimum machine check the rules call for."
  },
  {
   "block": "Exercise 1 - deploy a pod",
   "minutes": 40,
   "note": "The only exercise in this agenda carrying a checkpoint."
  },
  {
   "block": "Break",
   "minutes": 10,
   "note": "A break inside the long block, as the rules call for."
  },
  {
   "block": "Exercise 2 - services and ingress",
   "minutes": 50,
   "note": "No checkpoint, though the rules call for a checkpoint per exercise."
  },
  {
   "block": "Exercise 3 - scaling",
   "minutes": 45,
   "note": "No checkpoint, though the rules call for a checkpoint per exercise."
  },
  {
   "block": "Wrap-up",
   "minutes": 15,
   "note": "Closing talk, no checkpoint needed."
  }
 ],
 "materials": {
  "window": "1 month",
  "note": "Where the material lives afterwards is to be named, though a follow-up channel is in place for questions."
 },
 "triggers": [
  {
   "choice": "capacity",
   "trigger": "If the helper roster grows to the convention's 4-5 capable helpers, the capacity ceiling could rise toward the room's 36-seat limit next edition."
  },
  {
   "choice": "coverage",
   "trigger": "If more capable helpers who know the material join the room and meet the convention's 4-5 figure, revisit the roaming troubleshooter sizing next edition."
  },
  {
   "choice": "network",
   "trigger": "If the venue provides a written, sustained-bandwidth answer, the network pick could move back toward declaring the dependency with a fallback next edition."
  },
  {
   "choice": "prereqs",
   "trigger": "If a named account and a pre-day check are added to the sheet, the prerequisites finding would be resolved next edition."
  }
 ],
 "checks": [
  {
   "check": "Coverage",
   "pass": false
  },
  {
   "check": "Capacity",
   "pass": false
  },
  {
   "check": "Prerequisites",
   "pass": false
  },
  {
   "check": "Network",
   "pass": false
  },
  {
   "check": "Setup block",
   "pass": false
  },
  {
   "check": "Afterwards",
   "pass": true
  }
 ],
 "signals": [
  "Ready at minute zero: the share who finished prerequisites before arriving - a low share next edition would push for a stronger pre-day check.",
  "Confidence before and after: an 'I am confident in my ability to...' rating for the skill taught, borrowing the Carpentries' convention - a weak gain would call for more hands-on time.",
  "Help latency: how long a help flag stays up - a long latency next edition would call for more capable helpers."
 ],
 "caveats": [
  "40 registrations exceed the capacity of 30, bound by coverage - cap seats at 30 and keep a waitlist.",
  "2 capable helpers for 40 registrations falls short of the Carpentries convention's 4-5.",
  "The 10-minute machine check is short of the 20-minute minimum the rules call for.",
  "The exercise needs an account that is not yet on the sheet."
 ]
}

The page's check: kept - nothing to flag

Kubernetes from zero (a 3-hour conference lab) - preflight

180 minutes, 40 registrations; capacity 30, bound by coverage; roaming troubleshooter; published prerequisites; clear the room's network in writing; 1 of 6 checks.

Input:

{
 "task": "preflight",
 "session": "Workshop: Kubernetes from zero at Quillmoor Ops Days; booked length 180 minutes; 40 registrations; ticketed; a curriculum run every edition\nRoom: 36 seats; power at 24 seats; 1 instructor\nExercise: the skill can be acquired by reading no; installs on a participant's machine yes; accounts to sign up for yes; a live network service while it runs yes (the dependency can be removed no); participants download, install or sign in during the session yes; distinct workstations no\nMachines: every participant brings a capable machine they may install on yes; employer-managed laptops no; the organizer accepts a platform's terms and issues credentials no; minors present no\nVenue network: said \"it's fine\", nothing written; unusual protocol, port or device class needed no; prior edition: bandwidth failed\nPractice: pre-day check no; dry run on a fresh machine yes; two-colour sticky notes no; helpers briefed that participants type no; follow-up channel yes; material access window 1 month",
 "room": "Helpers (name | knows the material):\n  Ines | yes\n  Marco | no - logistics only\n  Lena | no - logistics only\n  Tom | yes\nPrerequisites as entered, by class:\n  knowledge: Comfortable in a terminal\n  machine: Docker Desktop 4.x running; kubectl 1.30 on the path\n  account: none - MISSING, the exercise needs one\nAgenda, in order (block | minutes | checkpoint | kind):\n1. Welcome | 10 | no | talk\n2. Setup check | 10 | no | check\n3. Exercise 1 - deploy a pod | 40 | yes | exercise\n4. Break | 10 | no | break\n5. Exercise 2 - services and ingress | 50 | no | exercise\n6. Exercise 3 - scaling | 45 | no | exercise\n7. Wrap-up | 15 | no | talk\nAgenda total: 180 of 180 minutes",
 "facts": "Hands-on: the page's pick is full; rungs No live hands-on available; Demonstration only available; Full hands-on default\nCoverage: the page's pick is roaming; rungs Solo instructor deleted; Structured peer pairing available; Roaming troubleshooter default; Stationed helpers per work area not yet; capable helpers 2, logistics-only 2; the convention asks for 4-5 capable helpers (one instructor - the reach is self-set)\nCapacity: Room ceiling 36; Coverage ceiling 30; Exercise throughput ceiling n/a; capacity 30, bound by coverage; power strips needed 2\nPrerequisites: the page's pick is published; rungs Nothing published deleted; Published prerequisites default; Provisioned environment only not yet; Both paths offered available\nNetwork: the page's pick is clear (removing the live dependency is promoted, but the exercise's dependency cannot be removed); rungs Assume the network holds deleted; Declare the dependency with a fallback default; Clear the room's network in writing promoted; Remove the live dependency promoted\nChecks (1 of 6): Coverage (Capable helpers meet the 1-per-8-10 convention, logistics volunteers not counted) MISSING; Capacity (Registrations sit inside the lowest of the three ceilings, and the binding one is named) MISSING; Prerequisites (Prerequisites cover knowledge, machine state and accounts, with a check participants run before the day whenever something must be installed or signed into) MISSING; Network (The venue's answer about this room's network is in writing) MISSING; Setup block (A machine check of at least 20 minutes sits inside the booked length) MISSING; Afterwards (The material has a home afterwards and a published access window) passed\nSignals to record: Ready at minute zero: the share of the room that finished the prerequisites before arriving (self-set); Confidence before and after: an \"I am confident in my ability to...\" rating for the skill taught (the Carpentries' convention - borrow the convention, not their figure); Help latency: how long a help flag stays up (self-set target)\nFindings (18):\n[fix] over_capacity (capacity): 40 registrations for a capacity of 30 (bound by the coverage ceiling) - cap the seats at 30 and keep a waitlist.\n[fix] under_covered (coverage): 2 capable helpers for 40 registrations - the Carpentries convention (two-day research-computing workshops, two instructors, helpers who know the tools) asks for 4-5.\n[fix] no_check_block (length): The machine check is 10 minutes - open with at least 20 minutes of checking machines even when prerequisites went out; prerequisites shrink that block, they never remove it.\n[fix] accounts_missing (prerequisites): The exercise needs an account, and no account is on the sheet - signup, email confirmation and employer SSO all land at minute zero, on the room's network, for everyone at once.\n[fix] verbal (network): The venue's answer is a verbal \"it's fine\" - get sustained bandwidth, the device count and the blocked protocols or device classes in writing; policy breaks sessions more often than bandwidth.\n[check] logistics (coverage): Marco, Lena know the logistics, not the material - they satisfy the arithmetic and supply no coverage; do not count them.\n[check] one_instructor (coverage): One instructor: the 1-per-8-10 convention assumes two - counting the instructor as one helper's reach during exercises is a self-set adjustment; say so.\n[check] power (room): Power at 24 of 30 seats - one power strip for every 3 learners means 2 more strips.\n[check] no_precheck (prerequisites): No check participants run before the day - ship one that confirms tools, versions, operating system, chip architecture and sign-ins.\n[check] prior (network): A prior edition's room network failed (bandwidth failed) - removing the live dependency is promoted.\n[check] checkpoints (room): No checkpoint for: Exercise 2 - services and ingress, Exercise 3 - scaling - a tagged branch or solutions folder per step lets a stuck participant rejoin at the next one.\n[check] typing (room): Brief helpers that the participant does the typing - a helper who takes the keyboard fixes the laptop and teaches nothing.\n[check] checks (measurement): Delivery checks: 1 of 6 (all self-set).\n[info] peer (coverage): Structured peer pairing (driver and navigator, swapped every 5-10 minutes) grows with the room - add it on top; plain role-free pairing loses focus.\n[info] account_persist (compliance): An account a participant creates because you told them to persists after the workshop, and you cannot delete it for them.\n[info] during (network): Participants download, install or sign in during the session: a whole room doing it at once is a load case - ask for pre-downloads before the day and carry an offline kit (USB sticks with the files and installers, a hub).\n[info] shared_exit (network): 40 laptops behind one venue address hit a registry's anonymous pull limit or an API key's quota together - plan for it.\n[info] stickies (room): Hand out two-colour sticky notes (blue and yellow, not red and green): one means \"I need help\", the other \"done\"."
}

Reply:

{
 "task": "preflight",
 "title": "Kubernetes from zero",
 "intro": "Kubernetes from zero is a 180 minute hands-on workshop at Quillmoor Ops Days, and the setup check starts on time, so please be ready to begin as soon as it opens.",
 "knowledge": [
  "Be comfortable in a terminal."
 ],
 "machine": [
  "Have Docker Desktop 4.x installed and running.",
  "Have kubectl 1.30 installed and on your path."
 ],
 "accounts": [],
 "check_steps": [
  "Open a terminal and make sure you're comfortable running commands in it.",
  "Install Docker Desktop 4.x and confirm it starts and stays running.",
  "Install kubectl 1.30 and confirm it's on your path by checking its version.",
  "Complete any sign-ups, downloads or installs before the day, since the session itself will not have time for them."
 ],
 "network": "This workshop needs an internet connection, and the organizers are confirming the room's network with the venue. Please do any sign-ups, downloads or installs before the day, since the exercises call for them during the session.",
 "bring": [
  "A charged laptop you can install software on.",
  "Your laptop charger."
 ],
 "after": "Questions after the workshop go to a follow-up channel, to be named, and the material stays available for 1 month.",
 "note": "Confirm the account the exercise needs and get the venue's network answer in writing before sending this note to participants."
}

The page's check: kept - nothing to flag

Borrow checker puzzles (a free meetup session) - sheet

90 minutes, 12 registrations; capacity 20, bound by room; roaming troubleshooter; published prerequisites; declare the dependency with a fallback; 6 of 6 checks.

Input:

{
 "task": "sheet",
 "session": "Workshop: Borrow checker puzzles at Tarnwick Rustaceans; booked length 90 minutes; 12 registrations; free; measured no-show share last edition 40%; a topic run once, not repeated each edition\nRoom: 20 seats; power at 20 seats; 1 instructor\nExercise: the skill can be acquired by reading no; installs on a participant's machine no; accounts to sign up for no; a live network service while it runs yes (the dependency can be removed yes); participants download, install or sign in during the session no; distinct workstations no\nMachines: every participant brings a capable machine they may install on yes; employer-managed laptops no; the organizer accepts a platform's terms and issues credentials no; minors present no\nVenue network: answered in writing; unusual protocol, port or device class needed no; prior edition: no prior failure\nPractice: pre-day check no; dry run on a fresh machine yes; two-colour sticky notes yes; helpers briefed that participants type yes; follow-up channel yes; material access window 72 hours",
 "room": "Helpers (name | knows the material):\n  Sara | yes\n  Joao | yes\nPrerequisites as entered, by class:\n  knowledge: Read the first four chapters of the Rust book\n  machine: none\n  account: none\nAgenda, in order (block | minutes | checkpoint | kind):\n1. Welcome and icebreaker | 10 | no | talk\n2. Machine check | 20 | no | check\n3. Borrow checker puzzles | 45 | yes | exercise\n4. Q&A | 15 | no | talk\nAgenda total: 90 of 90 minutes",
 "facts": "Hands-on: the page's pick is full; rungs No live hands-on available; Demonstration only available; Full hands-on default\nCoverage: the page's pick is roaming; rungs Solo instructor deleted; Structured peer pairing available; Roaming troubleshooter default; Stationed helpers per work area not yet; capable helpers 2, logistics-only 0; the convention asks for 2 capable helpers (one instructor - the reach is self-set)\nCapacity: Room ceiling 20; Coverage ceiling 30; Exercise throughput ceiling n/a; capacity 20, bound by room; seats stay at 20, but with the measured no-show share up to 33 registrations may be accepted\nPrerequisites: the page's pick is published; rungs Nothing published available; Published prerequisites default; Provisioned environment only not yet; Both paths offered available\nNetwork: the page's pick is declare; rungs Assume the network holds available; Declare the dependency with a fallback default; Clear the room's network in writing available; Remove the live dependency not yet\nChecks (6 of 6): Coverage (Capable helpers meet the 1-per-8-10 convention, logistics volunteers not counted) passed; Capacity (Registrations sit inside the lowest of the three ceilings, and the binding one is named) passed; Prerequisites (Prerequisites cover knowledge, machine state and accounts, with a check participants run before the day whenever something must be installed or signed into) passed; Network (The venue's answer about this room's network is in writing) passed; Setup block (A machine check of at least 20 minutes sits inside the booked length) passed; Afterwards (The material has a home afterwards and a published access window) passed\nSignals to record: Ready at minute zero: the share of the room that finished the prerequisites before arriving (self-set); Confidence before and after: an \"I am confident in my ability to...\" rating for the skill taught (the Carpentries' convention - borrow the convention, not their figure); Started versus finished: how many reached the last exercise, counted by done flags (self-set target)\nFindings (5):\n[check] one_instructor (coverage): One instructor: the 1-per-8-10 convention assumes two - counting the instructor as one helper's reach during exercises is a self-set adjustment; say so.\n[info] peer (coverage): Structured peer pairing (driver and navigator, swapped every 5-10 minutes) grows with the room - add it on top; plain role-free pairing loses focus.\n[info] overbook (capacity): Free session: with last edition's measured no-show share of 40%, accept up to 33 registrations, keep a waitlist and release unclaimed seats at the start.\n[info] fallback (network): Declaring the dependency with a participant-side fallback (their own data) moves the cost to participants, and roaming data excludes some international attendees - say so where you publish it.\n[info] checks (measurement): Delivery checks: 6 of 6 (all self-set)."
}

Reply:

{
 "task": "sheet",
 "summary": "This room has only one instructor against the 1-per-8-10 convention's two, so the first change is to state that counting the instructor as a helper's reach during exercises is a self-set adjustment.",
 "hands": {
  "pick": "full",
  "reason": "The skill cannot be acquired by reading, and although the exercise depends on a live network service, that dependency can be removed, so full hands-on remains the pick."
 },
 "capacity": {
  "number": 20,
  "bound": [
   "room"
  ],
  "note": "Seats stay at 20, but last edition's measured 40% no-show share lets the free session accept registrations up to 33 while keeping a waitlist and releasing unclaimed seats at the start."
 },
 "coverage": {
  "pick": "roaming",
  "needed": "2",
  "basis": "The Carpentries' convention of 1 helper per 8-10 learners, drawn from two-day research-computing workshops and not counting two instructors, works out to 2 capable helpers here, counting only those who can debug the material.",
  "adjustment": "This room has one instructor rather than the convention's two, so counting the instructor's reach as one helper during exercises is a self-set adjustment."
 },
 "prereqs": {
  "pick": "published",
  "knowledge": [
   "Read the first four chapters of the Rust book"
  ],
  "machine": [],
  "accounts": [],
  "note": "Nothing needs to be installed or signed into, so only the knowledge prerequisite applies and the prerequisites check passes without a pre-day check in place."
 },
 "network": {
  "pick": "declare",
  "venue": "The venue has answered in writing that this room needs no unusual protocol, port or device class, and there was no prior failure last edition.",
  "note": "Declaring the live network dependency with a participant-side fallback of their own data moves that cost to participants and excludes some international attendees, so say so where this is published."
 },
 "agenda": [
  {
   "block": "Welcome and icebreaker",
   "minutes": 10,
   "note": "This talk block opens the session with no checkpoint needed."
  },
  {
   "block": "Machine check",
   "minutes": 20,
   "note": "This 20-minute check satisfies the setup block requirement within the booked length."
  },
  {
   "block": "Borrow checker puzzles",
   "minutes": 45,
   "note": "The workshop's one exercise block carries the required checkpoint."
  },
  {
   "block": "Q&A",
   "minutes": 15,
   "note": "This closing talk block has no checkpoint."
  }
 ],
 "materials": {
  "window": "72 hours",
  "note": "Where the material lives afterward is to be named, though the 72-hour access window and the follow-up channel are already set."
 },
 "triggers": [
  {
   "choice": "hands",
   "trigger": "If a future edition's exercise needs a live network service that cannot be removed and the venue will not answer in writing, full hands-on would be deleted down to a demonstration."
  },
  {
   "choice": "coverage",
   "trigger": "If a second instructor or another capable helper joins next edition, the one-instructor self-set adjustment could be dropped and coverage counted against the full two-instructor convention."
  },
  {
   "choice": "capacity",
   "trigger": "If a future edition's measured no-show share lands well under 40%, the registrations accepted beyond 20 should be pulled back toward the room ceiling."
  },
  {
   "choice": "network",
   "trigger": "If the venue reports a new failure on this network dependency, the pick should move from declare to remove, with pre-downloads and an offline kit in place."
  }
 ],
 "checks": [
  {
   "check": "Coverage",
   "pass": true
  },
  {
   "check": "Capacity",
   "pass": true
  },
  {
   "check": "Prerequisites",
   "pass": true
  },
  {
   "check": "Network",
   "pass": true
  },
  {
   "check": "Setup block",
   "pass": true
  },
  {
   "check": "Afterwards",
   "pass": true
  }
 ],
 "signals": [
  "Ready at minute zero: a low share finishing prerequisites before arriving would call for a clearer pre-day check next edition.",
  "Confidence before and after: little change in the Carpentries-style rating would call for revisiting how the exercise is taught next edition.",
  "Started versus finished: a low share reaching the last exercise would call for trimming the earlier talk blocks next edition."
 ],
 "caveats": [
  "One instructor: the 1-per-8-10 convention assumes two, so counting the instructor as a helper's reach during exercises is a self-set adjustment."
 ]
}

The page's check: kept - nothing to flag

Borrow checker puzzles (a free meetup session) - preflight

90 minutes, 12 registrations; capacity 20, bound by room; roaming troubleshooter; published prerequisites; declare the dependency with a fallback; 6 of 6 checks.

Input:

{
 "task": "preflight",
 "session": "Workshop: Borrow checker puzzles at Tarnwick Rustaceans; booked length 90 minutes; 12 registrations; free; measured no-show share last edition 40%; a topic run once, not repeated each edition\nRoom: 20 seats; power at 20 seats; 1 instructor\nExercise: the skill can be acquired by reading no; installs on a participant's machine no; accounts to sign up for no; a live network service while it runs yes (the dependency can be removed yes); participants download, install or sign in during the session no; distinct workstations no\nMachines: every participant brings a capable machine they may install on yes; employer-managed laptops no; the organizer accepts a platform's terms and issues credentials no; minors present no\nVenue network: answered in writing; unusual protocol, port or device class needed no; prior edition: no prior failure\nPractice: pre-day check no; dry run on a fresh machine yes; two-colour sticky notes yes; helpers briefed that participants type yes; follow-up channel yes; material access window 72 hours",
 "room": "Helpers (name | knows the material):\n  Sara | yes\n  Joao | yes\nPrerequisites as entered, by class:\n  knowledge: Read the first four chapters of the Rust book\n  machine: none\n  account: none\nAgenda, in order (block | minutes | checkpoint | kind):\n1. Welcome and icebreaker | 10 | no | talk\n2. Machine check | 20 | no | check\n3. Borrow checker puzzles | 45 | yes | exercise\n4. Q&A | 15 | no | talk\nAgenda total: 90 of 90 minutes",
 "facts": "Hands-on: the page's pick is full; rungs No live hands-on available; Demonstration only available; Full hands-on default\nCoverage: the page's pick is roaming; rungs Solo instructor deleted; Structured peer pairing available; Roaming troubleshooter default; Stationed helpers per work area not yet; capable helpers 2, logistics-only 0; the convention asks for 2 capable helpers (one instructor - the reach is self-set)\nCapacity: Room ceiling 20; Coverage ceiling 30; Exercise throughput ceiling n/a; capacity 20, bound by room; seats stay at 20, but with the measured no-show share up to 33 registrations may be accepted\nPrerequisites: the page's pick is published; rungs Nothing published available; Published prerequisites default; Provisioned environment only not yet; Both paths offered available\nNetwork: the page's pick is declare; rungs Assume the network holds available; Declare the dependency with a fallback default; Clear the room's network in writing available; Remove the live dependency not yet\nChecks (6 of 6): Coverage (Capable helpers meet the 1-per-8-10 convention, logistics volunteers not counted) passed; Capacity (Registrations sit inside the lowest of the three ceilings, and the binding one is named) passed; Prerequisites (Prerequisites cover knowledge, machine state and accounts, with a check participants run before the day whenever something must be installed or signed into) passed; Network (The venue's answer about this room's network is in writing) passed; Setup block (A machine check of at least 20 minutes sits inside the booked length) passed; Afterwards (The material has a home afterwards and a published access window) passed\nSignals to record: Ready at minute zero: the share of the room that finished the prerequisites before arriving (self-set); Confidence before and after: an \"I am confident in my ability to...\" rating for the skill taught (the Carpentries' convention - borrow the convention, not their figure); Started versus finished: how many reached the last exercise, counted by done flags (self-set target)\nFindings (5):\n[check] one_instructor (coverage): One instructor: the 1-per-8-10 convention assumes two - counting the instructor as one helper's reach during exercises is a self-set adjustment; say so.\n[info] peer (coverage): Structured peer pairing (driver and navigator, swapped every 5-10 minutes) grows with the room - add it on top; plain role-free pairing loses focus.\n[info] overbook (capacity): Free session: with last edition's measured no-show share of 40%, accept up to 33 registrations, keep a waitlist and release unclaimed seats at the start.\n[info] fallback (network): Declaring the dependency with a participant-side fallback (their own data) moves the cost to participants, and roaming data excludes some international attendees - say so where you publish it.\n[info] checks (measurement): Delivery checks: 6 of 6 (all self-set)."
}

Reply:

{
 "task": "preflight",
 "title": "Before Borrow Checker Puzzles at Tarnwick Rustaceans",
 "intro": "Borrow Checker Puzzles at Tarnwick Rustaceans is a 90-minute, hands-on workshop. The machine check starts right on time, so please arrive ready.",
 "knowledge": [
  "Read the first four chapters of the Rust book before the day."
 ],
 "machine": [],
 "accounts": [],
 "check_steps": [
  "Read the first four chapters of the Rust book.",
  "Make sure you have a way to get online during the workshop, such as mobile data, in case the venue network has trouble.",
  "Plan to arrive in time for the 20-minute machine check at the start of the session."
 ],
 "network": "This workshop needs an internet connection for its live exercise. If the room's network has any trouble, please be ready to use your own mobile data as a fallback.",
 "bring": [
  "A charged laptop you can install software on.",
  "Your laptop charger.",
  "A mobile data plan or hotspot as a backup in case the venue network has trouble."
 ],
 "after": "Questions after the workshop go to the follow-up channel, and the material stays available for 72 hours.",
 "note": "Settle and share the specific follow-up channel link before sending, since the page only confirms one exists without naming it."
}

The page's check: kept - nothing to flag

Sensors to the cloud (a hardware lab with a student track) - sheet

150 minutes, 30 registrations; capacity 12, bound by throughput; stationed helpers per work area; provisioned environment only; remove the live dependency; 3 of 6 checks.

Input:

{
 "task": "sheet",
 "session": "Workshop: Sensors to the cloud at Tarnwick College Hack Week; booked length 150 minutes; 30 registrations; free; a curriculum run every edition\nRoom: 40 seats; power at 40 seats; 2 instructors; limited kit or logins: 12 sensor boards\nExercise: the skill can be acquired by reading no; installs on a participant's machine no; accounts to sign up for yes; a live network service while it runs yes (the dependency can be removed yes); participants download, install or sign in during the session yes; distinct workstations yes\nMachines: every participant brings a capable machine they may install on no; employer-managed laptops no; the organizer accepts a platform's terms and issues credentials yes; minors present yes\nVenue network: refuses to answer; unusual protocol, port or device class needed yes; prior edition: a blocked device class\nPractice: pre-day check yes; dry run on a fresh machine yes; two-colour sticky notes yes; helpers briefed that participants type yes; follow-up channel no; material access window NOT SET",
 "room": "Helpers (name | knows the material):\n  Ava | yes\n  Ben | yes\n  Kai | yes\n  Liv | no - logistics only\nPrerequisites as entered, by class:\n  knowledge: Basic Python\n  machine: none\n  account: Classroom login issued by the organizers\nAgenda, in order (block | minutes | checkpoint | kind):\n1. Machine and board check | 25 | no | check\n2. Wire the sensor | 40 | yes | exercise\n3. Break | 15 | no | break\n4. Publish to the broker | 50 | yes | exercise\n5. Wrap-up | 20 | no | talk\nAgenda total: 150 of 150 minutes",
 "facts": "Hands-on: the page's pick is full; rungs No live hands-on available; Demonstration only available; Full hands-on default\nCoverage: the page's pick is stationed; rungs Solo instructor deleted; Structured peer pairing available; Roaming troubleshooter default; Stationed helpers per work area promoted; capable helpers 3, logistics-only 1; the convention asks for 3-4 capable helpers\nCapacity: Room ceiling 40; Coverage ceiling 30; Exercise throughput ceiling 12; capacity 12, bound by throughput\nPrerequisites: the page's pick is provisioned; rungs Nothing published deleted; Published prerequisites default; Provisioned environment only promoted; Both paths offered available\nNetwork: the page's pick is remove; rungs Assume the network holds deleted; Declare the dependency with a fallback default; Clear the room's network in writing promoted; Remove the live dependency promoted\nChecks (3 of 6): Coverage (Capable helpers meet the 1-per-8-10 convention, logistics volunteers not counted) passed; Capacity (Registrations sit inside the lowest of the three ceilings, and the binding one is named) MISSING; Prerequisites (Prerequisites cover knowledge, machine state and accounts, with a check participants run before the day whenever something must be installed or signed into) passed; Network (The venue's answer about this room's network is in writing) MISSING; Setup block (A machine check of at least 20 minutes sits inside the booked length) passed; Afterwards (The material has a home afterwards and a published access window) MISSING\nSignals to record: Ready at minute zero: the share of the room that finished the prerequisites before arriving (self-set); Confidence before and after: an \"I am confident in my ability to...\" rating for the skill taught (the Carpentries' convention - borrow the convention, not their figure); Started versus finished: how many reached the last exercise, counted by done flags (self-set target)\nFindings (16):\n[fix] over_capacity (capacity): 30 registrations for a capacity of 12 (bound by the throughput ceiling) - cap the seats at 12 and keep a waitlist.\n[fix] minors (compliance): Minors in the room: terms are accepted and accounts created for someone who cannot consent - run the participant-data consent review before the day.\n[check] logistics (coverage): Liv knows the logistics, not the material - they satisfy the arithmetic and supply no coverage; do not count them.\n[check] no_noshow (capacity): Free session with no measured no-show share - keep a waitlist and release unclaimed seats at the start; never overbook on a borrowed share.\n[check] compliance (compliance): You accept a platform's terms for the room and issue credentials - review the platform's third-party terms and your own credential data posture; an environment you built is torn down on your schedule.\n[check] venue_refused (network): The venue refuses to answer in writing - remove the live dependency from the exercise.\n[check] protocol (network): The exercise needs an unusual protocol, port or device class - name it in the written question to the venue.\n[check] prior (network): A prior edition's room network failed (a blocked device class) - removing the live dependency is promoted.\n[check] channel (afterwards): No follow-up channel - give questions somewhere to go after the session ends.\n[check] window (afterwards): No access window for the material - publish how long it stays available.\n[check] checks (measurement): Delivery checks: 3 of 6 (all self-set).\n[info] stationed (coverage): Distinct workstations: post a helper at each - one helper at a station covers everyone who reaches it.\n[info] throughput (capacity): The exercise throughput binds: 12 sensor boards - the ceiling most often missed, invisible until the next person needs one.\n[info] provisioned (prerequisites): Not every participant can bring a capable machine they may install on - a provisioned environment is promoted; it trades the install failure for total dependence on the room's connection.\n[info] during (network): Participants download, install or sign in during the session: a whole room doing it at once is a load case - ask for pre-downloads before the day and carry an offline kit (USB sticks with the files and installers, a hub).\n[info] shared_exit (network): 30 laptops behind one venue address hit a registry's anonymous pull limit or an API key's quota together - plan for it."
}

Reply:

{
 "task": "sheet",
 "summary": "With 30 registrations against a capacity of 12 bound by exercise throughput (12 sensor boards), cap the seats at 12 and keep a waitlist.",
 "hands": {
  "pick": "full",
  "reason": "The skill cannot be learned by reading, and although the venue refuses to answer in writing, the exercise's network dependency can be removed, so full hands-on remains the default rather than being deleted."
 },
 "capacity": {
  "number": 12,
  "bound": [
   "throughput"
  ],
  "note": "Cap registrations at 12, the throughput ceiling bound by the 12 sensor boards, and keep a waitlist without overbooking since there is no measured no-show share."
 },
 "coverage": {
  "pick": "stationed",
  "needed": "3-4",
  "basis": "The Carpentries convention of one helper per 8 to 10 learners, drawn from two-day research-computing workshops and not counting the two instructors, sets the 3-4 figure for capable helpers here.",
  "adjustment": "With two instructors already matching the convention's assumption, this room needs no instructor-reach adjustment; stationing each of the 3 capable helpers at a distinct work area is a self-set translation of the coverage pick into this layout."
 },
 "prereqs": {
  "pick": "provisioned",
  "knowledge": [
   "Basic Python"
  ],
  "machine": [],
  "accounts": [
   "Classroom login issued by the organizers"
  ],
  "note": "The classroom login is issued by the organizers for this provisioned environment, and with minors present, a participant-data consent review is needed before the day."
 },
 "network": {
  "pick": "remove",
  "venue": "The venue refuses to answer in writing.",
  "note": "With the live dependency removed after the venue's refusal and a prior blocked device class, carry pre-downloads and an offline kit, including USB sticks with the files, installers and a hub."
 },
 "agenda": [
  {
   "block": "Machine and board check",
   "minutes": 25,
   "note": "At 25 minutes this exceeds the rules' 20-minute minimum machine check."
  },
  {
   "block": "Wire the sensor",
   "minutes": 40,
   "note": "Carries a checkpoint, as the rules call for a checkpoint per exercise."
  },
  {
   "block": "Break",
   "minutes": 15,
   "note": "A break inside the long block, as the rules call for."
  },
  {
   "block": "Publish to the broker",
   "minutes": 50,
   "note": "Carries a checkpoint, as the rules call for a checkpoint per exercise."
  },
  {
   "block": "Wrap-up",
   "minutes": 20,
   "note": "Closing talk, no checkpoint needed."
  }
 ],
 "materials": {
  "window": "to be named",
  "note": "Where the material lives afterwards is also to be named, and with no follow-up channel in place, questions currently have nowhere to go after the session ends."
 },
 "triggers": [
  {
   "choice": "capacity",
   "trigger": "If more sensor boards become available for a future edition, raise the throughput ceiling and the capacity above 12."
  },
  {
   "choice": "coverage",
   "trigger": "If a future edition runs with fewer instructors than planned, revisit the stationed coverage sizing against the convention's assumption of two instructors."
  },
  {
   "choice": "network",
   "trigger": "If the venue later answers in writing and allows the protocol, revisit moving off removing the live dependency."
  },
  {
   "choice": "materials",
   "trigger": "If the published access window goes unused once it is finally set, shorten it next edition."
  }
 ],
 "checks": [
  {
   "check": "Coverage",
   "pass": true
  },
  {
   "check": "Capacity",
   "pass": false
  },
  {
   "check": "Prerequisites",
   "pass": true
  },
  {
   "check": "Network",
   "pass": false
  },
  {
   "check": "Setup block",
   "pass": true
  },
  {
   "check": "Afterwards",
   "pass": false
  }
 ],
 "signals": [
  "Ready at minute zero: the share who finished prerequisites before arriving - a low share next edition would push for a stronger pre-day check.",
  "Confidence before and after: an 'I am confident in my ability to...' rating for the skill taught, borrowing the Carpentries' convention - a weak gain would call for more hands-on time.",
  "Started versus finished: how many reached the last exercise, counted by done flags - a low finish rate next edition would call for more sensor boards or a shorter exercise."
 ],
 "caveats": [
  "30 registrations exceed the capacity of 12, bound by exercise throughput - cap seats at 12 and keep a waitlist.",
  "Minors in the room: terms are accepted and accounts created for someone who cannot consent - run a participant-data consent review before the day.",
  "Liv knows the logistics, not the material, and should not be counted toward coverage.",
  "No measured no-show share for this free session - keep a waitlist and release unclaimed seats at the start, without overbooking."
 ]
}

The page's check: kept - nothing to flag

Sensors to the cloud (a hardware lab with a student track) - preflight

150 minutes, 30 registrations; capacity 12, bound by throughput; stationed helpers per work area; provisioned environment only; remove the live dependency; 3 of 6 checks.

Input:

{
 "task": "preflight",
 "session": "Workshop: Sensors to the cloud at Tarnwick College Hack Week; booked length 150 minutes; 30 registrations; free; a curriculum run every edition\nRoom: 40 seats; power at 40 seats; 2 instructors; limited kit or logins: 12 sensor boards\nExercise: the skill can be acquired by reading no; installs on a participant's machine no; accounts to sign up for yes; a live network service while it runs yes (the dependency can be removed yes); participants download, install or sign in during the session yes; distinct workstations yes\nMachines: every participant brings a capable machine they may install on no; employer-managed laptops no; the organizer accepts a platform's terms and issues credentials yes; minors present yes\nVenue network: refuses to answer; unusual protocol, port or device class needed yes; prior edition: a blocked device class\nPractice: pre-day check yes; dry run on a fresh machine yes; two-colour sticky notes yes; helpers briefed that participants type yes; follow-up channel no; material access window NOT SET",
 "room": "Helpers (name | knows the material):\n  Ava | yes\n  Ben | yes\n  Kai | yes\n  Liv | no - logistics only\nPrerequisites as entered, by class:\n  knowledge: Basic Python\n  machine: none\n  account: Classroom login issued by the organizers\nAgenda, in order (block | minutes | checkpoint | kind):\n1. Machine and board check | 25 | no | check\n2. Wire the sensor | 40 | yes | exercise\n3. Break | 15 | no | break\n4. Publish to the broker | 50 | yes | exercise\n5. Wrap-up | 20 | no | talk\nAgenda total: 150 of 150 minutes",
 "facts": "Hands-on: the page's pick is full; rungs No live hands-on available; Demonstration only available; Full hands-on default\nCoverage: the page's pick is stationed; rungs Solo instructor deleted; Structured peer pairing available; Roaming troubleshooter default; Stationed helpers per work area promoted; capable helpers 3, logistics-only 1; the convention asks for 3-4 capable helpers\nCapacity: Room ceiling 40; Coverage ceiling 30; Exercise throughput ceiling 12; capacity 12, bound by throughput\nPrerequisites: the page's pick is provisioned; rungs Nothing published deleted; Published prerequisites default; Provisioned environment only promoted; Both paths offered available\nNetwork: the page's pick is remove; rungs Assume the network holds deleted; Declare the dependency with a fallback default; Clear the room's network in writing promoted; Remove the live dependency promoted\nChecks (3 of 6): Coverage (Capable helpers meet the 1-per-8-10 convention, logistics volunteers not counted) passed; Capacity (Registrations sit inside the lowest of the three ceilings, and the binding one is named) MISSING; Prerequisites (Prerequisites cover knowledge, machine state and accounts, with a check participants run before the day whenever something must be installed or signed into) passed; Network (The venue's answer about this room's network is in writing) MISSING; Setup block (A machine check of at least 20 minutes sits inside the booked length) passed; Afterwards (The material has a home afterwards and a published access window) MISSING\nSignals to record: Ready at minute zero: the share of the room that finished the prerequisites before arriving (self-set); Confidence before and after: an \"I am confident in my ability to...\" rating for the skill taught (the Carpentries' convention - borrow the convention, not their figure); Started versus finished: how many reached the last exercise, counted by done flags (self-set target)\nFindings (16):\n[fix] over_capacity (capacity): 30 registrations for a capacity of 12 (bound by the throughput ceiling) - cap the seats at 12 and keep a waitlist.\n[fix] minors (compliance): Minors in the room: terms are accepted and accounts created for someone who cannot consent - run the participant-data consent review before the day.\n[check] logistics (coverage): Liv knows the logistics, not the material - they satisfy the arithmetic and supply no coverage; do not count them.\n[check] no_noshow (capacity): Free session with no measured no-show share - keep a waitlist and release unclaimed seats at the start; never overbook on a borrowed share.\n[check] compliance (compliance): You accept a platform's terms for the room and issue credentials - review the platform's third-party terms and your own credential data posture; an environment you built is torn down on your schedule.\n[check] venue_refused (network): The venue refuses to answer in writing - remove the live dependency from the exercise.\n[check] protocol (network): The exercise needs an unusual protocol, port or device class - name it in the written question to the venue.\n[check] prior (network): A prior edition's room network failed (a blocked device class) - removing the live dependency is promoted.\n[check] channel (afterwards): No follow-up channel - give questions somewhere to go after the session ends.\n[check] window (afterwards): No access window for the material - publish how long it stays available.\n[check] checks (measurement): Delivery checks: 3 of 6 (all self-set).\n[info] stationed (coverage): Distinct workstations: post a helper at each - one helper at a station covers everyone who reaches it.\n[info] throughput (capacity): The exercise throughput binds: 12 sensor boards - the ceiling most often missed, invisible until the next person needs one.\n[info] provisioned (prerequisites): Not every participant can bring a capable machine they may install on - a provisioned environment is promoted; it trades the install failure for total dependence on the room's connection.\n[info] during (network): Participants download, install or sign in during the session: a whole room doing it at once is a load case - ask for pre-downloads before the day and carry an offline kit (USB sticks with the files and installers, a hub).\n[info] shared_exit (network): 30 laptops behind one venue address hit a registry's anonymous pull limit or an API key's quota together - plan for it."
}

Reply:

{
 "task": "preflight",
 "title": "Sensors to the cloud",
 "intro": "Sensors to the cloud is a 150 minute hands-on workshop at Tarnwick College Hack Week, and the machine and board check starts on time, so please arrive ready before it begins.",
 "knowledge": [
  "Know basic Python."
 ],
 "machine": [],
 "accounts": [
  "Use the classroom login issued by the organizers."
 ],
 "check_steps": [
  "Sign in with the classroom login the organizers issue to you, before the day.",
  "Confirm that login works in the browser you plan to use at the workshop.",
  "If the sign-in fails, contact the organizers before the day rather than at the session.",
  "Brush up on basic Python before the day, since that is assumed going in."
 ],
 "network": "The exercises run without a live network connection during the session. Please sign in and complete any downloads before the day, since the session itself will not depend on the venue's network.",
 "bring": [
  "A laptop, tablet or phone with a web browser you can sign in with.",
  "Its charger."
 ],
 "after": "Where to send questions afterward and how long the material stays available are both to be announced.",
 "note": "Cap registrations at 12 (the throughput ceiling) and complete the minors consent review before sending this note."
}

The page's check: kept - nothing to flag

The prerequisite sheet CSV for the first sample

class,item
knowledge,Comfortable in a terminal
machine,Docker Desktop 4.x running
machine,kubectl 1.30 on the path

Build the input yourself

Load the engine in node (global.window = global; require("./labkit.js"); require("./labreply.js")), then:

const K = LabKit, R = LabReply;
const f = K.form({ name: "My lab", minutes: "180", registrants: "40", seats: "36", instructors: "1", installs: "yes", venue: "notyet",
  helpers: fs.readFileSync("helpers.csv", "utf8"), prereqs: fs.readFileSync("prereqs.csv", "utf8"), agenda: fs.readFileSync("agenda.csv", "utf8") });
// f.ceilings, f.capacity, f.bound, f.capable, f.needLow, f.needHigh, f.byClass, f.agenda, f.agendaTotal
// f.recHands, f.recCover, f.recPrereq, f.recNet and their rungs, f.checks, f.findings
K.sheetCSV(f)                                  // class, item
const b = K.buildInput(f, "sheet");            // or "preflight"
const wire = K.toWire(b.input);                // POST this to /estimate and /run
// then: const reply = R.normalize(R.parseReply(job.output.output), "sheet");
// R.check(reply, b)                           // {status: kept or flagged, notes}

Get a token for the steps below from /tokens.html.

Step 1 — a tiny client helper

One function that sends JSON and unwraps the response. Paste a personal token from /tokens.html, or leave it empty and mint a guest token in step 2.

BASE="https://api.skillsafe.ai/v1/app-api"
TOKEN="paste-your-token-here"   # from https://lab-ready.skillsafe.ai/tokens.html
api() { # api METHOD PATH [JSON-BODY]
  curl -s -X "$1" "$BASE$2" -H "Content-Type: application/json" \
    ${TOKEN:+-H "Authorization: Bearer $TOKEN"} ${3:+--data "$3"}
}

Step 2 — a token

A guest token is enough for /me and /estimate. A run is metered, so it needs a personal token: sign in on /tokens.html and copy it from there.

# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN=$(curl -s -X POST "$BASE/guest" -H "Content-Type: application/json" -d '{"slug":"lab-ready"}' | jq -r '.data.token')

Step 3 — GET /me

Who the token is (subject_type: user or guest) and the credit balance.

api GET /me | jq '.data | {subject_type, credits}' 

Step 4 — POST /estimate

Free. The body is the run input itself, the bare object (never wrapped in {"input": ...}). hold_credits is a reservation, not the price; min_credits is what the balance must cover; model_alias reads gpt-terra.

# input.json: the run input object - {"task": "sheet", "session": "Workshop: ...; booked length 180 minutes ...", "room": "Helpers (name | knows the material) ...", "facts": "Hands-on: the page's pick is full ..."}
# - see the input table
api POST /estimate "$(cat input.json)" | jq '.data | {hold_credits, min_credits, model, model_alias, markup_bps, warnings}' 

Step 5 — POST /run, then poll the job

Send an Idempotency-Key built from the lane and the input: a retry with the same key never bills twice. The page uses lab-ready:<task>:<inputHash>:a<attempt> - the lane is part of the key - and its one automatic reformat retry is a new attempt number, named in the page as one extra run. A sheet carries summary, hands, capacity, coverage, prereqs, network, agenda, materials, triggers, checks, signals and caveats; a pre-flight note carries title, intro, knowledge, machine, accounts, check_steps, network, bring, after and note. The code below prints the headline parts of either (list items are plain strings).

KEY="lab-ready:sheet:$(shasum -a 256 input.json | cut -c1-16):a1"
JOB=$(curl -s -X POST "$BASE/run" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $KEY" --data @input.json | jq -r '.data.job_id')
while :; do
  J=$(api GET "/jobs/$JOB"); S=$(echo "$J" | jq -r '.data.status')
  case "$S" in succeeded|failed|cancelled) break;; esac; sleep 2
done
echo "$J" | jq -r '.data.output.output' > reply.json   # one JSON object, the reply contract
echo "$J" | jq '.data | {charged_credits, truncated}'
jq -r '.summary // .format, .note // .intro, ((.signals // .caveats)[] | "\(.signal // .caveat): \(.text // .text)")' reply.json
jq -r '.network // .note // empty' reply.json   # the network sentence (preflight)

Step 6 — POST /run-stream

The same run as Server-Sent Events, with the same input.json. Browsers receive progress ticks rather than text deltas; the final done event carries the reply.

# Server-Sent Events: tick/delta events while the job runs, then a final event with the job
curl -N -s -X POST "$BASE/run-stream" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: lab-ready:sheet:$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json