fix(client): contain notification-callback failures and document the source lifecycle
Review follow-ups: the three new notify loops (currentProvideInfo subscribers, ui-skill lexicon listeners, late-registration controller setup) now contain per-callback failures so one faulty consumer cannot starve the rest, abort the list projection pass, or poison the source roster with no disposer; controller lexicon polling drops a throwing source with a console record like the candidate path. The ui-slash README (both languages) now states the late-registration warm and the subscribeLexicon contract, and the scenario suite drives a typed /name token gaining its decoration when the roll settles with no further input.
This commit is contained in:
@@ -236,6 +236,35 @@ describe('scenario H: backspace breaks the token', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('scenario: reference decoration lights up when the lexicon settles', () => {
|
||||
it('a typed /name token gains the text-ref mark without further input once the roll goes hot', async () => {
|
||||
let roll: readonly string[] | undefined
|
||||
let notify: (() => void) | undefined
|
||||
const b = await scopedBench((slash) => {
|
||||
slash.registerSource({
|
||||
trigger: '/', name: 'skill',
|
||||
candidates: () => Promise.resolve([]),
|
||||
onPick: () => undefined,
|
||||
lexicon: () => roll,
|
||||
subscribeLexicon: (_session: ClientSessionContext, listener: () => void) => {
|
||||
notify = listener
|
||||
return () => { notify = undefined }
|
||||
},
|
||||
} as never)
|
||||
})
|
||||
// Typed before the catalog settled: a plain token, no decoration.
|
||||
b.type('/deploy now')
|
||||
expect(b.view.container.querySelector('[data-decoration="text-ref"]')).toBeNull()
|
||||
// The catalog settles (ui-skill's settle path fires the same notification).
|
||||
act(() => {
|
||||
roll = ['deploy']
|
||||
notify?.()
|
||||
})
|
||||
const mark = b.view.container.querySelector('[data-decoration="text-ref"]')
|
||||
expect(mark?.textContent).toBe('/deploy')
|
||||
})
|
||||
})
|
||||
|
||||
describe('scenario I: unknown /xyz + enter', () => {
|
||||
it('adjudication misses in one hop and the whole line rides the default sink', async () => {
|
||||
const b = await bench()
|
||||
|
||||
Reference in New Issue
Block a user