walkthrough · diff

git:20261103.1a2d262 to git:20261103.b1d65f9

33 added, 28 removed. Audit A to A.

---
name: walkthrough
- description: Use when the user wants a change or an existing flow explained or walked through, as a slide deck in execution order: a pull request by number or URL (including a team mate's), the current branch, the work just built in this session, or existing code as-is. Triggers include "walk me through this PR", "explain this change", "give me a tour of PR #123", "how does this flow work", "walk me through the auth flow". Explains the flow and the decisions behind it. Not a code review, and it does not test the user; for that use quiz-me.
+ description: Use when the user wants a change or an existing flow explained or walked through, step by step in execution order: a pull request by number or URL (including a team mate's), the current branch, the work just built in this session, or existing code as-is. Triggers include "walk me through this PR", "explain this change", "give me a tour of PR #123", "how does this flow work", "walk me through the auth flow". Explains the flow and the decisions behind it. Not a code review, and it does not test the user; for that use quiz-me.
---
# Walkthrough
- Explain a change as a short slide deck that follows the order the code **runs**, not the order of the diff: an overview diagram and slide map, then **one slide per message** from entry to exit, then a recap. The goal is understanding the flow and the decisions behind it. This is not a code review: no findings, bugs or style notes, and no grading of the user.
+ Explain a change step by step, in the order the code **runs**, not the order of the diff: an overview diagram and step map, then **one step per message** from entry to exit, then a recap. The goal is understanding the flow and the decisions behind it. This is not a code review: no findings, bugs or style notes, and no grading of the user.
- **Short choices** go through your harness's question tool when it has one (e.g. `AskUserQuestion` in Claude Code, `question` in OpenCode): one option per choice, so the user picks from a popup. Put the slide in the message text first; the popup carries only the options. No such tool: list the options as plain text and stop.
+ **Short choices** end the message as a numbered plain-text list, after the content; then stop. The user replies with a number or in their own words. Every message here carries content above its choice, so it all stays in the message text: a question-tool popup can hide the text before it.
## 1. Gather silently
Scope, in this order:
- **A PR** (number or URL): run `gh pr view <n>` for the description **and**, separately, `gh pr view <n> --comments` (it omits the description). Then `gh pr diff <n>` and the full changed files at the head (`git fetch origin pull/<n>/head`, then `git show <sha>:<path>`). The PR need not be checked out.
- **A topic or file** ("the request flow"): if nothing in this session or branch touched it, walk through the **code as-is** (section 7) without asking. If changes touch it, ask: the changes or the code as-is?
- **Otherwise** this session's work, or the branch: base is `git merge-base HEAD main`, else `master`, else `origin/HEAD`; then `git diff <base>..HEAD`. If the branch has an open PR (`gh pr view --json number`), treat it as that PR.
- Then **read beyond the diff**. Follow the flow outward until you reach the entry point(s) and the exit(s): callers of changed functions, interfaces they implement, config and defaults they rely on, consumers of anything they publish or enqueue. Unchanged code that links the changed parts belongs in the deck.
+ Then **read beyond the diff**. Follow the flow outward until you reach the entry point(s) and the exit(s): callers of changed functions, interfaces they implement, config and defaults they rely on, consumers of anything they publish or enqueue. Unchanged code that links the changed parts belongs in the walkthrough.
- **Why** comes only from sources: this session's rejected alternatives, the PR description and comments, why-comments, ADRs, linked issues. Credit the source on the slide ("PR description: …"). For anything else, write **"my read:"**. Never present your guess as the author's reasoning.
+ **Why** comes only from sources: this session's rejected alternatives, the PR description and comments, why-comments, ADRs, linked issues. Credit the source in the step ("PR description: …"). For anything else, write **"my read:"**. Never present your guess as the author's reasoning.
## 2. Find the flow
- - Entry points: HTTP handler or middleware, CLI command, scheduled job, message consumer, UI event, migration run. Slide 1 of a track is the first code that handles the input (e.g. the middleware). Startup wiring in `main` is never slide 1: show its changed lines on the slide of the part it builds.
- - Order slides by execution: entry → processing → exit (response, write, published event). Async: producer → queue → consumer → side effect, even across processes.
- - **Tracks** follow entry points, not topics. One runtime path (request → limiter → handler → queue → consumer → store) is one track, even when it changes for several reasons. A new command, job or endpoint with its own entry point is its own track. Two or more: every track gets its own slides, under a `Track A · …` / `Track B · …` line in the map, each in execution order.
- - Config, wiring, schema migrations, feature flags: on the slide of the code that first uses them (a migration goes with the code that writes the column). Never a slide of their own.
- - Tests: one "How this is proven" slide near the end. Mechanical changes (version bump, renames, formatting, lock files): one final "Other changes" slide, or the recap's **Not covered** list.
- - Every changed file is on a slide or in **Not covered**. Never drop one silently.
- - Aim for 4–10 slides. **Trivial change** (typo, one-line doc, rename): say it is trivial and offer a one-message summary instead of a deck (**Summary** / **Deck anyway**). Stop.
+ - Entry points: HTTP handler or middleware, CLI command, scheduled job, message consumer, UI event, migration run. Step 1 of a track is the first code that handles the input (e.g. the middleware). Startup wiring in `main` is never step 1: show its changed lines in the step of the part it builds.
+ - Order steps by execution: entry → processing → exit (response, write, published event). Async: producer → queue → consumer → side effect, even across processes.
+ - **Tracks** follow entry points, not topics. One runtime path (request → limiter → handler → queue → consumer → store) is one track, even when it changes for several reasons. A new command, job or endpoint with its own entry point is its own track. Two or more: every track gets its own steps, under a `Track A · …` / `Track B · …` line in the map, each in execution order.
+ - Config, wiring, schema migrations, feature flags: in the step of the code that first uses them (a migration goes with the code that writes the column). Never a step of their own.
+ - Tests: one "How this is proven" step near the end. Mechanical changes (version bump, renames, formatting, lock files): one final "Other changes" step, or the recap's **Not covered** list.
+ - Every changed file is in a step or in **Not covered**. Never drop one silently.
+ - Aim for 4–10 steps. **Trivial change** (typo, one-line doc, rename): say it is trivial and offer a one-message summary instead of a walkthrough (**Summary** / **Walkthrough anyway**). Stop.
- ## 3. Check claims before they go on a slide
+ ## 3. Check claims before they go in a step
- A claim about behavior outside the changed code needs a source you read now: library defaults at the version pinned in the lock file, chart values, API specs, framework behavior. When the change builds a client and leaves options unset, those defaults *are* its behavior: before the overview, read them in the library source at the pinned version (module cache, vendor dir, or the tag upstream) and put them on that client's slide. Memory is not a source. Name the source on the slide ("HTTP client v2.3.1 `options.go`: retries 3"). Can't read it: drop the claim, or write "(unchecked)" next to it. The same holds for answers during **Dig deeper**.
+ A claim about behavior outside the changed code needs a source you read now: library defaults at the version pinned in the lock file, chart values, API specs, framework behavior. When the change builds a client and leaves options unset, those defaults *are* its behavior: before the overview, read them in the library source at the pinned version (module cache, vendor dir, or the tag upstream) and put them in that client's step. Memory is not a source. Name the source in the step ("HTTP client v2.3.1 `options.go`: retries 3"). Can't read it: drop the claim, or write "(unchecked)" next to it. The same holds for answers during **Dig deeper**.
## 4. Open with the overview
One message, in this order, then stop:
1. **Also read:** one line naming the unchanged code you read beyond the diff (e.g. "Also read: the middleware that calls the limiter, the queue consumer").
2. **Diagram:** a Mermaid `flowchart` (or `sequenceDiagram` when call order between a few parties is the point), at most ~10 nodes. Mark changed parts with `classDef changed`. Never put `;` in a label.
- 3. **Slide map**, exactly in this form.
+ 3. **Step map**, exactly in this form.
4. The short choice **Start**.
```mermaid
flowchart LR
client([Client]) --> mw[Rate limit middleware]
mw --> bucket[Token bucket]
bucket --> redis[(Redis)]
mw --> handler[Order handler]
classDef changed fill:#fde68a,stroke:#b45309
class bucket,handler changed
```
```
WALKTHROUGH · rate limiter
Track A · POST /orders
▶ 1. Request enters the middleware entry
○ 2. Take a token from the bucket changed
○ 3. Counters in Redis context
○ 4. Reject with 429 exit
Track B · admin reset-limits
○ 5. Reset one client's bucket entry
○ 6. How this is proven tests
✓ seen ▶ now ○ to come
then: recap → parked questions → quiz-me
```
- Right-column kinds: `entry`, `changed`, `context` (unchanged code needed to follow the flow), `step`, `exit`, `tests`. Changed files you plan to leave off the slides go on a `not covered:` line under the map.
+ Right-column kinds: `entry`, `changed`, `context` (unchanged code needed to follow the flow), `logic`, `exit`, `tests`. Changed files you plan to leave out of the steps go on a `not covered:` line under the map.
- ## 5. One slide per message
+ ## 5. One step per message
````
- **Slide 2 of 6 · Take a token from the bucket**
+ **Step 2 of 6 · Take a token from the bucket**
Flow: Client → Middleware → **Token bucket** → Redis
`limiter/bucket.go:40-52` · changed
```diff
func (b *Bucket) Take(ctx context.Context, key string) (bool, error) {
+ n, err := b.store.Decr(ctx, key)
+ if err != nil {
+ return true, err ◀ fails open
+ }
```
**What happens:** 1–3 sentences.
**Why:** 1–3 sentences, with the source, or "my read: …".
+
+ 1. **Next step**
+ 2. **Dig deeper**
+ 3. **Park it**
+ 4. **Skip to recap**
````
- Changed code: a `diff` block from the PR diff. Unchanged code: a plain fenced block with the language, headed `path:line · context`.
- About 15 lines per excerpt at most. Elide with `…`. Mark the line that matters with `◀`.
- - No slide map on slides; the `Flow:` breadcrumb shows the position.
- - End with the short choice, then stop. Never start the next slide in the same message:
- - **Next slide**
- - **Dig deeper** — free back-and-forth on this step. Answer only; no next slide until the user asks.
+ - No step map in a step; the `Flow:` breadcrumb shows the position.
+ - End with the short choice, then stop. Never start the next step in the same message:
+ - **Next step**
+ - **Dig deeper** — free back-and-forth on this step. Answer only; no next step until the user asks.
- **Park it** — note the question. Say it is parked; answer it after the recap, not now.
- **Skip to recap**
- A question mid-deck ("where is this called from?") is a dig deeper: answer it, and if the answer belongs in the flow, add a slide to the map and say so.
+ A question mid-walkthrough ("where is this called from?") is a dig deeper: answer it, and if the answer belongs in the flow, add a step to the map and say so.
## 6. Recap, parked questions, hand-off
- 1. The slide map: seen slides `✓`, skipped ones left `○`.
+ 1. The step map: seen steps `✓`, skipped ones left `○`.
2. **The flow** in 3–5 lines.
3. **Key decisions:** 2–4, each with its source or "my read".
- 4. **Not covered:** changed files not on any slide, if any.
+ 4. **Not covered:** changed files not in any step, if any.
5. **Parked:** answer each parked question now.
6. The short choice: **Run `quiz-me` now (recommended)** on the same scope (it reads this walkthrough from the conversation), or **Done**.
## 7. Code as-is
- For a flow nobody changed: same steps, with these differences.
- - No `changed` class in the diagram. Kinds are only `entry`, `step`, `context`, `exit` (`tests` only if the tests explain the flow).
- - The rule that every changed file is on a slide or in **Not covered** does not apply.
+ For a flow nobody changed: same sections, with these differences.
+ - No `changed` class in the diagram. Kinds are only `entry`, `logic`, `context`, `exit` (`tests` only if the tests explain the flow).
+ - The rule that every changed file is in a step or in **Not covered** does not apply.
- All code in plain fenced blocks with `path:line`. No `diff` blocks.
- The scope is the flow the user named. Say in the overview where the walkthrough stops (e.g. "stops at the in-memory store").
- **Why** comes from why-comments, docs, ADRs, and `git log` / `git blame` on the key lines. Else "my read".