Files
deepseek-harness/packages/interaction/permission/tests/invariant.spec.ts
Tianyi Cui 3fc35c91ff refactor(packages): dissolve ui/ and rename sdk/ to scaffold/
git mv per the regrouping RFC: the five human-collaboration seams and
tui join packages/interaction/, app-boot becomes packages/boot/, and
jsonrpc joins the renamed scaffold/ (formerly sdk/) as its server half
beside client/protocol/create-sdk/helper/scripts/telemetry, whose
folders drop the legacy sdk- prefix. Three new group README triplets
replace the ui/ and sdk/ ones; tsconfig references/paths/globs,
knip keys, vitest globs, gate scripts, catalogs, docs, and the
lockfile follow. Adds the four settled FIXME rename markers
(dsh-sdk-server, dsh-sdk-telemetry, dsh-sdk-helper, dsh-sdk-scripts).

The scaffold folders diverge from their npm names until those renames
land, so tsconfig.base.json maps the three affected names explicitly
beside the group wildcard. Also repairs two pre-existing stale-path
classes the strengthened sweep surfaced: docs/web-styling.md's retired
web-ui host package and type-model spec fixture-literal joins.

app-boot's three Loader-composition specs time out at the default 5s
under full-suite parallel load on this filesystem (pre-existing;
pass isolated with --testTimeout=30000); interaction/scaffold/boot
suites otherwise green (687 passed).
2026-08-09 01:21:12 +08:00

54 lines
2.0 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { Context, Service } from 'cordis'
import SessionStore, { type Session, type SessionEvent } from '@deepseek-ai/dsh-session'
import * as PermissionInvariant from '@deepseek-ai/dsh-permission/invariant'
import InvariantService from '@deepseek-ai/dsh-invariants'
class PermissionProbe extends Service {
readonly names = ['safe', 'trusted']
constructor(ctx: Context) {
super(ctx, 'permission')
}
}
async function setup(): Promise<Context> {
const ctx = new Context()
await ctx.plugin(SessionStore)
await ctx.plugin(PermissionProbe)
await ctx.plugin(InvariantService, { enabled: true })
await ctx.plugin(PermissionInvariant)
return ctx
}
function presetEvent(preset: string): SessionEvent {
return { type: 'permission/preset', seq: 0, time: 0, data: { preset } }
}
describe('permission invariants', () => {
it('accepts configured preset events and ignores other session data', async () => {
const ctx = await setup()
expect(() => { ctx.emit('session/event', {} as Session, presetEvent('safe')) }).not.toThrow()
expect(() => { ctx.emit('session/event', {} as Session, {
type: 'turn/end', seq: 0, time: 0, data: {},
} as SessionEvent) }).not.toThrow()
expect(() => { ctx.emit('tools/change') }).not.toThrow()
})
it('rejects a durable preset that the active table cannot resolve', async () => {
const ctx = await setup()
expect(() => { ctx.emit('session/event', {} as Session, presetEvent('missing')) })
.toThrow(/unknown preset "missing"/)
})
it('rejects an unknown preset already present on late registration', async () => {
const ctx = new Context()
await ctx.plugin(SessionStore)
await ctx.plugin(PermissionProbe)
ctx.sessions.create().append('permission/preset', { preset: 'missing' })
await ctx.plugin(InvariantService, { enabled: true })
await expect(ctx.plugin(PermissionInvariant).then(() => undefined)).rejects.toThrow(/unknown preset "missing"/)
})
})