💥 Rename DurableCtx to DurableContext - #409
Conversation
The repository spells `Context` out in identifiers, and `DurableCtx` was the
last exported holdout. It now shares its name with the `DurableContext`
interface it carries — a value and a type occupy separate declaration spaces —
so a scope read states its subject once: `scope.get(DurableContext)` and
`scope.expect<DurableContext>(DurableContext)`.
The context key is untouched. `createContext("@effection/durable")` still
names the same context, and Effection identifies a context by that string, so
the state a running workflow observes is the state it observed before. What
changes is the export: `@executablemd/durable-streams` no longer exports
`DurableCtx`, which is a breaking change for anyone reading the context
directly.
`mod.ts` re-exports the name once, without `export type`, because a value
re-export carries every meaning of the name; splitting it would leave the type
exported and the context unreachable. The new `context.test.ts` runs a
workflow that reads its own state through the exported value and returns the
coroutine id `durableRun` assigned it, so dropping the value export fails the
typecheck rather than passing silently.
Co-authored-by: Taras Mankovski <74687+taras@users.noreply.github.com>
PR #409: 💥 Rename DurableCtx to DurableContext12 files, +60 / -34 Scope✅ PR scope looks good. StructuralOxlint structural signals:
Slop✅ Slop indicators look low. Static AnalysisOxlint: 23 diagnostics across 4 files (8 rules) no-unsafe-type-assertion (9): packages/durable-streams/combinators.ts, packages/core/src/execute.ts, packages/durable-streams/run.ts CorrectnessNo extraneous code patterns detected. |
Closes #268.
Why
This repository spells
Contextout in identifiers —DurableContext,ReviewContext, or the unsuffixed house style (Staging,ActiveLoop).DurableCtxwas the last exported holdout, and it sat next to theDurableContextinterface it carries, so every read named the same subject twice under two spellings.What changes
The exported Effection context in
@executablemd/durable-streamsis namedDurableContext, sharing the name with the interface it holds — a value and a type occupy separate declaration spaces, the same shapeSymbolhas.Before:
After:
How it works
The context key is untouched:
createContext<DurableContext>("@effection/durable")still names the same context, and Effection identifies a context by that string rather than by the binding that holds it. A running workflow observes exactly the state it observed before.mod.tsre-exports the name once, as a value re-export rather than aexport { … }/export type { … }pair, because a value re-export carries every meaning of the name. Splitting it back into two lines would collide on the identifier; keeping only theexport typeline would leave the type exported and the context itself unreachable.Review guide
Start with:
packages/durable-streams/context.tsThen review:
packages/durable-streams/mod.ts— the public surface, now one line instead of twopackages/durable-streams/{effect,combinators,run}.ts— the internal readers and the one writerpackages/core/src/loop.ts— the only consumer outside the package that reads the contextpackages/durable-streams/tests/context.test.ts— the coverage the export previously had none ofWhat must stay true
"@effection/durable"— nothing in this diff touches thecreateContextargument, so durable state installed by one loaded copy stays visible to another.DurableContextremains reachable as a value from@executablemd/durable-streams— checked bypackages/durable-streams/tests/context.test.ts, which fails to typecheck if the export narrows back toexport type.How to verify it
context.test.tsruns a workflow underdurableRunthat reads its own state through the exportedDurableContext, asserts the stream and child counter it was given, and returns the coroutine iddurableRunassigned it (root.7). It fails if the value export is dropped, and it fails ifdurableRunstops installing the context on the workflow scope.export { DurableContext }withexport type { DurableContext }inmod.tsmakes that test fail type-checking ('DurableContext' was exported hereatmod.ts:62), confirming the test is not vacuous.Local verification on this commit:
deno task lint— 0 errors, formatting cleandeno task check— exit 0deno task check:jsr—Success Dry run completedeno task test --changed=origin/main— 301 passed (2235 steps), 0 failednpx tsc --project tsconfig.node.json— exit 0Scope
Included
packages/core.specs/executable-mdx-spec.md,specs/decisions.md, and the two documents underpackages/durable-streams/specs/.Intentionally unchanged
"@effection/durable"— renaming it would be a behavioral break, not a naming one.ctx,parentCtx, andchildCtx. They are not exported, and the issue scopes this PR to the exported name and its call sites.TestAgentCtx, which the TestAgent migration slice renames.Generated or mechanical changes
specs/andpackages/durable-streams/specs/are identifier substitutions with no other edits.Risks and limitations
DurableCtxis gone from the published surface of@executablemd/durable-streams. No consumer inside this repository referenced it outside the files changed here. Recovery for an external consumer is a one-word rename at the import site.Scope confirmation