Teardown safety & ctx.state authoring channel (0.10.0)#25
Merged
Conversation
Second umami dogfooding pass (on 0.9.0) surfaced a setup/teardown lifecycle cluster plus the ergonomic gap per-tutorial setup opened. Shipped as 0.10.0. Bug fixes (teardown coverage): - #15 setup-phase failures (adapter.setup / tutorial.setup) now run the full teardown chain before rethrowing, instead of leaking seeded data - #16 preview runs the full teardown chain on every exit path, not just step thunks — no more orphaned adapter seed on the run-repeatedly iterate tool - #20 a failed render with contactSheet on emits a partial sheet (completed steps + the failure frame), the at-a-glance view you most want on failure - #21 widen onTeardown return type to () => unknown | Promise<unknown> Additive API: - #17 typed ctx.state: adapter.setup's return lands on ctx.state, read by tutorial.setup and steps — replaces the module-global + `!` handoff; typed end-to-end via TutorialAdapter<S> / tutorial<S> / step<S> - #19 doctor --setup / probeAdapterSetup: actually run adapter.setup and tear it down, catching the reachable-but-wrong-database class of failure Docs (#18, #23): networkidle/startTransition caveat + waitFor guidance; ctx.state section and a teardown-coverage matrix in adapters.md. Tests (#22): runTeardownChain extracted as the single teardown entry point for record/preview/doctor; new unit suite (step-hooks.test.ts) and e2e assertions for setup-failure teardown, preview teardown, ctx.state handoff, probeAdapterSetup, and the partial failure contact sheet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 13, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses the second umami dogfooding pass (issues filed against 0.9.0). Six of seven issues cluster around the setup/teardown lifecycle #8 introduced — a correctness hole (leaked seed data) and an ergonomic hole (no adapter→tutorial state channel). Released as 0.10.0 (minor: includes additive API).
Bug fixes (teardown coverage)
adapter.setup/tutorial.setupfailures now run the full teardown chain before rethrowing, instead of leaking everything seeded before the throw.ctx.onTeardownregistered insetup()finally means what it looks like.previewruns the full teardown chain (step thunks → tutorial → adapter) on every exit path, not just step thunks. It's the run-repeatedly iterate tool, so the old behavior quietly filled the shared test DB.--contact-sheetnow emits a partial sheet (completed steps + the failure frame as the last cell). Never masks theStepError.onTeardownreturn type widened to() => unknown | Promise<unknown>, so() => Promise.all(...)typechecks.Additive API
ctx.state:adapter.setup's return value lands onctx.state, read bytutorial.setupand steps. Replaces the module-global +!-assertion handoff with a per-render, parallel-safe bag, typed end-to-end viaTutorialAdapter<S>/tutorial<S>/step<S>.tutorial-forge doctor --setup(andprobeAdapterSetup(adapter)) actually runadapter.setupand tear it down, catching the reachable-but-wrong-database failure class. Off by default.Docs
networkidleracesstartTransition-deferred Server Actions and steers towaitFor. The deferred code half (a React-idle settle) is split to React-idle settleUntil variant (deferred from #18) #24.ctx.statesection + teardown-coverage matrix inadapters.md.Design note
#15/#16/#19 all needed "run the teardown chain safely," so
runTeardownChain()was extracted intopipeline/step-hooks.tsas the single entry point for record, preview, and the doctor probe.Tests (#22)
packages/core/test/step-hooks.test.ts: teardown-chain ordering (LIFO), keeps-going-on-failure, value-returning thunks, typed-state compile check.ctx.statehandoff,probeAdapterSetup(success + failure-still-tears-down), partial failure contact sheet.Verification
pnpm build+pnpm typecheck(core, cli, example-app) clean ·pnpm test(97 unit tests) green ·pnpm e2egreen. Code-reviewed: no must-fix findings; double-close / error-swallow / browser-cleanup / sheet-masking-StepError all verified correct.Closes #15, #16, #17, #19, #20, #21, #22, #23. Addresses #18 (docs); code half tracked in #24.
🤖 Generated with Claude Code