Skip to content

Init#1

Merged
MasonEgger merged 20 commits intomainfrom
init
May 4, 2026
Merged

Init#1
MasonEgger merged 20 commits intomainfrom
init

Conversation

@MasonEgger
Copy link
Copy Markdown
Collaborator

No description provided.

A sub-agent swarm audited each chapter's assignment.md against the
workshop-nexus-intro-code exercise/solution sources, the samples-python
and samples-java repos, and the Temporal docs MCP. The findings were
synthesized into audit-report.md, then applied chapter by chapter.

Critical fixes. Chapter 1's startup banner, transaction descriptions,
result strings, and one-line output format were all fabrications that
did not match what payments/worker.py and payments/starter.py actually
print. Replaced the banner verbatim, rewrote the TXN-A/B/C
descriptions to match the real $250/$12,000/$75,000 amounts and
US-US/US-UK/US-US routes, and swapped the fake one-liner output for
the real multi-line Result/Risk/Reason block. The TXN-C decline
reason now correctly cites the over-$50,000 threshold rule rather
than a fabricated sanctions hit, and the Result string is
DECLINED_COMPLIANCE. The same fabricated output block was duplicated
in Chapter 8 and got the same fix. Chapters 1 and 3 also referred to
a non-existent payments-task-queue task queue; corrected to
payments-processing in three places.

Chapter 8 polyglot annotation contract. Added the failure-mode names
the cross-language contract relies on: NOT_FOUND: Unrecognized
operation if Java drops @operation(name = ...) and
UnrecognizedPropertyException if it drops @JsonProperty. Listed the
four Java source files with full paths so attendees can find the
annotated data classes. Added a one-line Jackson-via-temporal-sdk
transitive note. Named the three Nexus events (Scheduled, Started,
Completed) explicitly in the inspection step so attendees see
byte-for-byte equivalence with the pure-Python run. Bumped
setup-workshop with a target/ rebuild guard so the demo survives a
cache miss on the baked image.

Per-chapter polish. Chapter 2 gained a one-liner explaining why the
contract lives in shared/ (neither team owns it), and the
description-file path in solve-workshop was aligned to absolute.
Chapter 4 softened the "wired up the Nexus client" wording (Nexus
clients are created in workflow code at runtime, not registered on
the Worker) and added a forward reference explaining that TXN-B's
MEDIUM auto-approval is a property of the rule-based sync handler we
will replace in Chapter 6. Chapter 4's solve-workshop sleeps were
bumped from 3s to 5s for cold-VM resilience. Chapter 5 instructs
attendees to delete the now-dead _check_compliance import and uses
the real multi-line worker banner in place of a one-line snippet.
Chapter 6 added a namespace clarification for nexus.client() (it
returns the handler-namespace-bound Client, which is the right one
for the cross-namespace Update) and made the Step 8 namespace-selector
instruction explicit. Chapter 7 added the rationale for terminate()
vs cancel() in scenario B (a BackingOff Nexus operation would not
surface a cancel until its next attempt), added the
sync-operation-cannot-be-canceled caveat plus the
WAIT_CANCELLATION_REQUESTED proto-name aside, and dropped the "~"
from "60 seconds" since the docs are exact.

Verification. All eight assignment.md files contain zero em-dashes,
zero remaining payments-task-queue references, and zero references
to the fabricated "sanctioned destination" decline reason. Every
verbatim code snippet, banner, and event-name claim was checked
against the corresponding source file or the Temporal docs MCP.
This commit captures the round-trip with Instruqt that turned the
local track into a live one, plus the rendering fixes that fell out
of seeing it in the sandbox.

Track metadata. After the first push, Instruqt assigned ids to the
track itself, every challenge, and every tab; those ids are now
committed back into track.yml and each chapter's assignment.md so
subsequent pushes update the same artifacts. The track was renamed to
"Replay 2026 Nexus Workshop" with slug `replay26-nexus`. The
loadingMessages field was promoted from the boolean default to a list
of 35 Ziggy-and-tardigrade-themed messages. Other YAML reformatting
in track.yml (folded scalars, list indentation, the assigned
checksum, the enhanced_loading flag) is the CLI's canonical output
and will reappear on every pull, so it is taken as-is rather than
fought.

Image tag. instruqt/config.yml is pinned to
ghcr.io/temporalio/workshop-nexus-intro-sandbox:init while content
stabilizes on the init branch. It will flip back to :latest when init
merges to main.

Rendering fixes. Instruqt's markdown renderer treated the
`=========================================================` separator
lines inside fenced output blocks as Setext H1 syntax, which exploded
the layout and triggered the renderer to fold the broken block behind
a chevron. The separator lines are dropped in every banner snippet
across all chapters. Output fenced blocks are switched from
```output to ```bash,nocopy per the Instruqt markdown editor docs;
attendees get monospace formatting and bash-flavored coloring without
the misleading copy button on text that is not meant to be copied.

Heading hierarchy. The body `# Chapter N: Title` line is dropped from
every assignment, since Instruqt already renders the page title from
the `title:` field in the frontmatter. All `## Step N:` and sibling
section headings are promoted to `# `, and `### Subsection` headings
(Ch 6 substeps, Ch 7 scenario inspections) are promoted to `## `.
The result is a single H1 per page (the frontmatter title) with steps
rendered at the next level down rather than buried under a
duplicate-title H1. Bash-comment lines like `# TODO 4:` and
`# Press Ctrl+C` inside fenced code blocks are untouched.

Ch 3 banner correctness. While dropping the separator lines, the
audit-missed fabricated startup banner in Ch 3 (matching the same
shape of bug as the Ch 1 one the last commit fixed) was rewritten to
match what the Compliance Worker actually prints.

Build automation. A justfile at the repo root provides `just push`,
`just pull`, `just init` (first-push helper that reminds you to
commit the assigned ids), `just validate`, and `just diff` for the
Instruqt CLI workflow.
@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 27, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addeddocker/​build-push-action@​10e90e3645eae34f1e60eeb005ba3a3d33f178e898100100100100
Addeddocker/​login-action@​c94ce9fb468520275223c153574b00df6fe4bcc999100100100100
Addedactions/​checkout@​34e114876b0b11c390a56381ad16ebd13914f8d5100100100100100

View full report

