Source: c77 session-view — four-altitude anatomy over scenario fixtures, 2026-08-20
One session, four altitudes: receipt → chapters → turns → raw events. The hypothesis under test: transcript, trace, story, and footprint aren't competing framings — they're altitudes of the same object, and the design problem is the ladder between them. Every beat below is mechanically derived (role + adjacency + decision events) — no LLM classifies anything. Switch the scenario; the whole ladder follows.
Webhook retry logic — implement, test, PR
Claude Code · claude-sonnet-4-5 · marissa@acme.dev · 2026-08-18 14:02Z · 17m 32sReceipt
The compliance altitude — one page answering what ran, as whom, what it touched, what was blocked, what it cost. Exportable evidence; zero interaction required.
2026-08-18 14:02Z · 17m 32s
Chapters
The skim altitude — the session as ask→outcome brackets, each wearing its beat spine. Titles are the asks themselves; nothing is summarized. Read the glyphs before any text: the spine is the story.
Turns — the semantic transcript
The reading altitude — full dialogue text, machinery collapsed into action bursts (click to open), violations and errors surfaced in place. The spine down the left is the same glyph vocabulary as the chapters — skim the spine, dive on demand.
Add retry with exponential backoff to the webhook dispatcher, and cover it with tests.
I'll read the dispatcher and its queue first to see where delivery failures surface.
Failures throw DeliveryError from deliver(). Plan: wrap deliver() in a retry helper with exponential backoff + jitter, cap at 5 attempts, then dead-letter.
Retry helper in place — exponential backoff with jitter, 5-attempt cap, dead-letter on exhaustion. 14 dispatch tests pass (the first run caught a fake-timer gap in the jitter test).
Also make the max attempts configurable via env.
Adding WEBHOOK_RETRY_MAX to config with a validated default of 5, threading it into the retry helper.
WEBHOOK_RETRY_MAX added (default 5, validated 1–10), documented in .env.example. 17 tests pass.
Great — open a PR.
Creating a branch, committing, and opening the PR via the GitHub MCP server.
PR #4182 opened: "Webhook dispatcher: exponential-backoff retry with configurable cap." Two files added, three modified, 17 tests green.
Raw events
The forensic altitude — every event as observed, nothing collapsed, nothing derived. This is the qdash events table grain; everything above is computed from exactly this list.
| # | t+ | Type | Event |
|---|---|---|---|
| 1 | 0:00 | mcp_lifecycle | init github |
| 2 | 0:01 | mcp_lifecycle | list_tools github — 14 tools |
| 3 | 0:08 | message | user: Add retry with exponential backoff to the webhook dispatcher, and cover it with tests. |
| 4 | 0:14 | message | assistant: I'll read the dispatcher and its queue first to see where delivery failures surface. |
| 5 | 0:14 | llm_response | claude-sonnet-4-5 · 4.3k tok · $0.03 · 3210ms |
| 6 | 0:16 | file_access | read src/dispatch/webhook.ts |
| 7 | 0:17 | file_access | read src/dispatch/queue.ts |
| 8 | 0:19 | tool_call | builtin Grep — ok — deliver( in src/ |
| 9 | 0:22 | tool_call | builtin Read — ok — src/dispatch/errors.ts |
| 10 | 0:30 | message | assistant: Failures throw DeliveryError from deliver(). Plan: wrap deliver() in a retry helper with… |
| 11 | 0:30 | llm_response | claude-sonnet-4-5 · 10.3k tok · $0.06 · 5480ms |
| 12 | 0:41 | file_access | create src/dispatch/retry.ts |
| 13 | 0:55 | file_access | write src/dispatch/webhook.ts |
| 14 | 1:10 | file_access | create test/dispatch/retry.test.ts |
| 15 | 1:24 | tool_call | builtin Bash — failed — npm test -- dispatch |
| 16 | 1:24 | llm_response | claude-sonnet-4-5 · 12.5k tok · $0.05 · 6120ms |
| 17 | 1:41 | file_access | write test/dispatch/retry.test.ts — fake timers for jitter |
| 18 | 1:52 | tool_call | builtin Bash — ok — npm test -- dispatch |
| 19 | 1:52 | llm_response | claude-sonnet-4-5 · 14.1k tok · $0.04 · 4890ms |
| 20 | 2:06 | message | assistant: Retry helper in place — exponential backoff with jitter, 5-attempt cap, dead-letter on ex… |
| 21 | 2:06 | llm_response | claude-sonnet-4-5 · 14.5k tok · $0.03 · 3020ms |
| 22 | 3:34 | message | user: Also make the max attempts configurable via env. |
| 23 | 3:39 | message | assistant: Adding WEBHOOK_RETRY_MAX to config with a validated default of 5, threading it into the r… |
| 24 | 3:39 | llm_response | claude-sonnet-4-5 · 15.1k tok · $0.03 · 2410ms |
| 25 | 3:46 | file_access | write src/config.ts |
| 26 | 3:53 | file_access | write src/dispatch/retry.ts |
| 27 | 3:58 | file_access | write .env.example |
| 28 | 4:07 | tool_call | builtin Bash — ok — npm test -- dispatch config |
| 29 | 4:07 | llm_response | claude-sonnet-4-5 · 16.3k tok · $0.04 · 3350ms |
| 30 | 4:18 | message | assistant: WEBHOOK_RETRY_MAX added (default 5, validated 1–10), documented in .env.example. 17 tests… |
| 31 | 4:18 | llm_response | claude-sonnet-4-5 · 16.6k tok · $0.03 · 2100ms |
| 32 | 5:22 | message | user: Great — open a PR. |
| 33 | 5:27 | message | assistant: Creating a branch, committing, and opening the PR via the GitHub MCP server. |
| 34 | 5:27 | llm_response | claude-sonnet-4-5 · 16.9k tok · $0.02 · 1980ms |
| 35 | 5:33 | tool_call | builtin Bash — ok — git checkout -b webhook-retry && git commit |
| 36 | 5:41 | tool_call | mcp github·create_pull_request — ok — acme/platform #4182 |
| 37 | 5:41 | egress | api.github.com — allow |
| 38 | 5:52 | message | assistant: PR #4182 opened: "Webhook dispatcher: exponential-backoff retry with configurable cap." T… |
| 39 | 5:52 | llm_response | claude-sonnet-4-5 · 17.4k tok · $0.03 · 2540ms |
| 40 | 17:32 | mcp_lifecycle | close github |