@company-semantics/contracts 0.93.0 → 0.94.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { CHAT_RUNTIME_PROFILES, DEFAULT_CHAT_RUNTIME_PROFILE } from '../runtime-profile.js'
|
|
3
|
+
|
|
4
|
+
describe('CHAT_RUNTIME_PROFILES golden snapshot', () => {
|
|
5
|
+
it('exact values are frozen', () => {
|
|
6
|
+
expect(CHAT_RUNTIME_PROFILES).toStrictEqual([
|
|
7
|
+
{ id: 'fast', label: 'Fast', description: 'Single-step, no tools', model: 'gpt-3.5-turbo' },
|
|
8
|
+
{ id: 'balanced', label: 'Balanced', description: 'Multi-step with tools', model: 'gpt-4o' },
|
|
9
|
+
{ id: 'agentic', label: 'Agentic', description: 'Agent loop, full reasoning', model: 'claude-sonnet-4-20250514' },
|
|
10
|
+
])
|
|
11
|
+
})
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
describe('CHAT_RUNTIME_PROFILES invariants', () => {
|
|
15
|
+
it('covers all ChatRuntimeProfile values', () => {
|
|
16
|
+
const ids = CHAT_RUNTIME_PROFILES.map(p => p.id)
|
|
17
|
+
expect(ids).toContain('fast')
|
|
18
|
+
expect(ids).toContain('balanced')
|
|
19
|
+
expect(ids).toContain('agentic')
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('has no duplicate profile IDs', () => {
|
|
23
|
+
const ids = CHAT_RUNTIME_PROFILES.map(p => p.id)
|
|
24
|
+
expect(new Set(ids).size).toBe(ids.length)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('all entries have non-empty label and description', () => {
|
|
28
|
+
for (const profile of CHAT_RUNTIME_PROFILES) {
|
|
29
|
+
expect(profile.label.length).toBeGreaterThan(0)
|
|
30
|
+
expect(profile.description.length).toBeGreaterThan(0)
|
|
31
|
+
}
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('all entries have non-empty model strings', () => {
|
|
35
|
+
for (const profile of CHAT_RUNTIME_PROFILES) {
|
|
36
|
+
expect(profile.model.length).toBeGreaterThan(0)
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('DEFAULT_CHAT_RUNTIME_PROFILE', () => {
|
|
42
|
+
it('is agentic', () => {
|
|
43
|
+
expect(DEFAULT_CHAT_RUNTIME_PROFILE).toBe('agentic')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('exists in CHAT_RUNTIME_PROFILES', () => {
|
|
47
|
+
const ids = CHAT_RUNTIME_PROFILES.map(p => p.id)
|
|
48
|
+
expect(ids).toContain(DEFAULT_CHAT_RUNTIME_PROFILE)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('is a valid ChatRuntimeProfile value', () => {
|
|
52
|
+
const validIds = CHAT_RUNTIME_PROFILES.map(p => p.id) as readonly string[]
|
|
53
|
+
expect(validIds).toContain(DEFAULT_CHAT_RUNTIME_PROFILE)
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -172,7 +172,7 @@ describe('applyIntent', () => {
|
|
|
172
172
|
expect(applyIntent('undone', 'confirm')).toBe('conflict')
|
|
173
173
|
})
|
|
174
174
|
|
|
175
|
-
it('pending_confirmation + reject
|
|
175
|
+
it('pending_confirmation + reject resolves as approve (rejection uses same cancel path)', () => {
|
|
176
176
|
expect(applyIntent('pending_confirmation', 'reject')).toBe('approve')
|
|
177
177
|
})
|
|
178
178
|
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { WireSurfaceBuilder } from '../wire.js'
|
|
3
|
+
import type { ExecutionResultData } from '../execution.js'
|
|
4
|
+
import type { UndoResultData } from '../execution.js'
|
|
5
|
+
|
|
6
|
+
describe('WireSurfaceBuilder.toolList', () => {
|
|
7
|
+
it('returns data part with type data-tool-list', () => {
|
|
8
|
+
const tools = [{ name: 'search', description: 'Search tool', inputSchema: {} }] as any
|
|
9
|
+
const result = WireSurfaceBuilder.toolList(tools)
|
|
10
|
+
expect(result.type).toBe('data-tool-list')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('data.tools matches input array exactly', () => {
|
|
14
|
+
const tools = [
|
|
15
|
+
{ name: 'search', description: 'Search tool', inputSchema: {} },
|
|
16
|
+
{ name: 'fetch', description: 'Fetch tool', inputSchema: { type: 'object' } },
|
|
17
|
+
] as any
|
|
18
|
+
const result = WireSurfaceBuilder.toolList(tools)
|
|
19
|
+
expect(result.data.tools).toEqual(tools)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('works with empty tools array', () => {
|
|
23
|
+
const result = WireSurfaceBuilder.toolList([])
|
|
24
|
+
expect(result.type).toBe('data-tool-list')
|
|
25
|
+
expect(result.data.tools).toEqual([])
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
describe('WireSurfaceBuilder.executionResult', () => {
|
|
30
|
+
const data: ExecutionResultData = {
|
|
31
|
+
actionId: 'act-1',
|
|
32
|
+
executionId: 'exec-001',
|
|
33
|
+
state: 'completed',
|
|
34
|
+
artifacts: [{ kind: 'profile_name', label: 'Name', status: 'success' }],
|
|
35
|
+
summary: { title: 'Profile Updated' },
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
it('returns data part with type data-execution-result', () => {
|
|
39
|
+
const result = WireSurfaceBuilder.executionResult(data)
|
|
40
|
+
expect(result.type).toBe('data-execution-result')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('data matches input ExecutionResultData exactly', () => {
|
|
44
|
+
const result = WireSurfaceBuilder.executionResult(data)
|
|
45
|
+
expect(result.data).toEqual(data)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('preserves actionId from input', () => {
|
|
49
|
+
const result = WireSurfaceBuilder.executionResult(data)
|
|
50
|
+
expect(result.data.actionId).toBe('act-1')
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('WireSurfaceBuilder.undoResult', () => {
|
|
55
|
+
const data: UndoResultData = {
|
|
56
|
+
actionId: 'act-1',
|
|
57
|
+
executionId: 'exec-001',
|
|
58
|
+
undoExecutionId: 'undo-exec-002',
|
|
59
|
+
status: 'success',
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
it('returns data part with type data-undo-result', () => {
|
|
63
|
+
const result = WireSurfaceBuilder.undoResult(data)
|
|
64
|
+
expect(result.type).toBe('data-undo-result')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('data matches input UndoResultData exactly', () => {
|
|
68
|
+
const result = WireSurfaceBuilder.undoResult(data)
|
|
69
|
+
expect(result.data).toEqual(data)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('preserves undoExecutionId from input', () => {
|
|
73
|
+
const result = WireSurfaceBuilder.undoResult(data)
|
|
74
|
+
expect(result.data.undoExecutionId).toBe('undo-exec-002')
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
describe('WireSurfaceBuilder.messageStart', () => {
|
|
79
|
+
it('returns data part with type data-message-start', () => {
|
|
80
|
+
const result = WireSurfaceBuilder.messageStart('msg-123')
|
|
81
|
+
expect(result.type).toBe('data-message-start')
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('data.messageId matches input', () => {
|
|
85
|
+
const result = WireSurfaceBuilder.messageStart('msg-456')
|
|
86
|
+
expect(result.data.messageId).toBe('msg-456')
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('data.version is 1', () => {
|
|
90
|
+
const result = WireSurfaceBuilder.messageStart('msg-789')
|
|
91
|
+
expect(result.data.version).toBe(1)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('data.timestamp is a valid ISO 8601 string', () => {
|
|
95
|
+
const result = WireSurfaceBuilder.messageStart('msg-ts')
|
|
96
|
+
const parsed = new Date(result.data.timestamp)
|
|
97
|
+
expect(parsed.toISOString()).toBe(result.data.timestamp)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
describe('WireSurfaceBuilder.messageComplete', () => {
|
|
102
|
+
it('returns data part with type data-message-complete', () => {
|
|
103
|
+
const result = WireSurfaceBuilder.messageComplete('msg-123', 500)
|
|
104
|
+
expect(result.type).toBe('data-message-complete')
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('data.messageId matches input', () => {
|
|
108
|
+
const result = WireSurfaceBuilder.messageComplete('msg-456', 200)
|
|
109
|
+
expect(result.data.messageId).toBe('msg-456')
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('data.narrativeLength matches input', () => {
|
|
113
|
+
const result = WireSurfaceBuilder.messageComplete('msg-789', 1234)
|
|
114
|
+
expect(result.data.narrativeLength).toBe(1234)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('data.version is 1', () => {
|
|
118
|
+
const result = WireSurfaceBuilder.messageComplete('msg-v', 100)
|
|
119
|
+
expect(result.data.version).toBe(1)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('data.timestamp is a valid ISO 8601 string', () => {
|
|
123
|
+
const result = WireSurfaceBuilder.messageComplete('msg-ts', 300)
|
|
124
|
+
const parsed = new Date(result.data.timestamp)
|
|
125
|
+
expect(parsed.toISOString()).toBe(result.data.timestamp)
|
|
126
|
+
})
|
|
127
|
+
})
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { VIEW_SCOPE_MAP, getViewScope } from '../view-scopes.js'
|
|
3
|
+
|
|
4
|
+
describe('VIEW_SCOPE_MAP golden snapshot', () => {
|
|
5
|
+
it('exact values are frozen', () => {
|
|
6
|
+
expect(VIEW_SCOPE_MAP).toStrictEqual({
|
|
7
|
+
workspace: 'org.view_workspace',
|
|
8
|
+
timeline: 'org.view_timeline',
|
|
9
|
+
activity: 'org.view_activity',
|
|
10
|
+
strategy: 'org.view_strategy',
|
|
11
|
+
'internal-admin': 'internal.view_admin',
|
|
12
|
+
chat: null,
|
|
13
|
+
settings: null,
|
|
14
|
+
chats: null,
|
|
15
|
+
upgrade: null,
|
|
16
|
+
})
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
describe('getViewScope', () => {
|
|
21
|
+
it('returns the required scope for protected views', () => {
|
|
22
|
+
expect(getViewScope('workspace')).toBe('org.view_workspace')
|
|
23
|
+
expect(getViewScope('timeline')).toBe('org.view_timeline')
|
|
24
|
+
expect(getViewScope('activity')).toBe('org.view_activity')
|
|
25
|
+
expect(getViewScope('strategy')).toBe('org.view_strategy')
|
|
26
|
+
expect(getViewScope('internal-admin')).toBe('internal.view_admin')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('returns null for public views', () => {
|
|
30
|
+
expect(getViewScope('chat')).toBeNull()
|
|
31
|
+
expect(getViewScope('settings')).toBeNull()
|
|
32
|
+
expect(getViewScope('chats')).toBeNull()
|
|
33
|
+
expect(getViewScope('upgrade')).toBeNull()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('returns null for unknown view string', () => {
|
|
37
|
+
expect(getViewScope('nonexistent-view')).toBeNull()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('returns null for empty string', () => {
|
|
41
|
+
expect(getViewScope('')).toBeNull()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('returns null for view name that is a substring of a real view', () => {
|
|
45
|
+
expect(getViewScope('work')).toBeNull()
|
|
46
|
+
})
|
|
47
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { REPO_PRECEDENCE } from '../prd.js'
|
|
3
|
+
|
|
4
|
+
describe('REPO_PRECEDENCE', () => {
|
|
5
|
+
it('has contracts first (dependency source)', () => {
|
|
6
|
+
expect(REPO_PRECEDENCE[0]).toBe('company-semantics-contracts')
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
it('exact values and order are frozen (golden snapshot)', () => {
|
|
10
|
+
expect(REPO_PRECEDENCE).toStrictEqual([
|
|
11
|
+
'company-semantics-contracts',
|
|
12
|
+
'company-semantics-control',
|
|
13
|
+
'company-semantics-ci',
|
|
14
|
+
'company-semantics-backend',
|
|
15
|
+
'company-semantics-edge',
|
|
16
|
+
'company-semantics-app',
|
|
17
|
+
'company-semantics-site',
|
|
18
|
+
])
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('has exactly 7 entries (all known repos)', () => {
|
|
22
|
+
expect(REPO_PRECEDENCE).toHaveLength(7)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('has no duplicates', () => {
|
|
26
|
+
expect(new Set(REPO_PRECEDENCE).size).toBe(REPO_PRECEDENCE.length)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('all entries start with company-semantics- prefix', () => {
|
|
30
|
+
for (const repo of REPO_PRECEDENCE) {
|
|
31
|
+
expect(repo).toMatch(/^company-semantics-/)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('all entries are non-empty strings', () => {
|
|
36
|
+
for (const repo of REPO_PRECEDENCE) {
|
|
37
|
+
expect(typeof repo).toBe('string')
|
|
38
|
+
expect(repo.length).toBeGreaterThan(0)
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
})
|