Comment on lines +44 to +50
run: |
if [ "${{ github.ref_name }}" = "main" ]; then
echo "extra=${{ env.IMAGE }}:latest" >> "$GITHUB_OUTPUT"
else
echo "extra=${{ env.IMAGE }}:${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
fi

Copy link
Copy Markdown

@semgrep-managed-scans semgrep-managed-scans Bot Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".

🥳 Fixed in commit 81ee050 🥳

This commit follows up on `ec8c183` (which introduced the Solution
tabs) by working through a full audit of the eight chapter assignment
files for consistency, attendee discoverability, and renderer
behavior.

Solution tabs. The six tabs added in the prior commit lacked `id:`
fields and sat at the end of each chapter's tab list, after the
Temporal UI service tab. Each now has a stable 12-character id
(`cjoljjm4x5i1`, `ww0fsdf18zxw`, `azh4d9gf2did`, `lmldoarsfqyc`,
`hhmx3u77tul9`, `mxlwpnohrz8r`) so subsequent pushes update the same
artifact rather than racing against a fresh assigned id. The tabs
also moved to index 1, immediately after Code Editor, on the theory
that two code-viewing surfaces belong next to each other. Every
`(tab-N)` button reference in chapters 3-7 was rewritten to absorb
the index shift.

Admonition syntax. The prior commit introduced two GitHub-flavored
`> [!NOTE]` callouts in Chapter 2 alongside plain `>` blockquotes
elsewhere. This commit completes that conversion: every blockquote
in all eight chapters now opens with `[!NOTE]`, `[!TIP]`,
`[!WARNING]`, or `[!IMPORTANT]`. Choices follow intent: `TIP` for the
new "Stuck? See Solution" callouts, troubleshooting tips, and "where
to go next"; `WARNING` for footguns (Ch 2 missing decorator, Ch 8
dev-server failure); `IMPORTANT` for Ch 7 production take-aways;
`NOTE` for the rest.

Solution-tab discoverability. Chapters 2-7 each gained a `[!TIP]`
near the start of "What you will do" reminding attendees the
**Solution** tab exists. Chapters 1 and 8 instead got a `[!NOTE]`
explaining why their layout differs (Ch 1's Code Editor is the
finished monolith; Ch 8's is the finished Java implementation), so
the asymmetry between chapters does not look like a missing tab.

Knowledge checks. Chapter 1 already ended with a knowledge-check
blockquote; chapters 2-8 now have parallel three-question blocks at
the end of each chapter's wrap-up, all under `> [!NOTE]`. The
questions are calibrated to the chapter's central concept (sync vs
async, error types, validator semantics, and so on) rather than
trivia.

Smaller fixes. Ch 3 Step 6 referenced the Web UI without a
`[button label="Temporal UI"]` link; that link now points at the
correct tab index. Ch 7 softened "~90 seconds total" and "~20
seconds" to ranges with explanations, since those numbers depend on
retry timing. Every challenge frontmatter now sets
`enhanced_loading: false` to match `track.yml` rather than `null`.

No changes needed. The Ch 3 and Ch 5 worker startup-banner snippets
were re-verified against the corresponding `compliance/worker.py`
files in `workshop-nexus-intro-code` and match exactly. Chapter
titles were already consistent in their casing.
This commit consolidates a top-level review pass over the eight chapter
assignment files plus a new ninth chapter, syncs the assignment text
with a TODO-numbering rework happening in `workshop-nexus-intro-code`,
and fixes a Semgrep finding in the image build workflow.

Assignment structure. Every chapter loses its `# Chapter N: ...` H1.
Instruqt was rendering the YAML `title:` as the page header and the
markdown H1 stacked underneath, producing the title twice on every
page. The H1 is gone now; the YAML title is the single source.

Section header rename. `## Why this chapter exists` (which read as
weak in the lab UI) is now `## What You're Solving` across all eight
chapters.

Solution tab moves to the rightmost position. In chapters 2-7 the
Solution tab was at index 1, immediately next to the Code Editor, and
attendees were misclicking and editing the finished file. Solution
now sits after every other tab (Worker terminals, Starter, Temporal
UI). Every `(tab-N)` button reference in those chapters was
renumbered to absorb the index shift. The "Stuck on a TODO" callouts
gained a "(rightmost)" pointer and were converted from `[!TIP]` to
`[!NOTE]` so Instruqt renders them as admonitions.

Wrap-up rename and knowledge-check removal. `## Wrapping up` is now
`## Key Takeaways` everywhere, and the trailing `> [!NOTE] Knowledge
check:` blockquotes have been dropped from every chapter. The
chapter-by-chapter quizzing role moves to the live AhaSlides deck;
the in-lab text now ends on a forward-looking summary instead of
unanswered questions.

"Stop the Worker" steps removed. Each chapter's per-challenge
`cleanup-workshop` already runs `pkill -f "payments.worker"` and
`pkill -f "compliance.worker"` between challenges, so the trailing
`## Step N: Stop the Worker(s)` step in chapters 1, 3, 4, 5, 6, 7,
and 8 was redundant busywork. Those steps are gone; the surviving
steps are still in correct numerical order.

TODO sub-letter sync with the code repo. The companion change in
`workshop-nexus-intro-code` rewrote exercise files to follow the
"strip exactly what the user is asked to write; one TODO per
insertion point; sub-letters when a logical step touches multiple
locations" standard documented in `tmp/lessons-learned.md`. The
assignment text mirrors that numbering:

- Ch 2: Step 1 now walks TODOs 1a (decorator), 1b
  (`check_compliance` Operation), 1c (`submit_review` Operation).
- Ch 3: Step 1 walks 2a (class decorator), 2b
  (`check_compliance` body), 2c (`submit_review` stub).
- Ch 4: Step 1 walks 4a (remove unused import), 4b (replace activity
  call with Nexus call). Step 2 walks 5a (worker import), 5b
  (Activities list).
- Ch 5: Step 2 walks 7a (convert handler) and 7b (delete dead
  import).
- Ch 6: Step 1 walks 10a (init state), 10b (run-method branching),
  10c (Update handler + validator). Step 2 walks 11a (`WorkflowHandle`
  import), 11b (`submit_review` body). Step 3 walks 12a/12b in
  `payments/workflows.py` and 12c/12d in `payments/worker.py` for the
  cross-file `ReviewCallerWorkflow` change.
- Ch 7: Step 1 walks 13a (top-level `nexusrpc` import) and 13b
  (failure-injection branches).

