Add assertNever with closed-vs-extensible exhaustiveness guidance
assertNever (dsh-llm) marks unreachable defaults on CLOSED unions: adding a StreamChunk variant now breaks compilation at BlockAssembler.push, and a value escaping its type at runtime throws with diagnostics. The module doc and a new AGENTS.md convention spell out the dividing line: merge-extensible unions (SessionEventMap, ContentBlockMap, …) must NOT use assertNever — plugin-added variants are valid unknown values there; handle known cases and fall through with a comment.
This commit is contained in:
@@ -151,3 +151,18 @@ describe('BlockAssembler', () => {
|
||||
expect('usage' in result).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('assertNever', () => {
|
||||
it('throws with diagnostics when a value escapes a closed union at runtime', async () => {
|
||||
const { assertNever } = await import('@deepseek-ai/dsh-llm')
|
||||
expect(() => assertNever({ type: 'rogue' } as never, 'test-context'))
|
||||
.toThrow('unreachable variant in test-context: {"type":"rogue"}')
|
||||
expect(() => assertNever(undefined as never)).toThrow('unreachable variant: undefined')
|
||||
})
|
||||
|
||||
it('BlockAssembler.push rejects chunks outside the closed StreamChunk union', () => {
|
||||
const assembler = new BlockAssembler()
|
||||
expect(() => assembler.push({ type: 'rogue-chunk' } as unknown as StreamChunk))
|
||||
.toThrow('unreachable variant in BlockAssembler.push')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user