test: fix CI coverage + e2e for user/message coalescing

- tui.spec: exercise a goal-sourced injected context card (labels by
  source kind, not plugin name), closing the last uncovered branch in
  tui/src/index.ts that the CI coverage gate caught.
- time-context.e2e / goal.e2e: filter injected context by source now
  that it is a user/message (plugin/goal source), and count goal
  continuation rounds by round>0 rather than event type.
This commit is contained in:
Turtle
2026-07-23 22:57:39 +08:00
parent d5f88f1221
commit 7b7f793ee5
3 changed files with 9 additions and 2 deletions
@@ -48,7 +48,8 @@ describe('time-context through a real headless cordis.yml', () => {
expect(stderr).not.toContain('UNHANDLED')
expect(events.filter(event => event.type === 'turn/end')).toHaveLength(2)
const contexts = events.filter(event => event.type === 'user/message')
const contexts = events.filter(
(event): event is SessionEvent<'user/message'> => event.type === 'user/message' && event.data.source.kind === 'plugin')
const starts = events.filter(event => event.type === 'step/start')
expect(contexts).toHaveLength(2)
expect(starts).toHaveLength(2)
+3 -1
View File
@@ -69,7 +69,9 @@ describe('goal domain through a real cordis.yml and headless process', () => {
})
expect(context.data.content).toEqual(renderGoalChange(change))
expect(JSON.stringify(context)).not.toContain('activation')
// No admitted continuation round ran (the snapshot mounts without starting
// a round); the round-zero state change from create is expected above.
expect(events.filter(event => event.type === 'user/message'
&& event.data.source.kind === 'goal')).toHaveLength(0)
&& event.data.source.kind === 'goal' && event.data.source.round > 0)).toHaveLength(0)
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
})
+4
View File
@@ -395,6 +395,9 @@ describe('pi-tui chat lifecycle and transcript', () => {
result.session.append('steering/message', { turn: 2, content: [{ type: 'text', text: '' }], source: { kind: 'user' } }, { surfaceOp: 'append' })
result.session.append('user/message', { content: [{ type: 'text', text: 'user context' }], source: { kind: 'plugin', plugin: 'ctx' } }, { surfaceOp: 'append' })
result.session.append('user/message', { content: [{ type: 'text', text: '' }], source: { kind: 'plugin', plugin: 'ctx' } }, { surfaceOp: 'append' })
// A non-plugin injected source (goal) has no `plugin` field, so its context
// card label falls back to the source kind.
result.session.append('user/message', { content: [{ type: 'text', text: 'goal context' }], source: { kind: 'goal', goalId: 'g1', revision: 1, round: 0 } as never }, { surfaceOp: 'append' })
result.session.append('prompt/blocked', { content: [{ type: 'text', text: 'blocked' }], source: { kind: 'user' }, reason: 'test policy' })
appendAssistant(result.session, [])
result.session.append('step/end', { turn: 1, step: 1 })
@@ -475,6 +478,7 @@ describe('pi-tui chat lifecycle and transcript', () => {
expect(result.terminal.output).toContain('Enter sends steering, Esc cancels')
expect(result.terminal.output).toContain('Steering')
expect(result.terminal.output).toContain('user context')
expect(result.terminal.output).toContain('Context · goal') // goal-sourced injected context labels by kind
expect(result.terminal.output).toContain('Prompt blocked')
expect(result.terminal.output).toContain('Turn cancelled')
expect(result.terminal.progress).toContain(true)