Code-Editor file path test. Chapter 2's Code Editor tab `path:` now
points at `…/exercise/shared/service.py` directly instead of the
chapter directory, to test whether Instruqt's `code` tab will open a
specific file by default. The Instruqt docs only describe `path:` as
a directory location, so this is a speculative experiment; if it
works, the same change will roll out to the chapters that have a
single primary edit target.

New chapter 09-what-next. Added a Multiple Choice (`type: quiz`)
challenge as the wrap-up after the polyglot demo. The body is a
resource page with links to docs.temporal.io/nexus, learn.temporal.io,
the per-language samples repos, the workshop's own code repo,
follow-up patterns we did not have time to teach (in-workflow
cancellation, `asyncio.shield`, Worker Versioning), and the
community channels. The single answer is "Do you plan on using
Nexus?" (Yes / No, both marked correct so the chapter passes either
way and the response captures intent without gating progress). The
old chapter-8 `> [!TIP] Where to go next` block was removed since
those links now live in the wrap-up chapter.

Loader-message tweak. `track.yml` line 33 dropped "the tardigrade"
from the rehydrating Ziggy message, matching the wording on the
other 30+ Ziggy lines.

Build workflow Semgrep fix. `.github/workflows/build-image.yml` was
flagged by Semgrep `yaml.github-actions.security.run-shell-injection`
for interpolating `${{ github.ref_name }}` and `${{ env.IMAGE }}`
directly into the `Compute image tags` shell script. The step now
binds `REF_NAME` via a step-level `env:` block and reads `IMAGE`
through its job-level env definition, so neither value is
string-substituted into the shell. Semantics are unchanged.

AhaSlides documentation tweak. `aha.md` updated to reflect that the
Pattern Roulette spinner (slide 5) is now skipped during
presentation. The slide remains in the deck (id 150153117) with
`skip_when_presenting=True`; downstream slide numbering is unchanged.

justfile. Added `slides-install`, `slides-dev`, and `slides-build`
recipes for the Slidev deck. The `slides/` directory itself is not
in this commit.
@nadvolod nadvolod mentioned this pull request Apr 29, 2026
3 tasks
This commit drops the initial Slidev presentation deck for the
workshop, documents the repo's architecture and slide-deck
conventions in `CLAUDE.md`, and lands a second editorial pass over
all nine Instruqt chapter assignments. Plus a small justfile safety
fix and an end-to-end polyglot solve script.

Slidev deck (new, `slides/`). The whole directory is new: a master
`slides.md` that imports per-chapter files from `slides/chapters/`,
the vendored Temporal theme at `slides/theme-temporal/` (footer text
and `WorkshopToc.vue` chapter list customized for this workshop), and
ten chapter files (`welcome`, `ch01-why-nexus`, `ch02-service-contract`,
`ch03-sync-handler`, `ch04-caller-workflow`, `ch05-async-operations`,
`ch06-updates`, `ch07-lifecycle`, `polyglot`, `wrap`). Every on-slide
bullet has a matching `**Build N**` entry in the speaker notes
following the convention; AhaSlides transition slides ("Quiz Time",
"Halftime!", "Reaction Time") carry scripted Lead-in / Lead-out lines
keyed to specific AhaSlides slide numbers. The deck builds cleanly
with `pnpm build`.

Workshop-register slide patterns (mirrors `tmp/Temporal 102 in Python`).
The deck adopts four canonical 102 patterns that were missing from the
initial draft: a single workshop-level `During this workshop, you will`
Outcomes slide (verb-led contract with the room, in `welcome.md`),
per-chapter `Review` slides on the consequential chapters (Ch01, Ch04,
Ch05, Ch06, Ch07), an `Essential Points (1)` through `Essential Points
(5)` synthesis sequence at the wrap, and a combined "Thank you for
your time and attention / We welcome your feedback" closing slide that
replaces a separate `Questions?` end slide. The thesis sentence "The
contract is the integration." is reasserted three times: welcome ("What
Is Nexus?"), Chapter 2 close ("Why Types Matter Here"), and `Essential
Points (5)`.

Workshop register on slide bodies, personality in notes. The slide
bodies stay declarative throughout: no first-person opinion ("I
believe"), no tag questions, no dramatic ellipsis, no SRE anecdotes,
no mock dialogue. Those flourishes belong in talks, not workshops, and
live in the `<!-- ... -->` speaker-notes blocks where they coach the
delivery without competing with the slide for the room's attention.

Brand rule: Temporal logo never tinted mint green. The vendored theme
had `.cover-logo` and `.end-logo` set to `var(--temporal-green)`, which
renders the Temporal plus mark in mint and violates Temporal's brand
standards (the mark must be white on dark or black on light; mint
green is reserved for accent text, links, and UI affordances, never
the logo itself). Both layout selectors now hard-code `color: #ffffff;`
with an inline brand-rule comment above them so a future editor does
not "fix" it back to the palette variable. The `TemporalLogo.vue`
component header was expanded with the same rule so it travels with
the component for any future layout that imports it. Other mint-green
uses (link colors, page numbers, TOC dots, blockquote borders) were
left alone; the rule is logo-specific.

CLAUDE.md (new, untracked). Captures the repo's three runtime surfaces
(Instruqt lab, Slidev deck, AhaSlides), the sandbox-image build flow,
the sparse-stage pattern in `setup-workshop` scripts, the load-bearing
nature of Instruqt-assigned `id:` and `tabs:` ids in YAML frontmatter,
and the slide-deck conventions described above. A new "Brand rules"
section codifies the logo-color rule above so any future session
rendering or editing the theme inherits it without needing to find
the inline CSS comment first. Calls out `tmp/` as the local-only
references directory holding `style.md` (the synthesis style guide,
which can overgeneralize) and the two source PPTX decks (`Temporal
102 in Python` and `Events are the Wrong Abstraction`) that are
canonical for any pattern decisions; the PPTX wins when they
disagree.

Instruqt assignment prose pass (chapters 1 through 8). Tightened
wording across every chapter, removed remaining forward references
("Chapter 5 adds them" -> "the next chapter adds them" or fully
inlined), and made several technical explanations more precise:

- Ch 1: reframed the monolith framing note to make explicit that the
  visible-Activity coupling is the extreme form, while the more common
  shape in production is two teams sharing a namespace and task queue
  with no contract between them. Smoothed the TXN-B description so the
  $10K threshold reads as the cause directly.
