@sidurijs/core 1.0.1 → 1.0.3
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/dist/adversarial.test.js +27 -19
- package/dist/chat-contract.d.ts +9 -0
- package/dist/cognition-planner.d.ts +2 -2
- package/dist/context-retriever.d.ts +4 -4
- package/dist/context-retriever.js +22 -25
- package/dist/conversational-teach.test.js +21 -21
- package/dist/evidence.d.ts +3 -3
- package/dist/gating.d.ts +2 -2
- package/dist/gating.js +1 -1
- package/dist/index.d.ts +9 -27
- package/dist/index.js +0 -1
- package/dist/intent-classifier.d.ts +1 -1
- package/dist/intent-classifier.js +4 -4
- package/dist/intent-classifier.test.js +1 -1
- package/dist/interaction-settler.d.ts +4 -12
- package/dist/interaction-settler.js +14 -18
- package/dist/perception-cycle.test.js +18 -34
- package/dist/perception-pipeline.d.ts +3 -4
- package/dist/perception-pipeline.js +12 -13
- package/dist/prompt-compiler.d.ts +1 -1
- package/dist/prompt-compiler.js +11 -11
- package/dist/prompt-compiler.test.js +5 -5
- package/dist/proposals.d.ts +1 -2
- package/dist/response-envelope.d.ts +3 -3
- package/dist/response-envelope.js +4 -4
- package/dist/schema-validator.test.js +3 -3
- package/dist/siduri-db.d.ts +3 -1
- package/dist/siduri-db.js +0 -31
- package/dist/teaching.d.ts +3 -3
- package/dist/teaching.js +1 -1
- package/package.json +1 -1
package/dist/adversarial.test.js
CHANGED
|
@@ -53,38 +53,43 @@ describe('Adversarial Hardening Verification Suite (Phase 3)', () => {
|
|
|
53
53
|
validFrom: pastTime,
|
|
54
54
|
validUntil: futureTime,
|
|
55
55
|
};
|
|
56
|
-
const
|
|
56
|
+
const mockArchive = {
|
|
57
57
|
initialize: jest.fn().mockResolvedValue(undefined),
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
searchEvents: jest.fn().mockResolvedValue([{
|
|
59
|
+
id: 'evt-valid',
|
|
60
|
+
companionId: 'companion-adv',
|
|
61
|
+
sourceType: 'User',
|
|
62
|
+
occurredAt: new Date().toISOString(),
|
|
63
|
+
payload: 'favoriteColor Azure',
|
|
64
|
+
}]),
|
|
60
65
|
};
|
|
61
66
|
const runtime = new index_1.SiduriRuntime('companion-adv', { name: 'AdvCompanion' }, {
|
|
62
67
|
brain: mockBrain,
|
|
63
|
-
|
|
68
|
+
archive: mockArchive,
|
|
64
69
|
});
|
|
65
70
|
await runtime.handleUserMessage('What is my favorite color?', baseOwnerContext);
|
|
66
|
-
expect(
|
|
71
|
+
expect(mockArchive.searchEvents).toHaveBeenCalled();
|
|
67
72
|
const brainCall = mockBrain.generatePlan.mock.calls[0][0];
|
|
68
|
-
expect(brainCall.contextPrompt).toContain('
|
|
73
|
+
expect(brainCall.contextPrompt).toContain('ARCHIVE:');
|
|
74
|
+
expect(brainCall.contextPrompt).toContain('favoriteColor Azure');
|
|
69
75
|
});
|
|
70
76
|
test('companion isolation: runtime passes only companionId matching context', async () => {
|
|
71
77
|
const mockBrain = {
|
|
72
78
|
generatePlan: jest.fn().mockResolvedValue({ speech: 'OK', language: 'en' }),
|
|
73
79
|
};
|
|
74
|
-
const
|
|
80
|
+
const mockArchive = {
|
|
75
81
|
initialize: jest.fn().mockResolvedValue(undefined),
|
|
76
|
-
|
|
77
|
-
getDirectives: jest.fn().mockResolvedValue([]),
|
|
82
|
+
searchEvents: jest.fn().mockResolvedValue([]),
|
|
78
83
|
};
|
|
79
84
|
const runtime = new index_1.SiduriRuntime('companion-A', { name: 'AdvA' }, {
|
|
80
85
|
brain: mockBrain,
|
|
81
|
-
|
|
86
|
+
archive: mockArchive,
|
|
82
87
|
});
|
|
83
88
|
await runtime.handleUserMessage('Query', {
|
|
84
89
|
...baseOwnerContext,
|
|
85
90
|
companionId: 'companion-A',
|
|
86
91
|
});
|
|
87
|
-
expect(
|
|
92
|
+
expect(mockArchive.searchEvents).toHaveBeenCalledWith('companion-A', 'Query', 5);
|
|
88
93
|
});
|
|
89
94
|
});
|
|
90
95
|
// INVARIANT 2: Authority & Request Boundary
|
|
@@ -349,27 +354,30 @@ describe('Adversarial Hardening Verification Suite (Phase 3)', () => {
|
|
|
349
354
|
});
|
|
350
355
|
// INVARIANT 6: Failure Semantics & Degradation
|
|
351
356
|
describe('Invariant 6: Subsystem Failure Diagnostics & Non-Empty Propagation', () => {
|
|
352
|
-
test('
|
|
357
|
+
test('archive/self query failure surfaces diagnostic in contextPrompt and metadata', async () => {
|
|
353
358
|
const mockBrain = {
|
|
354
359
|
generatePlan: jest.fn().mockResolvedValue({ speech: 'Graceful fallback response', language: 'en' }),
|
|
355
360
|
};
|
|
356
|
-
const
|
|
361
|
+
const failingArchive = {
|
|
357
362
|
initialize: jest.fn().mockResolvedValue(undefined),
|
|
358
|
-
|
|
359
|
-
|
|
363
|
+
searchEvents: jest.fn().mockRejectedValue(new Error('Connection terminated unexpectedly')),
|
|
364
|
+
};
|
|
365
|
+
const failingSelf = {
|
|
366
|
+
getActiveDirectives: jest.fn().mockRejectedValue(new Error('Database read timeout')),
|
|
360
367
|
};
|
|
361
368
|
const runtime = new index_1.SiduriRuntime('companion-adv', { name: 'AdvCompanion' }, {
|
|
362
369
|
brain: mockBrain,
|
|
363
|
-
|
|
370
|
+
archive: failingArchive,
|
|
371
|
+
self: failingSelf,
|
|
364
372
|
});
|
|
365
373
|
const response = await runtime.handleUserMessage('Hello companion', baseOwnerContext);
|
|
366
374
|
expect(response.status).toBe('APPROVED');
|
|
367
375
|
expect(response.metadata.subsystem_diagnostics).toBeDefined();
|
|
368
|
-
expect(response.metadata.subsystem_diagnostics.
|
|
369
|
-
expect(response.metadata.subsystem_diagnostics.
|
|
376
|
+
expect(response.metadata.subsystem_diagnostics.archive).toContain('UNAVAILABLE');
|
|
377
|
+
expect(response.metadata.subsystem_diagnostics.self_directives).toContain('UNAVAILABLE');
|
|
370
378
|
const brainCall = mockBrain.generatePlan.mock.calls[0][0];
|
|
371
379
|
expect(brainCall.contextPrompt).toContain('SUBSYSTEM STATUS (DEGRADED):');
|
|
372
|
-
expect(brainCall.contextPrompt).toContain('
|
|
380
|
+
expect(brainCall.contextPrompt).toContain('archive');
|
|
373
381
|
});
|
|
374
382
|
});
|
|
375
383
|
// INVARIANT 8: Truth Gate Admissibility vs Factuality
|
package/dist/chat-contract.d.ts
CHANGED
|
@@ -46,6 +46,15 @@ export interface ChatResponsePlan {
|
|
|
46
46
|
export interface ChatResponseMetadata {
|
|
47
47
|
language?: string;
|
|
48
48
|
proposals?: Claim[];
|
|
49
|
+
claim_proposals?: Array<{
|
|
50
|
+
proposal_id: string;
|
|
51
|
+
subject?: string;
|
|
52
|
+
predicate?: string;
|
|
53
|
+
value?: string;
|
|
54
|
+
status: string;
|
|
55
|
+
content?: string;
|
|
56
|
+
claim_type?: string;
|
|
57
|
+
}>;
|
|
49
58
|
memory_proposals?: Array<{
|
|
50
59
|
proposal_id: string;
|
|
51
60
|
subject?: string;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { BrainOrgan, Message, ResponsePlan,
|
|
1
|
+
import { BrainOrgan, Message, ResponsePlan, ClaimScope } from './index';
|
|
2
2
|
export interface CognitionPlanningParams {
|
|
3
3
|
companionName: string;
|
|
4
4
|
brain?: BrainOrgan;
|
|
5
5
|
systemPrompt: string;
|
|
6
6
|
contextPrompt: string;
|
|
7
7
|
recentMessages: Message[];
|
|
8
|
-
recipient?:
|
|
8
|
+
recipient?: ClaimScope;
|
|
9
9
|
perceivedText: string;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { KnowledgeOrgan, KnowledgeItem, Claim, BehaviorDirective, EvidenceRecord, ResponseCitation, RequestContext, SelfRepository, LifeDatabase, ArchiveLedger,
|
|
1
|
+
import { KnowledgeOrgan, KnowledgeItem, Claim, BehaviorDirective, EvidenceRecord, ResponseCitation, RequestContext, SelfRepository, LifeDatabase, ArchiveLedger, EKnowledgeOrgan } from './index';
|
|
2
2
|
export interface ContextRetrievalParams {
|
|
3
3
|
companionId: string;
|
|
4
4
|
perceivedText: string;
|
|
@@ -7,17 +7,17 @@ export interface ContextRetrievalParams {
|
|
|
7
7
|
isContextObject: boolean;
|
|
8
8
|
shouldQueryKnowledge: boolean;
|
|
9
9
|
knowledgeQueries?: string[];
|
|
10
|
-
|
|
10
|
+
archiveQueries?: string[];
|
|
11
11
|
isSelfIdentityRequest?: boolean;
|
|
12
12
|
knowledge?: KnowledgeOrgan | LifeDatabase;
|
|
13
13
|
archive?: ArchiveLedger;
|
|
14
|
-
memory?:
|
|
14
|
+
memory?: any;
|
|
15
15
|
self?: SelfRepository;
|
|
16
16
|
externalKnowledge?: EKnowledgeOrgan | KnowledgeOrgan;
|
|
17
17
|
}
|
|
18
18
|
export interface RetrievedContext {
|
|
19
19
|
knowledgeData: KnowledgeItem[];
|
|
20
|
-
|
|
20
|
+
archiveData: Claim[];
|
|
21
21
|
activeDirectives: BehaviorDirective[];
|
|
22
22
|
subsystemDiagnostics: Record<string, string>;
|
|
23
23
|
collectedEvidence: EvidenceRecord[];
|
|
@@ -7,7 +7,7 @@ const intent_classifier_1 = require("./intent-classifier");
|
|
|
7
7
|
* in a single parallel pass with graceful degradation.
|
|
8
8
|
*/
|
|
9
9
|
async function retrieveRuntimeContext(params) {
|
|
10
|
-
const { companionId, perceivedText, requestContext, role, isContextObject, shouldQueryKnowledge, knowledgeQueries,
|
|
10
|
+
const { companionId, perceivedText, requestContext, role, isContextObject, shouldQueryKnowledge, knowledgeQueries, archiveQueries, isSelfIdentityRequest, knowledge, archive, memory, self, externalKnowledge, } = params;
|
|
11
11
|
const queryOptions = isContextObject
|
|
12
12
|
? {
|
|
13
13
|
limit: 5,
|
|
@@ -31,11 +31,11 @@ async function retrieveRuntimeContext(params) {
|
|
|
31
31
|
queryCandidateSet.add(perceivedText.trim());
|
|
32
32
|
}
|
|
33
33
|
const finalKnowledgeQueries = Array.from(queryCandidateSet);
|
|
34
|
-
const
|
|
35
|
-
?
|
|
34
|
+
const archiveQueryToRun = (archiveQueries && archiveQueries.length > 0 && archiveQueries[0])
|
|
35
|
+
? archiveQueries[0]
|
|
36
36
|
: (0, intent_classifier_1.extractSearchKeywords)(perceivedText, companionId)[0] || perceivedText;
|
|
37
37
|
// 2. Query streams in parallel
|
|
38
|
-
const [knowledgeData,
|
|
38
|
+
const [knowledgeData, archiveData, selfDirectives, lifeContext, selfIdentity, selfRelationship, personality,] = await Promise.all([
|
|
39
39
|
// Stream A: External Cited Lore / Documentation
|
|
40
40
|
extKnowledge && shouldQueryKnowledge && typeof extKnowledge.search === 'function'
|
|
41
41
|
? Promise.all(finalKnowledgeQueries.map((q) => extKnowledge.search(q).catch((e) => {
|
|
@@ -46,10 +46,8 @@ async function retrieveRuntimeContext(params) {
|
|
|
46
46
|
const merged = [];
|
|
47
47
|
const seen = new Set();
|
|
48
48
|
for (const list of resultsArray) {
|
|
49
|
-
if (!Array.isArray(list))
|
|
50
|
-
continue;
|
|
51
49
|
for (const item of list) {
|
|
52
|
-
const key = item.
|
|
50
|
+
const key = item.content.slice(0, 100);
|
|
53
51
|
if (!seen.has(key)) {
|
|
54
52
|
seen.add(key);
|
|
55
53
|
merged.push(item);
|
|
@@ -59,12 +57,11 @@ async function retrieveRuntimeContext(params) {
|
|
|
59
57
|
return merged;
|
|
60
58
|
})
|
|
61
59
|
: Promise.resolve([]),
|
|
62
|
-
// Stream B: Interaction Archive /
|
|
60
|
+
// Stream B: Interaction Archive / Claims
|
|
63
61
|
memory && typeof memory.searchClaims === 'function'
|
|
64
62
|
? (async () => {
|
|
65
63
|
try {
|
|
66
|
-
|
|
67
|
-
let result = await memory.searchClaims(memoryQueryToRun, queryOptions, 5);
|
|
64
|
+
let result = await memory.searchClaims(archiveQueryToRun, queryOptions, 5);
|
|
68
65
|
if ((!result || result.length === 0) && isSelfIdentityRequest) {
|
|
69
66
|
if (typeof memory.getApprovedClaims === 'function') {
|
|
70
67
|
const approved = await memory.getApprovedClaims(companionId, 10);
|
|
@@ -96,7 +93,7 @@ async function retrieveRuntimeContext(params) {
|
|
|
96
93
|
: archive && typeof archive.searchEvents === 'function'
|
|
97
94
|
? (async () => {
|
|
98
95
|
try {
|
|
99
|
-
const events = await archive.searchEvents(companionId,
|
|
96
|
+
const events = await archive.searchEvents(companionId, archiveQueryToRun, 5);
|
|
100
97
|
return (events || []).map((evt) => ({
|
|
101
98
|
id: evt.id,
|
|
102
99
|
companionId: evt.companionId,
|
|
@@ -156,7 +153,7 @@ async function retrieveRuntimeContext(params) {
|
|
|
156
153
|
? self.getPersonality(companionId).catch(() => undefined)
|
|
157
154
|
: Promise.resolve(undefined),
|
|
158
155
|
]);
|
|
159
|
-
const activeDirectives = (
|
|
156
|
+
const activeDirectives = (selfDirectives || []);
|
|
160
157
|
// Build evidence records from retrieved context streams
|
|
161
158
|
const collectedEvidence = [];
|
|
162
159
|
const citations = [];
|
|
@@ -208,19 +205,19 @@ async function retrieveRuntimeContext(params) {
|
|
|
208
205
|
}
|
|
209
206
|
}
|
|
210
207
|
}
|
|
211
|
-
// Stream B:
|
|
212
|
-
if (
|
|
213
|
-
for (const m of
|
|
214
|
-
const claimId = m.claim_id || m.id || `
|
|
215
|
-
const sourceId = m.provenance || '
|
|
216
|
-
const evId = `ev-
|
|
217
|
-
const claimPreview = m.content || `${m.subject || '
|
|
208
|
+
// Stream B: Interaction Archive
|
|
209
|
+
if (archiveData.length > 0) {
|
|
210
|
+
for (const m of archiveData) {
|
|
211
|
+
const claimId = m.claim_id || m.id || `evt-${Date.now()}`;
|
|
212
|
+
const sourceId = m.provenance || 'archive_ledger';
|
|
213
|
+
const evId = `ev-arc-${claimId}`;
|
|
214
|
+
const claimPreview = m.content || `${m.subject || 'event'} ${m.predicate || 'event'}: ${m.value || ''}`;
|
|
218
215
|
collectedEvidence.push({
|
|
219
216
|
evidenceId: evId,
|
|
220
217
|
sourceId,
|
|
221
218
|
documentId: claimId,
|
|
222
|
-
chunkId: `${m.subject || '
|
|
223
|
-
origin: '
|
|
219
|
+
chunkId: `${m.subject || 'archive'}:${m.predicate || 'event'}`,
|
|
220
|
+
origin: 'archive',
|
|
224
221
|
trust: 'configured',
|
|
225
222
|
sensitivity: 'private',
|
|
226
223
|
companionId,
|
|
@@ -229,11 +226,11 @@ async function retrieveRuntimeContext(params) {
|
|
|
229
226
|
});
|
|
230
227
|
citations.push({
|
|
231
228
|
evidenceId: evId,
|
|
232
|
-
provenance: '
|
|
229
|
+
provenance: 'archive',
|
|
233
230
|
sourceId,
|
|
234
231
|
documentId: claimId,
|
|
235
|
-
chunkId: `${m.subject || '
|
|
236
|
-
locator: `
|
|
232
|
+
chunkId: `${m.subject || 'archive'}.${m.predicate || 'event'}`,
|
|
233
|
+
locator: `archive:${claimId}`,
|
|
237
234
|
preview: claimPreview.slice(0, 300),
|
|
238
235
|
});
|
|
239
236
|
}
|
|
@@ -268,7 +265,7 @@ async function retrieveRuntimeContext(params) {
|
|
|
268
265
|
}
|
|
269
266
|
return {
|
|
270
267
|
knowledgeData,
|
|
271
|
-
|
|
268
|
+
archiveData,
|
|
272
269
|
activeDirectives,
|
|
273
270
|
subsystemDiagnostics,
|
|
274
271
|
collectedEvidence,
|
|
@@ -172,10 +172,10 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
172
172
|
return {
|
|
173
173
|
generatePlan: jest.fn().mockImplementation(async (brainCtx) => {
|
|
174
174
|
const lastMsg = brainCtx.recentMessages?.[brainCtx.recentMessages.length - 1]?.content || '';
|
|
175
|
-
const
|
|
175
|
+
const claimProposals = [];
|
|
176
176
|
const behaviorProposals = [];
|
|
177
177
|
if (/AI researcher at VXNUS Studio/i.test(lastMsg)) {
|
|
178
|
-
|
|
178
|
+
claimProposals.push({
|
|
179
179
|
subject: `companion:${companionId}`,
|
|
180
180
|
predicate: 'role',
|
|
181
181
|
value: 'AI researcher at VXNUS Studio',
|
|
@@ -189,35 +189,35 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
189
189
|
});
|
|
190
190
|
}
|
|
191
191
|
else if (/Lead Architect at VXNUS Studio/i.test(lastMsg)) {
|
|
192
|
-
|
|
192
|
+
claimProposals.push({
|
|
193
193
|
subject: `companion:${companionId}`,
|
|
194
194
|
predicate: 'role',
|
|
195
195
|
value: 'Lead Architect at VXNUS Studio',
|
|
196
196
|
});
|
|
197
197
|
}
|
|
198
198
|
else if (/Research Specialist/i.test(lastMsg)) {
|
|
199
|
-
|
|
199
|
+
claimProposals.push({
|
|
200
200
|
subject: `companion:${companionId}`,
|
|
201
201
|
predicate: 'role',
|
|
202
202
|
value: 'Research Specialist',
|
|
203
203
|
});
|
|
204
204
|
}
|
|
205
205
|
else if (/Security Officer/i.test(lastMsg)) {
|
|
206
|
-
|
|
206
|
+
claimProposals.push({
|
|
207
207
|
subject: `companion:${companionId}`,
|
|
208
208
|
predicate: 'role',
|
|
209
209
|
value: 'Security Officer',
|
|
210
210
|
});
|
|
211
211
|
}
|
|
212
212
|
else if (/VXNUS Studio Staff/i.test(lastMsg)) {
|
|
213
|
-
|
|
213
|
+
claimProposals.push({
|
|
214
214
|
subject: `companion:${companionId}`,
|
|
215
215
|
predicate: 'role',
|
|
216
216
|
value: 'VXNUS Studio Staff',
|
|
217
217
|
});
|
|
218
218
|
}
|
|
219
219
|
if (/\bcreator\b/i.test(lastMsg)) {
|
|
220
|
-
|
|
220
|
+
claimProposals.push({
|
|
221
221
|
subject: 'actor:kur-zagin',
|
|
222
222
|
predicate: 'stated_relationship',
|
|
223
223
|
value: 'creator',
|
|
@@ -232,7 +232,7 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
232
232
|
});
|
|
233
233
|
}
|
|
234
234
|
if (/Kur Zagin/i.test(lastMsg)) {
|
|
235
|
-
|
|
235
|
+
claimProposals.push({
|
|
236
236
|
subject: 'actor:kur-zagin',
|
|
237
237
|
predicate: 'name',
|
|
238
238
|
value: 'Kur Zagin',
|
|
@@ -252,7 +252,7 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
252
252
|
category: 'behavioral',
|
|
253
253
|
priority: 60,
|
|
254
254
|
});
|
|
255
|
-
|
|
255
|
+
claimProposals.push({
|
|
256
256
|
subject: 'actor:kur-zagin',
|
|
257
257
|
predicate: 'rule',
|
|
258
258
|
value: 'Be concise when answering technical questions',
|
|
@@ -261,7 +261,7 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
261
261
|
return {
|
|
262
262
|
speech: 'Understood, I have acknowledged your input.',
|
|
263
263
|
language: 'en',
|
|
264
|
-
|
|
264
|
+
claimProposals: claimProposals.length > 0 ? claimProposals : undefined,
|
|
265
265
|
behaviorProposals: behaviorProposals.length > 0 ? behaviorProposals : undefined,
|
|
266
266
|
_receivedSystemPrompt: brainCtx.systemPrompt,
|
|
267
267
|
};
|
|
@@ -399,14 +399,14 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
399
399
|
text: 'Remember this rule: be concise when answering technical questions.',
|
|
400
400
|
context: createRequestContext(companionId, 'teach'),
|
|
401
401
|
});
|
|
402
|
-
// Check behavioral proposals or
|
|
402
|
+
// Check behavioral proposals or claim proposals
|
|
403
403
|
const behavioralReceipts = perceptionResult.metadata?.behavioral_proposals || [];
|
|
404
|
-
const
|
|
404
|
+
const claimProposals = perceptionResult.metadata?.proposals || [];
|
|
405
405
|
const hasDirectiveProposal = behavioralReceipts.length > 0 ||
|
|
406
|
-
|
|
406
|
+
claimProposals.some((p) => p.predicate === 'rule' || p.predicate === 'behavioral_rule');
|
|
407
407
|
expect(hasDirectiveProposal).toBe(true);
|
|
408
408
|
const directiveId = behavioralReceipts[0]?.directive_id;
|
|
409
|
-
const proposalId =
|
|
409
|
+
const proposalId = claimProposals[0]?.id;
|
|
410
410
|
// 2. Active directives before approval must not include the new rule
|
|
411
411
|
const directivesBefore = await self.getActiveDirectives(companionId);
|
|
412
412
|
expect(directivesBefore.some((d) => d.directive.toLowerCase().includes('be concise when answering technical questions'))).toBe(false);
|
|
@@ -450,7 +450,7 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
450
450
|
expect(perceptionResult.status).toBe('APPROVED');
|
|
451
451
|
// Zero proposals allowed in casual mode
|
|
452
452
|
expect(perceptionResult.metadata?.proposals).toEqual([]);
|
|
453
|
-
expect(perceptionResult.metadata?.
|
|
453
|
+
expect(perceptionResult.metadata?.claim_proposals).toEqual([]);
|
|
454
454
|
// Self must remain unchanged
|
|
455
455
|
const identity = await self.getIdentity(companionId);
|
|
456
456
|
expect(identity?.role).toBeUndefined();
|
|
@@ -666,10 +666,10 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
666
666
|
const mockBrain = {
|
|
667
667
|
generatePlan: jest.fn().mockImplementation(async (brainCtx) => {
|
|
668
668
|
const lastMsg = brainCtx.recentMessages?.[brainCtx.recentMessages.length - 1]?.content || '';
|
|
669
|
-
const
|
|
669
|
+
const claimProposals = [];
|
|
670
670
|
const behaviorProposals = [];
|
|
671
671
|
if (/your name is Siduri/i.test(lastMsg)) {
|
|
672
|
-
|
|
672
|
+
claimProposals.push({
|
|
673
673
|
subject: 'companion:self',
|
|
674
674
|
predicate: 'name',
|
|
675
675
|
value: 'Siduri',
|
|
@@ -683,12 +683,12 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
683
683
|
});
|
|
684
684
|
}
|
|
685
685
|
if (/i am Kur Zagin, your creator/i.test(lastMsg)) {
|
|
686
|
-
|
|
686
|
+
claimProposals.push({
|
|
687
687
|
subject: 'actor:kur_zagin',
|
|
688
688
|
predicate: 'name',
|
|
689
689
|
value: 'Kur Zagin',
|
|
690
690
|
});
|
|
691
|
-
|
|
691
|
+
claimProposals.push({
|
|
692
692
|
subject: 'actor:kur_zagin',
|
|
693
693
|
predicate: 'stated_relationship',
|
|
694
694
|
value: 'creator of companion Siduri',
|
|
@@ -711,7 +711,7 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
711
711
|
return {
|
|
712
712
|
speech: 'I understand and acknowledge.',
|
|
713
713
|
language: 'en',
|
|
714
|
-
|
|
714
|
+
claimProposals: claimProposals.length > 0 ? claimProposals : undefined,
|
|
715
715
|
behaviorProposals: behaviorProposals.length > 0 ? behaviorProposals : undefined,
|
|
716
716
|
_receivedSystemPrompt: brainCtx.systemPrompt,
|
|
717
717
|
};
|
|
@@ -819,7 +819,7 @@ describe('Conversational Teach Mode End-to-End Lifecycle', () => {
|
|
|
819
819
|
context: createRequestContext(companionId, 'hybrid', 'owner-user'),
|
|
820
820
|
});
|
|
821
821
|
const whoAmICtx = calls[calls.length - 1][0];
|
|
822
|
-
expect(whoAmICtx.contextPrompt).toContain('
|
|
822
|
+
expect(whoAmICtx.contextPrompt).toContain('ARCHIVE:');
|
|
823
823
|
expect(whoAmICtx.contextPrompt).toContain('Kur Zagin');
|
|
824
824
|
db.close();
|
|
825
825
|
});
|
package/dist/evidence.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export type EvidenceOrigin = 'knowledge' | '
|
|
1
|
+
import { ClaimProposal, BehaviorProposal } from './proposals';
|
|
2
|
+
export type EvidenceOrigin = 'knowledge' | 'archive' | 'life' | 'observation' | 'ocr' | 'platform' | 'conversation';
|
|
3
3
|
export type EvidenceTrust = 'configured' | 'provider' | 'untrusted';
|
|
4
4
|
export type EvidenceSensitivity = 'public' | 'private' | 'restricted';
|
|
5
5
|
export interface EvidenceRecord {
|
|
@@ -47,7 +47,7 @@ export interface StagedResponsePlan {
|
|
|
47
47
|
status: ResponseApprovalStatus;
|
|
48
48
|
createdAt: string;
|
|
49
49
|
expiresAt?: string;
|
|
50
|
-
|
|
50
|
+
claimProposals?: ClaimProposal[];
|
|
51
51
|
behaviorProposals?: BehaviorProposal[];
|
|
52
52
|
internalMonologue?: string;
|
|
53
53
|
[key: string]: unknown;
|
package/dist/gating.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { RequestContext } from './context';
|
|
2
|
-
import {
|
|
2
|
+
import { ClaimProposal, BehaviorProposal } from './proposals';
|
|
3
3
|
import { EvidenceRecord, StagedResponsePlan, ResponseGateEvaluation, ResponseCitation } from './evidence';
|
|
4
4
|
export interface StageResponseOptions {
|
|
5
5
|
requestContext: RequestContext;
|
|
6
6
|
candidateSpeech: string;
|
|
7
7
|
candidateLanguage: string;
|
|
8
8
|
internalMonologue?: string;
|
|
9
|
-
|
|
9
|
+
claimProposals?: ClaimProposal[];
|
|
10
10
|
behaviorProposals?: BehaviorProposal[];
|
|
11
11
|
evidenceRecords?: EvidenceRecord[];
|
|
12
12
|
citations?: ResponseCitation[];
|
package/dist/gating.js
CHANGED
|
@@ -50,7 +50,7 @@ class ResponseGatingEngine {
|
|
|
50
50
|
status: 'STAGED',
|
|
51
51
|
createdAt: new Date(nowTime).toISOString(),
|
|
52
52
|
expiresAt,
|
|
53
|
-
|
|
53
|
+
claimProposals: options.claimProposals,
|
|
54
54
|
behaviorProposals: options.behaviorProposals,
|
|
55
55
|
internalMonologue: options.internalMonologue,
|
|
56
56
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -18,7 +18,6 @@ export * from './context-retriever';
|
|
|
18
18
|
export * from './prompt-compiler';
|
|
19
19
|
export * from './cognition-planner';
|
|
20
20
|
export * from './interaction-settler';
|
|
21
|
-
export * from './memory-settler';
|
|
22
21
|
export * from './action-executor';
|
|
23
22
|
export * from './experience-emitter';
|
|
24
23
|
export * from './response-envelope';
|
|
@@ -32,7 +31,7 @@ import { EvidenceRecord } from './evidence';
|
|
|
32
31
|
import { ActionIntent } from './action';
|
|
33
32
|
import { RequestContext } from './context';
|
|
34
33
|
import { EarIngestOptions } from './ear-types';
|
|
35
|
-
import { ClaimType, ClaimAuthority, ClaimStatus, DirectiveStatus, SourceEvent,
|
|
34
|
+
import { ClaimType, ClaimAuthority, ClaimStatus, DirectiveStatus, SourceEvent, ClaimProposal, BehaviorProposal } from './proposals';
|
|
36
35
|
export interface OrganConfig {
|
|
37
36
|
provider: string;
|
|
38
37
|
[key: string]: unknown;
|
|
@@ -57,14 +56,14 @@ export interface BrainContext {
|
|
|
57
56
|
systemPrompt: string;
|
|
58
57
|
contextPrompt: string;
|
|
59
58
|
recentMessages: Message[];
|
|
60
|
-
recipient?:
|
|
59
|
+
recipient?: ClaimScope;
|
|
61
60
|
}
|
|
62
61
|
export interface ResponsePlan {
|
|
63
62
|
speech: string;
|
|
64
63
|
language: string;
|
|
65
64
|
subtitle?: string;
|
|
66
65
|
subtitles?: Record<string, string>;
|
|
67
|
-
|
|
66
|
+
claimProposals?: ClaimProposal[];
|
|
68
67
|
behaviorProposals?: BehaviorProposal[];
|
|
69
68
|
actionIntents?: ActionIntent[];
|
|
70
69
|
internalMonologue?: string;
|
|
@@ -72,8 +71,8 @@ export interface ResponsePlan {
|
|
|
72
71
|
export interface RetrievalPlan {
|
|
73
72
|
shouldQueryKnowledge: boolean;
|
|
74
73
|
knowledgeQueries: string[];
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
shouldQueryArchive?: boolean;
|
|
75
|
+
archiveQueries?: string[];
|
|
77
76
|
reasoning?: string;
|
|
78
77
|
}
|
|
79
78
|
export interface PersonaCompilationResult {
|
|
@@ -127,7 +126,7 @@ export interface BrainOrgan {
|
|
|
127
126
|
companionId?: string;
|
|
128
127
|
}): Promise<PersonaCompilationResult>;
|
|
129
128
|
}
|
|
130
|
-
export type
|
|
129
|
+
export type ClaimScope = 'companion' | 'user' | string;
|
|
131
130
|
export interface Claim {
|
|
132
131
|
id: string;
|
|
133
132
|
subject: string;
|
|
@@ -135,7 +134,7 @@ export interface Claim {
|
|
|
135
134
|
value: string;
|
|
136
135
|
status: ClaimStatus;
|
|
137
136
|
evidence?: string[];
|
|
138
|
-
scope?:
|
|
137
|
+
scope?: ClaimScope;
|
|
139
138
|
companionId: string;
|
|
140
139
|
provenance?: string;
|
|
141
140
|
sourceEventId?: string;
|
|
@@ -158,7 +157,6 @@ export interface BehaviorDirective {
|
|
|
158
157
|
priority: number;
|
|
159
158
|
status: DirectiveStatus;
|
|
160
159
|
supersedesId?: string;
|
|
161
|
-
memoryClass?: 'identity' | 'relationship' | 'behavioral';
|
|
162
160
|
subject?: string;
|
|
163
161
|
predicate?: string;
|
|
164
162
|
value?: string;
|
|
@@ -166,13 +164,6 @@ export interface BehaviorDirective {
|
|
|
166
164
|
validUntil?: string;
|
|
167
165
|
[key: string]: unknown;
|
|
168
166
|
}
|
|
169
|
-
export interface MemoryQueryOptions {
|
|
170
|
-
sensitivity?: string;
|
|
171
|
-
limit?: number;
|
|
172
|
-
minConfidence?: number;
|
|
173
|
-
now?: string | Date;
|
|
174
|
-
[key: string]: unknown;
|
|
175
|
-
}
|
|
176
167
|
export interface ArchiveEvent {
|
|
177
168
|
id: string;
|
|
178
169
|
companionId: string;
|
|
@@ -323,8 +314,8 @@ export interface HealthProbeResult {
|
|
|
323
314
|
}
|
|
324
315
|
export type HealthProbeFn = (context: HealthProbeContext) => Promise<HealthProbeResult> | HealthProbeResult;
|
|
325
316
|
export * from './mouth-types';
|
|
326
|
-
import type { SelfIdentity, PersonalityTraits, SelfDirective, SelfRelationship, SelfDialogueExample, LifeInventoryItem, LifeScheduleItem, LifePreference, LifeEntity, LifeEvent, LifeTask, MemoryClaim, EpisodicEvent } from './siduri-db';
|
|
327
|
-
export type { SelfIdentity, PersonalityTraits, SelfDirective, SelfRelationship, SelfDialogueExample, LifeInventoryItem, LifeScheduleItem, LifePreference, LifeEntity, LifeEvent, LifeTask, MemoryClaim, EpisodicEvent, };
|
|
317
|
+
import type { SelfIdentity, PersonalityTraits, SelfDirective, SelfRelationship, SelfDialogueExample, LifeInventoryItem, LifeScheduleItem, LifePreference, LifeEntity, LifeEvent, LifeTask, ClaimRecord, MemoryClaim, EpisodicEvent } from './siduri-db';
|
|
318
|
+
export type { SelfIdentity, PersonalityTraits, SelfDirective, SelfRelationship, SelfDialogueExample, LifeInventoryItem, LifeScheduleItem, LifePreference, LifeEntity, LifeEvent, LifeTask, ClaimRecord, MemoryClaim, EpisodicEvent, };
|
|
328
319
|
export interface SelfRepository {
|
|
329
320
|
getIdentity(companionId: string): Promise<SelfIdentity | undefined>;
|
|
330
321
|
setIdentity(identity: SelfIdentity): Promise<void>;
|
|
@@ -361,15 +352,6 @@ export interface LifeDatabase {
|
|
|
361
352
|
queryContext(companionId: string, query: string): Promise<string[]>;
|
|
362
353
|
searchLifeContext?(queryText: string): Promise<string[]>;
|
|
363
354
|
}
|
|
364
|
-
export interface EpisodicMemoryStore {
|
|
365
|
-
recordEvent(companionId: string, event: any): Promise<void>;
|
|
366
|
-
searchClaims(companionId: string, query: string, limit?: number): Promise<MemoryClaim[]>;
|
|
367
|
-
proposeClaim(claim: any): Promise<MemoryClaim>;
|
|
368
|
-
approveClaim(claimId: string): Promise<void>;
|
|
369
|
-
rejectClaim?(claimId: string): Promise<void>;
|
|
370
|
-
getApprovedClaims?(companionId: string, limit?: number): Promise<MemoryClaim[]>;
|
|
371
|
-
getRecentEvents?(companionId: string, limit?: number): Promise<EpisodicEvent[]>;
|
|
372
|
-
}
|
|
373
355
|
export interface EKnowledgeOrgan {
|
|
374
356
|
search(query: string): Promise<KnowledgeItem[]>;
|
|
375
357
|
}
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,6 @@ __exportStar(require("./context-retriever"), exports);
|
|
|
36
36
|
__exportStar(require("./prompt-compiler"), exports);
|
|
37
37
|
__exportStar(require("./cognition-planner"), exports);
|
|
38
38
|
__exportStar(require("./interaction-settler"), exports);
|
|
39
|
-
__exportStar(require("./memory-settler"), exports);
|
|
40
39
|
__exportStar(require("./action-executor"), exports);
|
|
41
40
|
__exportStar(require("./experience-emitter"), exports);
|
|
42
41
|
__exportStar(require("./response-envelope"), exports);
|
|
@@ -9,7 +9,7 @@ export interface IntentClassification {
|
|
|
9
9
|
shouldQueryKnowledge: boolean;
|
|
10
10
|
knowledgeQueries?: string[];
|
|
11
11
|
primaryQuery?: string;
|
|
12
|
-
|
|
12
|
+
archiveQueries?: string[];
|
|
13
13
|
effectiveMode: InteractionMode;
|
|
14
14
|
confidence?: number;
|
|
15
15
|
classifierOrigin?: 'heuristic' | 'cognitive' | 'ear' | 'brain';
|
|
@@ -93,12 +93,12 @@ function classifyInputIntent(text, context, overrides) {
|
|
|
93
93
|
? Array.from(new Set([...aiKnowledgeQueries, ...rawKeywords]))
|
|
94
94
|
: (shouldQueryKnowledge ? rawKeywords : []);
|
|
95
95
|
const primaryQuery = knowledgeQueries[0] || (shouldQueryKnowledge ? text.trim() : undefined);
|
|
96
|
-
const
|
|
97
|
-
? overrides.
|
|
96
|
+
const archiveQueries = (overrides?.archiveQueries && overrides.archiveQueries.length > 0)
|
|
97
|
+
? overrides.archiveQueries
|
|
98
98
|
: rawKeywords;
|
|
99
99
|
// Multi-tier Interaction Mode Resolution:
|
|
100
100
|
// 1. Overrides / Cognitive Classifier
|
|
101
|
-
// 2. Security Boundary: public channel or external source forces 'casual' (Zero
|
|
101
|
+
// 2. Security Boundary: public channel or external source forces 'casual' (Zero Drift)
|
|
102
102
|
// 3. Explicit Request Mode (context.mode: 'casual' | 'teach' | 'hybrid')
|
|
103
103
|
// 4. Default companion baseline: 'hybrid' (salience filtering)
|
|
104
104
|
let effectiveMode;
|
|
@@ -123,7 +123,7 @@ function classifyInputIntent(text, context, overrides) {
|
|
|
123
123
|
shouldQueryKnowledge,
|
|
124
124
|
knowledgeQueries,
|
|
125
125
|
primaryQuery,
|
|
126
|
-
|
|
126
|
+
archiveQueries,
|
|
127
127
|
effectiveMode,
|
|
128
128
|
confidence: overrides?.confidence ?? 0.95,
|
|
129
129
|
classifierOrigin: overrides?.classifierOrigin ?? 'heuristic',
|
|
@@ -80,7 +80,7 @@ describe('IntentClassifier', () => {
|
|
|
80
80
|
expect((0, intent_classifier_1.classifyInputIntent)('How are you doing?', casualContext).effectiveMode).toBe('casual');
|
|
81
81
|
expect((0, intent_classifier_1.classifyInputIntent)('Tell me a joke', casualContext).effectiveMode).toBe('casual');
|
|
82
82
|
});
|
|
83
|
-
test('enforces casual mode (Zero
|
|
83
|
+
test('enforces casual mode (Zero Drift) on public channel or external source boundary', () => {
|
|
84
84
|
const publicContext = {
|
|
85
85
|
...dummyContext,
|
|
86
86
|
conversation: { channel: 'public', correlationId: 'corr-pub' },
|