- Ch 2: unchanged in spirit; rewording for cadence.
- Ch 3: tightened the sync handler explanation; minor cleanup.
- Ch 4: expanded the "no caller-side retry policy" bullet to make the
  retry-vs-timeout distinction explicit (Nexus owns retries of the
  StartOperation, bounded by `schedule_to_close_timeout`; the policy is
  built-in and not user-tunable; only the timeout envelope is). Added a
  new `Nexus:` line example for the worker startup banner.
- Ch 5: small cleanup; `compliance-ch05-{txn_id}` workflow IDs
  consistent.
- Ch 6: switched the `__init__` to `@workflow.init` with a typed
  `request: ComplianceRequest` parameter and explained why (constructor
  parameters are bound before message handlers run, so `_request` is
  typed `ComplianceRequest` instead of `ComplianceRequest | None`).
  Added the "Update rejection writes nothing to History" nuance to the
  validator paragraph (no `Accepted`, no `Completed`, no `Rejected`
  events). Added the `start_update(..., wait_for_stage=ACCEPTED)`
  alternative as a follow-up to `execute_update`. Workflow IDs are now
  `compliance-ch06-{txn_id}` and `payment-ch06-{txn_id}` to keep
  per-chapter histories isolated for the lab.
- Ch 7: rewording for cadence; lifecycle scenario explanations
  tightened.
- Ch 8: polyglot framing tightened; small clarifications.

Polyglot solve-workshop walks the full A/B/C path. The previous
solve script ran `payments.starter` once and exited, which left TXN-B
blocking on the Java handler's `wait_condition` and never produced the
finished-state output. The script now backgrounds `payments.starter`,
sleeps briefly, runs `payments.review_starter` to unblock TXN-B, then
waits on the starter to drain through TXN-C. The solve now exercises
the same flow attendees see in the live demo plus the Chapter 6 review
path against the Java handler.

Chapter 09 (`what-next`) updates. Replaced the generic Nexus tutorial
link with the specific Java sync tutorial URL plus the canonical
Python Nexus quickstart on the docs site. Expanded the sample-code
references to specific subdirectories per language (`hello_nexus/`,
`nexus_cancel/`, `nexus_multiple_args/`, `nexus_sync_operations/` on
the Python side; the Java equivalents). Replaced the em-dash list
separator with colon-led prose to match the no-em-dashes rule.

Added a `CLAUDE_HELP` HTML comment at the top of the chapter flagging
the release blocker that `temporalio/workshop-nexus-intro-code` is
currently empty (only `.gitignore` and `LICENSE`). The comment never
renders to attendees; it exists so a future Claude session sees the
unfinished prerequisite and surfaces it before the workshop ships.

justfile default recipe is now `@just --list`. Previously `just`
with no arguments ran `push`, which is destructive (it would push the
local `instruqt/` tree to Instruqt). Listing the recipes is the safer
default; pushing now requires the explicit `just push`.

Other small changes. `.gitignore` adds `.playwright-mcp/` so the
Playwright MCP server's local artifacts stay out of the tree.
`instruqt/track.yml` got a regenerated `checksum:` from the Instruqt
CLI tooling.
Ch 1 narrative restructure. The chapter now opens with the framing
slides (Two Teams, What Goes Wrong, The Shape You Probably Have,
Quick Poll), runs the monolith exercise (Exercise 1) BEFORE
introducing Nexus, then runs a "Where Are the Seams?" debrief slide
that surfaces what students just saw, and only then transitions into
the Nexus solution arc. The pedagogical principle: feel the pain
before being told the fix. Adult learners internalize architecture
problems they have just touched, not problems explained to them. The
lab assignment was already written for this placement; only the slide
order changed.

New slides in Ch 1.

- "Where Are the Seams?" — a debrief slide that reflects on what was
  just observed in Exercise 1, with priming bullets for the deck
  driver in case the room is quiet (Compliance code on the Payments
  Worker, same default namespace + payments-processing task queue, no
  boundary in Event History; deploy coupling, blast radius, mixed
  PCI/KYC scope).
- "Two Operation Types" — explicit synchronous vs asynchronous
  Operation distinction, set BEFORE Two Hard Limits so the room has
  both words anchored before the constraint slide lands. Table format:
  Behavior, Used for, Bounded by; lead-in line names that the
  Operation is the one building block of the four with a choice.
- "Same Word, Three Different Things" — a vocabulary disambiguation
  slide for "handler", which the docs use for three referents (a side,
  a piece of code, a Worker). Workshop convention: "handler" for the
  code, "implementer" for the side, "Worker" stays "Worker", "caller"
  stays "caller." Speaker notes name the issue ("you're not crazy")
  and give the room a portable habit ("substitute 'implementer' when
  the docs say 'handler' for the role; after a week you won't notice
  you're doing it").
- "From Weld to Contract" — the Nexus introductory slide, renamed
  from "What Nexus Is, In One Sentence" to ground the welding/seam
  metaphor that runs through the chapter. Sentence is now: "A Nexus
  call is a way of invoking a typed Operation behind a contract, with
  durable delivery. Think durable RPC." Reviewed against the docs MCP:
  accurate today (caller is a Workflow, per Python SDK README) and
  forward-compatible (the slide says "a way of invoking" rather than
  "a Workflow invoking" so it stays accurate when non-Workflow callers
  ship per the GA roadmap).
- "A Preview of the Destination" — the Topology Sandbox preview,
  moved into Ch 1 from the welcome chapter and reframed as a
  destination tease that lands AFTER the Nexus intro arc instead of
  as an early-workshop logistical beat.

Two Hard Limits corrected. The previous framing ("Sync handlers must
respond within 10 seconds") was incorrect per Cloud limits and
nexus/operations docs: the 10-second per-attempt deadline applies to
BOTH sync AND async handlers. What differs is the work that has to
fit in the window. Sync must produce the full result inside it; async
only has to start a Workflow (`start_workflow` returns in
milliseconds), with the resulting Workflow then running up to
schedule_to_close (60-day cap on Cloud). The slide now reflects this,
and the Review slide at the chapter close was updated to match.

Vocabulary disambiguation across the deck. The Temporal docs use
"handler" for three different referents (a team or namespace, a
function or class, a Worker process), which is internally consistent
but causes referent-shift confusion sentence to sentence. The
workshop now adopts:

- "handler" = the code only (a function or class decorated with
  `@sync_operation` or `@workflow_run_operation`).
- "implementer" = the side, the team, the role.
- "Worker" stays "Worker." Already its own well-known concept.
- "caller" stays "caller." The docs only use that word one way.

Sweep applied across ch03, ch05, ch06, ch07: 11 instances of
"handler-side" / "handler side" replaced with "implementer-side" /
"implementer side". Code-level usages of "handler" (sync handler,
async handler, handler Worker, handler Workflow, decorator names) are
kept because they match SDK and doc canon.

Welcome chapter trimmed. Removed "What Is Nexus?" (the definition now
lives only in Ch 1's "From Weld to Contract", so the welcome chapter
doesn't blow the punchline) and "A Preview, Before We Begin" (moved
into Ch 1 and reframed). About Me line condensed. Three Environments
slide adds an inline AhaSlides QR code (asset added to
`slides/public/ahaslides-qrcode.png`) so the room can scan to join.
The Agenda table is now a 7-row schedule with scoped styling (smaller
font, tighter padding) so it fits the slide.

Schedule alignment across all four artifacts. The workshop runs 9:00
to 12:30 with a hard-locked 11:00 to 11:30 break. To fit those
constraints, Ch 5 (Async Operations) moves to BEFORE the break
instead of after. Updated:

- `slides/chapters/welcome.md` Agenda table.
- `course-plan.md` activity timing table (Ch 5 row reordered).
- `aha.md` "Trigger pattern" prose (Ch 1 deviation called out
  explicitly), mermaid flowchart restructured to show Ch 5
  lecture/quiz/lab landing before halftime, "Halftime and break"
  section consolidated.
- `CLAUDE.md` ordering note rewritten: now reads as "Ch 1 is
  intentionally asymmetric" instead of "course-plan and aha disagree."

AhaSlides deck physically reordered. Used the AhaSlides MCP to move
slides 22-25 (Ch 5 questions) before slide 19 (halftime leaderboard)
so the deck ordering matches the new chapter sequence. Final order:
Ch 4 closes (slides 17-18), Ch 5 questions (19-22), halftime
leaderboard (23), break-time pulse and Q&A parking lot (24-25), Ch 6
onward (26+).

Section-divider title slides removed. Each chapter previously opened
with a TOC slide followed by a section-divider title slide (e.g., `#
01 / Why Nexus`, `# 02 / The Service Contract`). The TOC slide already
highlights the current chapter, so the additional section-divider
title was redundant. Removed across ch01 through ch07, polyglot, and
wrap (9 slides total).

Wrap chapter additions. New "What's Next for Nexus" slide inserted
between "Patterns We Didn't Cover" and "Where to Go Next". Lists
roadmap items pulled from the Nexus GA announcement and the Public
Preview blog: non-Workflow callers (bash, service, app), contract-
first development with `nexus-rpc-gen`, per-caller rate limiting plus
fine-grained authorization, enhanced routing rules. Closing v-click
ties back to the "durable RPC" framing from Ch 1: "Today's Workflow-
to-Workflow case is one application of a broader durable-RPC story.
The platform is leaning in."

Theme typography brought to PPT-equivalent. Font sizes now mirror the
canonical `Temporal 102 in Python` deck:

- h1 (slide title) = 3rem (48pt PPT equivalent).
- h2 = 2.2rem, h3 = 1.7rem (proportional).
- p, li, base = 1.375rem (22pt).
- code blocks = 1.375rem (22pt); inline code = 1.2rem.

Footer raised from 48px to 18px from canvas bottom via `margin-
bottom: -1.875rem` on `.temporal-footer`, leaving the content's
lower-third protection intact (the layout's `padding-bottom: 3rem`
still constrains where content can go; only the footer extends past
it). Patterns slide punchline ("None of these draw a line between
teams.") styled with a scoped class: centered, larger font, mint
green for both regular and bold text. Agenda slide has scoped
table styling (smaller font, tighter cell padding) so 7 rows fit
comfortably.

Em-dash sweep. The user's no-em-dash rule applies to every written
output for this project (memory file
`feedback-no-em-dashes.md`). Em-dashes were introduced in earlier
sessions across speaker notes and prose; this commit removes them and
replaces with periods, commas, colons, semicolons, or parentheticals
as appropriate.

GitHub Actions image build cleanup. Removed the `repository_dispatch`
trigger that auto-republished the sandbox image when the code repo
notified this repo. The build now triggers on push to `main` when
`docker/**` or the workflow itself changes, and is also manually
triggerable via `workflow_dispatch` from the Actions UI (with an
optional `code_ref` input). Republishing after a code-repo change is
now a deliberate manual click.

Other small changes. `slides/slides.md` dropped 20 lines of unused
intermediary headmatter. `instruqt/track.yml` got a regenerated
`checksum:` from the Instruqt CLI tooling. New untracked directory
`slides/public/` holds the AhaSlides QR code asset referenced from the
Three Environments slide.
Multi-session sweep. The deck got new slides and reorganized teaching
notes, the schedule moved from one 30-minute break to two 15-minute
breaks, the Slidev exercise layout grew a real countdown timer, the
Instruqt labs absorbed Michael Haynie's QA feedback, and the repo got
a top-level README.

## Instruqt: Michael Haynie's lab review

Michael walked the labs end to end and flagged a punch list. All
addressed in this commit:

- **Ch 1**: KYC and AML acronyms expanded to "KYC (Know Your
  Customer)" and "AML (Anti-Money Laundering)" on first appearance.
- **Ch 2**: corrected the misleading claim that only `endpoint get`
  surfaces the Markdown description (`endpoint list` shows it too);
  fixed the left-nav tab label from "Nexus Endpoints" to "Nexus" to
  match the dev-server UI as deployed.
- **Ch 3**: removed the entire "Confirm both Workers are healthy"
  step. It told learners to click a Workers entry in the left
  navigation that does not exist on the workshop's dev-server build.
- **Ch 4**: reordered TODO 4a to land before TODO 4b in the lab so
  the natural reading order matches the apply order; dropped the
  false promise that the worker startup banner gains a `Nexus:`
  line. The deployed exercise's print statement is hardcoded
  monolith-style and the lab can't promise it changes.
- **Ch 5**: clarified that the Worker startup banner is intentionally
  minimal in this chapter (no `Registered:` line) so the absence is
  not a bug to chase; rewrote the optional durability test to stop
  the Compliance Worker BEFORE running the starter rather than
  trying to Ctrl-C it inside a 2-second window. The new shape: kill
  the Worker, run the starter (it blocks at NexusOperationScheduled
  with no Started event), restart the Worker, watch it pick up. The
  durability point lands without the timing pressure.
- **Ch 7**: pivoted Scenario B's inspection to read Event History at
  the user's own pace (`temporal workflow show`) as the primary
  path, with the live `BackingOff` watch demoted to optional. The
  20-second window the starter held open before terminating was too
  tight for someone reading carefully.
- **Ch 9**: replaced the broken Yes/No survey (which required
  selecting BOTH boxes to advance because of `solution: [0, 1]`)
  with a single-answer reflection quiz on the workshop's central
  thesis ("typed Service contract plus a Nexus Endpoint"). The
  survey signal moves entirely off Instruqt to the post-workshop
  feedback link on the closing slide.

The Ch 5 "missing imports" bug Michael hit is fixed in the companion
`workshop-nexus-intro-code` repo's working tree (uncommitted there as
of this session); landing it requires committing in that repo and
rebuilding the sandbox image.

## Instruqt: feedback collection removed from the lab

Instruqt's in-lab feedback recap and feedback tab are off. Mason runs
a separate post-workshop survey via the QR + URL on the wrap deck's
closing slide, so the Instruqt-side prompts were redundant.

- `instruqt/track.yml`: `feedback_recap_enabled` and
  `feedback_tab_enabled` flipped from `true` to `false`.
- `instruqt/09-what-next/assignment.md`: removed the callout
  pointing at the Feedback tab.

The community-forum reference in Ch 9 ("long-form questions, design
feedback, and searchable history") describes the forum's purpose and
stays.

## Schedule restructure: two 15-minute breaks

Schedule moves from a single 30-minute break at 11:00 to two
15-minute breaks (9:45-10:00 and 11:15-11:30). The day now reads as
three blocks:

- **Block 1 (45 min)**: Welcome, Ch 1, Ch 2. Set up the problem,
  define the contract.
- **Block 2 (75 min)**: Ch 3, Ch 4, Ch 5. Build the integration end
  to end, sync handler through the caller swap into async.
- **Block 3 (60 min)**: Ch 6, Ch 7, Polyglot, Wrap. Human-in-the-loop,
  lifecycle control, polyglot demo, close.

Halftime + leaderboard now lands at 11:15-11:30, after Ch 5, instead
of replacing the break. Updated:

- `course-plan.md`: activity timing table reordered, "three blocks"
  paragraph added below totals.
- `slides/chapters/welcome.md`: Agenda table rewritten to match the
  new block structure.
- `aha.md`: prose adjustments are minimal here; AhaSlides ordering
  was already locked in the prior commit.

## Slidev: countdown timer in `exercise.vue`

The exercise layout grew from a static "N min" chip into a real
countdown timer.

- MM:SS countdown.
- Play / Pause toggle that morphs based on state. Idle starts the
  timer; running pauses; paused resumes; expired resets and starts.
- Restart button always resets to full duration and starts running.
- State persists via `localStorage` keyed by `(heading, minutes)` so
  the timer survives slide navigation and stays in sync between
  presenter and audience views.
- Storage key namespace: `nexus-workshop:timer:<heading>:<minutes>`.

The timer is wall-clock based (stores `endsAt` while running, not a
decrementing counter), so a slide that sits unmounted for 90 seconds
returns with the right remaining time.

## Slidev: chapter content changes

Heavy rework across all seven content chapters and the wrap. Pattern
of the changes:

- **Headlines refactored to define by behavior, not by Python form.**
  Ch 3's "What Is a Sync Nexus Handler?" now opens with what the
  handler does (run and return inline within the deadline) and
  demotes the `@sync_operation` reference to a bullet. Ch 5's
  "Defining an Async Handler" replaces the decorator-named slide
  title for the same reason. Mirrors Ch 2's "What Is a Nexus
  Service?" mold.
- **Teaching notes split out from spoken script.** Speaker notes are
  now structured as: spoken script with `**Build N**` markers up
  top, then a `## Teaching notes` block below for stage direction,
  doc citations, anecdotal anchors that stay verbal, and reasons a
  given build exists. Applied across every chapter file.
- **New "When to Use a Sync Handler" slide in Ch 3.** Implements the
  PM-call guidance: sync is for fast, reliable handoffs (forwarding
  to a workflow, in-process compute, reliable downstream Temporal
  infrastructure), not for arbitrary external HTTP. Names the
  circuit-breaker scope (per caller-Namespace, Endpoint pair) and
  why rate-limited APIs trip it. The workshop's `check_compliance`
  is anchored as the reliable in-process case explicitly.
- **New "What's Different on Temporal Cloud" slide in the wrap.**
  Cloud-vs-self-hosted differences land as five bullets:
  per-Endpoint allowlist, mTLS Envoy mesh + audit logs,
  account-scoped Endpoints, HA Namespaces and cross-region routing,
  production limits / Worker tuning. Frame: the contract is
  portable; the Cloud differentiators sit on the operator surface.
- **New "Meet the Teams" slide in Ch 1.** Business framing
  (Payments processes transactions; Compliance assesses regulatory
  risk into LOW / MEDIUM / HIGH) before the chapter's pain
  enumeration. The structural picture got the room the topology;
  this slide gives them the stakes.
- **Standalone activities added to wrap close.** New bullet under
  "Patterns We Didn't Cover": standalone activities, GA-imminent on
  Temporal Cloud, the right tool for unreliable external HTTP.
  Co-launch with Coinbase 2026-05-06; customer name lives in
  Teaching notes only, never on the slide.
- **Cancellation table tightened in Ch 7.** Removed the
  decision-tree mermaid (overlapped with the table); compressed
  table cells; merged the wire-format aside into a v-click; surfaced
  "sync Operations cannot be cancelled" as its own v-click.
- **`# Four Ways Off the Happy Path`** replaces Ch 7's "What This
  Chapter Teaches You to Recognize" headline. More direct, easier to
  return to from the next slide.
- **Authority framing added in Ch 2.** The Service is owned by the
  team that names it. Other teams open PRs against it; the owning
  team has write access. Compliance writes the contract, registers
  the Endpoint, and decides who's allowed to call. This frames the
  per-Endpoint allowlist that lands later.
- **AhaSlides URL updated everywhere from O8RSE to NEXUSWS.**
  Final-standings slide and reflection slide both point at the new
  shortcode.
- **Closing slide gains the feedback QR.** `exit-survey-feedack.png`
  added to `slides/public/`; bottom-right positioning via scoped
  `<style>`. URL is `t.mp/replay26-ws-feedback`. Replaced the prior
  AhaSlides URL on the close.

## CLAUDE.md additions

- New row in "What lives where" pointing at `slides/DEPLOY.md` (VPS
  hosting guide; previously undocumented in the index).
- New section "Vocabulary convention: handler vs implementer"
  documenting the workshop's disambiguation of the docs' three uses
  of "handler" (side, code, Worker process). Specifies which
  phrasings belong to the role (sweep to "implementer") and which
  belong to the code (keep "handler"). Pairs with the Ch 1 "Same
  Word, Three Different Things" slide.
- Slide-deck conventions block expanded: per-slide `<style>` blocks
  beat frontmatter `class:` overrides for theme-font-size overrides;
  chapters open with `layout: toc` only and never re-add section
  dividers; PPT-equivalent font sizes documented with the conversion
  rule (Slidev's 980px canvas vs PPT 16:9's 960pt).
- Thesis-sentence reassertion location updated to "From Weld to
  Contract" (was "What Nexus Is, In One Sentence").

## Top-level README

New `README.md` at the repo root. Public-facing entry point that
explains:

- What the workshop is, who it's for.
- The three runtime surfaces (Slidev deck, Instruqt lab, AhaSlides),
  with a Mermaid flowchart of how they hand off.
- Repo layout table with clickable paths.
- Quick-start commands (Instruqt CLI recipes, Slidev `pnpm` scripts,
  PDF export).
- Pointer to `slides/DEPLOY.md` for live presenter-follow setup.
- Sandbox-image build flow (CI on `docker/**` push, manual republish
  via `workflow_dispatch`).
- Pointer to the companion `workshop-nexus-intro-code` repo.
- Pointer to `CLAUDE.md` as the canonical authoring guide.

Deliberately does not duplicate `CLAUDE.md` content. CLAUDE.md is the
deep authoring/conventions manual; README is the entry point.

## Other small changes

- `aha.md`: graded-quiz prompts gained explicit correct-answer and
  distractor labels for slides 9, 15, and 29; the Match-pairs
  prompt for cancellation types now spells out the four pairings
  inline rather than relying on the AhaSlides UI alone.
- `slides/public/exit-survey-feedack.png`: new asset for the closing
  feedback QR.
Copy link
Copy Markdown
Contributor

@prasek prasek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overall lgtm, dropped some comments/suggestions


<v-clicks>

- **Shared blast radius.** A bug in `check_compliance` takes down `execute_payment`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Shared blast radius.** A bug in `check_compliance` takes down `execute_payment`.
- **Shared blast radius.** A bug in `check_compliance` takes down `execute_payment`.
- **Overly permissive security.** Both teams have full access to everything in the monolithic namespace.

Comment thread slides/chapters/ch01-why-nexus.md Outdated

<v-click>

A Nexus **Service** is that contract, expressed in your SDK's native types.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A Nexus **Service** is that contract, expressed in your SDK's native types.
A Nexus **Service** is that contract, expressed in your SDK's native types (with JSON serialization or proto defs for polyglot environments).

We mention Polyglot later but should really put folks at ease that it's not just native types (and single language) but we do support polyglot - just like the rest of Temporal does with the same data converters

Comment thread slides/chapters/ch03-sync-handler.md Outdated

<v-click>

**Avoid for arbitrary external HTTP.** Rate limits, timeouts, and 5xx trip the circuit breaker fast.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
**Avoid for arbitrary external HTTP.** Rate limits, timeouts, and 5xx trip the circuit breaker fast.
**Back with a Workflow or Standalone Activity for arbitrary external HTTP.** Rate limits, timeouts, and 5xx can trip the Nexus circuit breaker fast so handoff to a durable backing primitive.

- **What happens.**
- New Operations get `State: Blocked`. After 60s, one probe decides close or re-open.
- **Why a trip is bad.**
- Every caller targeting that Endpoint freezes for at least a minute.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Every caller targeting that Endpoint freezes for at least a minute.
- Each Nexus caller-destination pair trips independently, so specific callers can freeze for a minute or more if the circuit breaker is not considered.


# Spotting a Circuit-Breaker Trip

When the breaker opens, here's what it looks like in production.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When the breaker opens, here's what it looks like in production.
When the breaker opens for a caller-destination pair, here's what it looks like in production.

Comment thread slides/chapters/wrap.md Outdated

- Cross-team Temporal integration needs cross-team Nexus Endpoints. **Namespaces become tenancy boundaries with real teeth.**
- A Nexus **Service** is a typed Python class both teams import. **Operations** are the typed methods on it.
- An **Endpoint** is a routing entry the operator creates with the Temporal CLI. Caller code names only the Endpoint.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- An **Endpoint** is a routing entry the operator creates with the Temporal CLI. Caller code names only the Endpoint.
- An **Endpoint** is a reverse proxy with a routing entry the operator creates with the Temporal CLI. Caller code names only the Endpoint.

Comment thread slides/chapters/wrap.md Outdated
- **Synchronous handlers** run inline on the handler Worker, return a result directly, and must respond within a **10-second** per-request deadline.
- **Asynchronous handlers** return a `WorkflowHandle` to a workflow that produces the result. Up to **60 days** on Temporal Cloud.
- Choose sync when the work fits comfortably under five seconds. Choose async for everything else, especially anything that needs cancellation.
- Set all three timeouts (`schedule_to_close`, `schedule_to_start`, `start_to_close`) on every async caller. Use `WorkflowIDConflictPolicy.USE_EXISTING` for idempotent retries.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need to set all 3 timeouts, or would just schedule_to_close be sufficient in most cases?

Comment thread slides/chapters/wrap.md Outdated
<v-clicks>

- **Synchronous handlers** run inline on the handler Worker, return a result directly, and must respond within a **10-second** per-request deadline.
- **Asynchronous handlers** return a `WorkflowHandle` to a workflow that produces the result. Up to **60 days** on Temporal Cloud.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Asynchronous handlers** return a `WorkflowHandle` to a workflow that produces the result. Up to **60 days** on Temporal Cloud.
- **Asynchronous handlers** return a handle to obtain the result, cancel, and otherwise manage the async Operation. Up to **60 days** on Temporal Cloud.

We'll be supporting different types of async handlers in the future, not just WorkflowHandle, but for async updates, and generic async Nexus ops that are manually completed.

Comment thread slides/chapters/wrap.md
MasonEgger and others added 5 commits May 3, 2026 17:59
Co-authored-by: Phil Prasek <prasek@gmail.com>
Co-authored-by: Phil Prasek <prasek@gmail.com>
Co-authored-by: Phil Prasek <prasek@gmail.com>
Co-authored-by: Phil Prasek <prasek@gmail.com>
This commit picks up the non-verbatim portion of Phil Prasek's review
on PR #1. The verbatim-accept suggestions (Durable RPC rename,
async-match correction, INTERNAL parenthetical, evaluate link)
already landed in the four prior commits via GitHub's "Apply
suggestion" button.

## Reworded accepts

Three of Phil's suggestions were accepted in spirit but reworded to
fit the deck's slide register and the existing v-click rhythm.

- **Sync-handler external HTTP framing (ch03).** The "Avoid for
  arbitrary external HTTP" anti-pattern bullet is now Phil's
  prescriptive form: "For arbitrary external HTTP, back with a
  Workflow or Standalone Activity." Build 4 speaker note updated to
  match. The slide now points the room at the right tool instead of
  just naming the wrong one.
- **Endpoint reframed as "reverse proxy with a routing entry."** Phil
  pointed out that "routing rule" understates what an Endpoint is;
  it is a reverse proxy in the system architecture. Applied
  consistently across ch03's "What Is a Nexus Endpoint?" slide and
  speaker note, ch03's "Creating the Endpoint" slide and speaker
  note, and the matching Essential Points (1) bullet on the wrap.
  The DNS-entry mental model stays as the accessible analogy.
- **Async handlers stay generic on the wrap (Essential Points 2).**
  Replaced the specific `WorkflowHandle` reference with Phil's "a
  handle to obtain the result, cancel, and otherwise manage the
  async Operation." A new `## Teaching notes` block on the slide
  explains why the wrap stays abstract (more async handler shapes
  are on the Nexus roadmap: async Updates, manually-completed async
  ops) while ch04 and ch05 keep concrete `WorkflowHandle` framing.

## Speaker-note adds

Three of Phil's on-slide suggestions were rejected on the slide body
but added as verbal callouts in speaker notes. The on-slide claims
stay tight; Phil's substance lands aloud.

- **ch02 polyglot reassurance.** Build 4 sub-bullet on "What Is a
  Nexus Service?" now disambiguates "native types" from
  single-language: JSON wire format, optional proto defs, same data
  converters as the rest of Temporal. Polyglot is first-class.
- **ch03 trap-everything edge case.** "If asked" footnote under
  Build 5 of "When the Workers Aren't Running": a handler that
  catches every exception and returns a non-retryable error stays
  out of breaker territory even when it is busted. Pick error types
  deliberately. Teaching note credits Phil and warns not to
  introduce unprompted because it muddies the slide's main thesis
  ("watch your Worker fleet").
- **ch06 sync-only Nexus Updates today.** Build 5 sub-bullet on
  "Workflow Updates in 60 Seconds" anchors the actual 10s ceiling
  and the sync-only-today reality (async Nexus Updates with their
  own callback semantics for arbitrary duration are on the roadmap,
  not GA). Title stays unchanged; new Teaching note explains the
  "60 Seconds" is a pacing meta-phrase, not a duration claim.

## Roadmap-slide sharpening

`wrap.md` "What's Next for Nexus" Build 5 speaker note now uses
Phil's "single routing rule today" framing explicitly. Names the
multi-rule capability in flight (traffic-split, canary, per-caller
routing without standing up a new Endpoint). Replaces the previous
"one Endpoint maps to one (Namespace, Task Queue)" wording, which
was correct but lands less cleanly once the multi-rule capability
ships.

## Timeout narrow fix

Phil questioned whether the wrap's "Set all three timeouts" guidance
is actually how Temporal recommends configuring async Nexus callers.
He is right, and the docs MCP corroborates:
`docs.temporal.io/nexus/operations#timeouts` treats
`schedule_to_close_timeout` as the umbrella with retries inside;
`schedule_to_start` and `start_to_close` are explicitly opt-in ("if
not set or zero, no timeout is enforced") and require Temporal
Server 1.31.0 or later, flagged experimental in the Go SDK.

- **wrap.md Essential Points (2).** Bullet rewritten from "Set all
  three timeouts" to "Set `schedule_to_close_timeout` on every
  async caller. `schedule_to_start` and `start_to_close` are
  situational." Build 4 speaker note expanded with rationale
  sub-bullets explaining what schedule_to_close bounds and when to
  reach for the other two (known queue-pickup ceiling, per-attempt
  cap distinct from total time).
- **ch05 slide title.** "Three Timeouts You'll Actually Set" renamed
  to "Three Timeouts You May Set." Slide body still teaches all
  three (the room needs to know what each is), but the title now
  signals optionality and lines up with the wrap's framing.
- **ch05 exercise TODO 9 left alone** by design. The exercise sets
  all three so attendees see them in action; the slide title and
  the wrap make clear that production usually only sets
  `schedule_to_close`.

## Rejected on-slide

Documented for the record; no edits in this commit:

- **PR #8 (ch01).** Adding "Overly permissive security" as a fifth
  pain bullet on "What Goes Wrong as Teams Grow" pre-empts ch03's
  Cloud allowlist punchline (which Phil himself elevated as the key
  takeaway in his earlier PM-call guidance).
- **PR #10 (ch03:124).** Per-pair scope is already established
  three builds earlier on the same Circuit Breaker slide; the "Why
  a trip is bad" beat is meant to land impact, not re-explain
  scope.
- **PR #14 (ch07:273).** Per-pair scope reminder on the diagnostic
  slide is saturated; the room has heard it four times by ch07.

## Files modified

- `slides/chapters/ch02-service-contract.md`
- `slides/chapters/ch03-sync-handler.md`
- `slides/chapters/ch05-async-operations.md`
- `slides/chapters/ch06-updates.md`
- `slides/chapters/wrap.md`
@MasonEgger MasonEgger merged commit 1de2d35 into main May 4, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants