@siduri-x/core 1.0.7 → 1.0.8
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/action-policy.test.js +0 -1
- package/dist/adversarial.test.js +11 -15
- package/dist/capability.test.js +0 -1
- package/dist/context-retriever.js +0 -2
- package/dist/context.d.ts +1 -2
- package/dist/dispatcher.test.js +0 -2
- package/dist/evidence.d.ts +1 -4
- package/dist/evidence.js +2 -22
- package/dist/evidence.test.js +11 -37
- package/dist/experience-emitter.js +0 -1
- package/dist/experience.d.ts +0 -2
- package/dist/experience.js +0 -5
- package/dist/experience.test.js +0 -4
- package/dist/gating.d.ts +0 -1
- package/dist/gating.js +0 -2
- package/dist/gating.test.js +9 -13
- package/dist/intent-classifier.test.js +0 -1
- package/dist/memory-settler.js +0 -3
- package/dist/perception-cycle.test.js +2 -4
- package/dist/prompt-compiler.js +0 -3
- package/dist/prompt-compiler.test.js +0 -1
- package/dist/proposals.d.ts +0 -1
- package/dist/runtime.js +1 -1
- package/dist/sqlite-action-store.test.js +0 -1
- package/dist/teaching.d.ts +2 -2
- package/dist/teaching.js +5 -32
- package/package.json +1 -1
package/dist/adversarial.test.js
CHANGED
|
@@ -14,7 +14,6 @@ describe('Adversarial Hardening Verification Suite (Phase 3)', () => {
|
|
|
14
14
|
},
|
|
15
15
|
conversation: {
|
|
16
16
|
channel: 'private',
|
|
17
|
-
audienceId: 'audience-owner',
|
|
18
17
|
correlationId: 'corr-adv-1',
|
|
19
18
|
},
|
|
20
19
|
};
|
|
@@ -29,7 +28,6 @@ describe('Adversarial Hardening Verification Suite (Phase 3)', () => {
|
|
|
29
28
|
},
|
|
30
29
|
conversation: {
|
|
31
30
|
channel: 'public',
|
|
32
|
-
audienceId: 'audience-public',
|
|
33
31
|
correlationId: 'corr-adv-2',
|
|
34
32
|
},
|
|
35
33
|
};
|
|
@@ -86,7 +84,7 @@ describe('Adversarial Hardening Verification Suite (Phase 3)', () => {
|
|
|
86
84
|
...baseOwnerContext,
|
|
87
85
|
companionId: 'companion-A',
|
|
88
86
|
});
|
|
89
|
-
expect(mockMemory.searchClaims).toHaveBeenCalledWith('Query', expect.objectContaining({
|
|
87
|
+
expect(mockMemory.searchClaims).toHaveBeenCalledWith('Query', expect.objectContaining({ limit: 5 }), 5);
|
|
90
88
|
});
|
|
91
89
|
});
|
|
92
90
|
// INVARIANT 2: Authority & Request Boundary
|
|
@@ -378,41 +376,39 @@ describe('Adversarial Hardening Verification Suite (Phase 3)', () => {
|
|
|
378
376
|
describe('Invariant 8: Response Gating Evidence Admissibility Semantics', () => {
|
|
379
377
|
test('gate strictly enforces evidence admissibility and disclosure without claiming unverified factuality', () => {
|
|
380
378
|
const gating = new index_1.ResponseGatingEngine();
|
|
381
|
-
const
|
|
379
|
+
const validEvidence = {
|
|
382
380
|
evidenceId: 'ev-pub-1',
|
|
383
381
|
sourceId: 'src-facts',
|
|
384
382
|
origin: 'knowledge',
|
|
385
383
|
trust: 'configured',
|
|
386
384
|
sensitivity: 'public',
|
|
387
|
-
allowedAudiences: ['audience-public'],
|
|
388
385
|
companionId: 'companion-adv',
|
|
389
386
|
correlationId: 'corr-adv-1',
|
|
390
387
|
createdAt: new Date().toISOString(),
|
|
391
388
|
};
|
|
392
|
-
const
|
|
393
|
-
evidenceId: 'ev-
|
|
389
|
+
const foreignCompanionEvidence = {
|
|
390
|
+
evidenceId: 'ev-foreign-1',
|
|
394
391
|
sourceId: 'src-secrets',
|
|
395
392
|
origin: 'knowledge',
|
|
396
393
|
trust: 'configured',
|
|
397
394
|
sensitivity: 'restricted',
|
|
398
|
-
|
|
399
|
-
companionId: 'companion-adv',
|
|
395
|
+
companionId: 'foreign-companion',
|
|
400
396
|
correlationId: 'corr-adv-1',
|
|
401
397
|
createdAt: new Date().toISOString(),
|
|
402
398
|
};
|
|
403
|
-
// Staged for
|
|
399
|
+
// Staged for companion-adv with both valid and foreign-companion evidence attached
|
|
404
400
|
const staged = gating.stageResponse({
|
|
405
|
-
requestContext:
|
|
401
|
+
requestContext: baseOwnerContext,
|
|
406
402
|
candidateSpeech: 'Siduri was created in 1840 by aliens.',
|
|
407
403
|
candidateLanguage: 'en',
|
|
408
|
-
evidenceRecords: [
|
|
404
|
+
evidenceRecords: [validEvidence, foreignCompanionEvidence],
|
|
409
405
|
});
|
|
410
|
-
const evaluation = gating.evaluateGate(staged, [
|
|
406
|
+
const evaluation = gating.evaluateGate(staged, [validEvidence, foreignCompanionEvidence]);
|
|
411
407
|
expect(evaluation.admissible).toBe(true);
|
|
412
408
|
expect(evaluation.reasonCode).toBe('APPROVED_DIRECT');
|
|
413
|
-
//
|
|
409
|
+
// Valid companion evidence admitted, foreign companion evidence excluded by isolation boundary
|
|
414
410
|
expect(evaluation.filteredEvidenceIds).toEqual(['ev-pub-1']);
|
|
415
|
-
expect(evaluation.filteredEvidenceIds).not.toContain('ev-
|
|
411
|
+
expect(evaluation.filteredEvidenceIds).not.toContain('ev-foreign-1');
|
|
416
412
|
});
|
|
417
413
|
});
|
|
418
414
|
// INVARIANT 9: Full-Field Tamper-Evident Audit Trail
|
package/dist/capability.test.js
CHANGED
|
@@ -9,8 +9,6 @@ async function retrieveRuntimeContext(params) {
|
|
|
9
9
|
const { companionId, perceivedText, requestContext, role, isContextObject, shouldQueryKnowledge, knowledge, memory, } = params;
|
|
10
10
|
const queryOptions = isContextObject
|
|
11
11
|
? {
|
|
12
|
-
channel: requestContext.conversation.channel,
|
|
13
|
-
audienceId: requestContext.conversation.audienceId,
|
|
14
12
|
limit: 5,
|
|
15
13
|
}
|
|
16
14
|
: role;
|
package/dist/context.d.ts
CHANGED
|
@@ -9,7 +9,6 @@ export interface ConversationContext {
|
|
|
9
9
|
correlationId: string;
|
|
10
10
|
sessionId?: string;
|
|
11
11
|
channel?: string;
|
|
12
|
-
audienceId?: string;
|
|
13
12
|
[key: string]: unknown;
|
|
14
13
|
}
|
|
15
14
|
export type SubjectKind = 'actor' | 'companion' | 'configured';
|
|
@@ -27,7 +26,7 @@ export interface RequestContext {
|
|
|
27
26
|
metadata?: Record<string, unknown>;
|
|
28
27
|
}
|
|
29
28
|
export type DiagnosticCode = 'legacy_role_removed' | 'anonymous_session_generated' | 'companion_default_mapped_for_bootstrap' | 'actor_scoped_subject_mapped';
|
|
30
|
-
export type ContextErrorCode = 'MISSING_CONTEXT' | 'INVALID_CONTEXT' | 'FORBIDDEN_CONTEXT' | '
|
|
29
|
+
export type ContextErrorCode = 'MISSING_CONTEXT' | 'INVALID_CONTEXT' | 'FORBIDDEN_CONTEXT' | 'AMBIGUOUS_CONTEXT' | 'UNAUTHORIZED_CAPABILITY';
|
|
31
30
|
export interface ContextError {
|
|
32
31
|
code: ContextErrorCode;
|
|
33
32
|
message?: string;
|
package/dist/dispatcher.test.js
CHANGED
|
@@ -33,7 +33,6 @@ describe('T5 ExperienceDispatcher Contract Suite', () => {
|
|
|
33
33
|
companionId: 'companion-a',
|
|
34
34
|
correlationId: 'corr-1',
|
|
35
35
|
channel: 'public',
|
|
36
|
-
audienceId: 'audience-public',
|
|
37
36
|
speech: 'Hello dispatch',
|
|
38
37
|
language: 'en',
|
|
39
38
|
});
|
|
@@ -50,7 +49,6 @@ describe('T5 ExperienceDispatcher Contract Suite', () => {
|
|
|
50
49
|
companionId: 'companion-a',
|
|
51
50
|
correlationId: 'corr-1',
|
|
52
51
|
channel: 'public',
|
|
53
|
-
audienceId: 'audience-public',
|
|
54
52
|
speech: 'Hello empty',
|
|
55
53
|
});
|
|
56
54
|
const summary = await emptyDispatcher.dispatchEvents(events);
|
package/dist/evidence.d.ts
CHANGED
|
@@ -16,13 +16,12 @@ export interface EvidenceRecord {
|
|
|
16
16
|
expiresAt?: string;
|
|
17
17
|
trust: EvidenceTrust;
|
|
18
18
|
sensitivity?: EvidenceSensitivity;
|
|
19
|
-
allowedAudiences?: string[];
|
|
20
19
|
companionId: string;
|
|
21
20
|
correlationId: string;
|
|
22
21
|
[key: string]: unknown;
|
|
23
22
|
}
|
|
24
23
|
export type ResponseApprovalStatus = 'STAGED' | 'APPROVED' | 'REJECTED' | 'EXPIRED' | 'EMITTED';
|
|
25
|
-
export type ResponseGateReasonCode = 'APPROVED_DIRECT' | 'APPROVAL_REQUIRED' | 'UNKNOWN_APPROVAL_ID' | 'APPROVAL_ID_MISMATCH' | 'COMPANION_MISMATCH' | '
|
|
24
|
+
export type ResponseGateReasonCode = 'APPROVED_DIRECT' | 'APPROVAL_REQUIRED' | 'UNKNOWN_APPROVAL_ID' | 'APPROVAL_ID_MISMATCH' | 'COMPANION_MISMATCH' | 'EVIDENCE_EXPIRED' | 'EVIDENCE_SENSITIVITY_EXCLUDED' | 'UNRESOLVED_LOW_CONFIDENCE' | 'EMPTY_SPEECH' | 'PROPOSAL_VALIDATION_FAILED' | 'EXPLICITLY_REJECTED';
|
|
26
25
|
export interface ResponseCitation {
|
|
27
26
|
sourceId: string;
|
|
28
27
|
documentId?: string;
|
|
@@ -35,7 +34,6 @@ export interface StagedResponsePlan {
|
|
|
35
34
|
companionId: string;
|
|
36
35
|
correlationId: string;
|
|
37
36
|
channel?: string;
|
|
38
|
-
audienceId?: string;
|
|
39
37
|
speech: string;
|
|
40
38
|
language: string;
|
|
41
39
|
evidenceIds: string[];
|
|
@@ -63,7 +61,6 @@ export interface ResponseGateEvaluation {
|
|
|
63
61
|
export interface EvidenceFilterOptions {
|
|
64
62
|
companionId: string;
|
|
65
63
|
channel?: string;
|
|
66
|
-
audienceId?: string;
|
|
67
64
|
now?: string | Date;
|
|
68
65
|
[key: string]: unknown;
|
|
69
66
|
}
|
package/dist/evidence.js
CHANGED
|
@@ -19,28 +19,8 @@ function filterEvidenceRecords(records, options) {
|
|
|
19
19
|
continue;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
record.allowedAudiences &&
|
|
25
|
-
record.allowedAudiences.length > 0 &&
|
|
26
|
-
!record.allowedAudiences.includes('audience-public') &&
|
|
27
|
-
!record.allowedAudiences.includes(options.audienceId)) {
|
|
28
|
-
excluded.push({ record, reason: 'audience_not_allowed' });
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
// 4. Optional channel sensitivity policy (if channel explicitly specified)
|
|
32
|
-
if (options.channel === 'public') {
|
|
33
|
-
if (record.sensitivity && record.sensitivity !== 'public') {
|
|
34
|
-
excluded.push({ record, reason: 'sensitivity_private_in_public_channel' });
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
else if (options.channel === 'direct') {
|
|
39
|
-
if (record.sensitivity === 'restricted') {
|
|
40
|
-
excluded.push({ record, reason: 'sensitivity_restricted_in_direct_channel' });
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
22
|
+
// In single-owner architecture, memory and evidence are partitioned strictly
|
|
23
|
+
// by companion boundary (companionId) and temporal expiration.
|
|
44
24
|
admitted.push(record);
|
|
45
25
|
}
|
|
46
26
|
return { admitted, excluded };
|
package/dist/evidence.test.js
CHANGED
|
@@ -8,7 +8,6 @@ describe('T4 Evidence & Disclosure Core Contract', () => {
|
|
|
8
8
|
origin: 'knowledge',
|
|
9
9
|
trust: 'configured',
|
|
10
10
|
sensitivity: 'public',
|
|
11
|
-
allowedAudiences: ['audience-public'],
|
|
12
11
|
companionId: 'companion-a',
|
|
13
12
|
correlationId: 'corr-1',
|
|
14
13
|
createdAt: new Date(Date.now() - 5000).toISOString(),
|
|
@@ -21,7 +20,6 @@ describe('T4 Evidence & Disclosure Core Contract', () => {
|
|
|
21
20
|
const options = {
|
|
22
21
|
companionId: 'companion-a',
|
|
23
22
|
channel: 'public',
|
|
24
|
-
audienceId: 'audience-public',
|
|
25
23
|
};
|
|
26
24
|
const { admitted, excluded } = (0, evidence_1.filterEvidenceRecords)(records, options);
|
|
27
25
|
expect(admitted.map((e) => e.evidenceId)).toEqual(['ev-mine']);
|
|
@@ -40,7 +38,6 @@ describe('T4 Evidence & Disclosure Core Contract', () => {
|
|
|
40
38
|
const options = {
|
|
41
39
|
companionId: 'companion-a',
|
|
42
40
|
channel: 'public',
|
|
43
|
-
audienceId: 'audience-public',
|
|
44
41
|
};
|
|
45
42
|
const { admitted, excluded } = (0, evidence_1.filterEvidenceRecords)(records, options);
|
|
46
43
|
expect(admitted.map((e) => e.evidenceId)).toEqual(['ev-valid']);
|
|
@@ -51,51 +48,28 @@ describe('T4 Evidence & Disclosure Core Contract', () => {
|
|
|
51
48
|
}),
|
|
52
49
|
]);
|
|
53
50
|
});
|
|
54
|
-
test('
|
|
51
|
+
test('single-owner companion admits valid evidence without multi-audience filtering', () => {
|
|
55
52
|
const records = [
|
|
56
|
-
{ ...baseRecord, evidenceId: 'ev-public'
|
|
57
|
-
{ ...baseRecord, evidenceId: 'ev-direct-only'
|
|
53
|
+
{ ...baseRecord, evidenceId: 'ev-public' },
|
|
54
|
+
{ ...baseRecord, evidenceId: 'ev-direct-only' },
|
|
58
55
|
];
|
|
59
56
|
const options = {
|
|
60
57
|
companionId: 'companion-a',
|
|
61
|
-
channel: 'public',
|
|
62
|
-
audienceId: 'audience-public',
|
|
63
58
|
};
|
|
64
59
|
const { admitted, excluded } = (0, evidence_1.filterEvidenceRecords)(records, options);
|
|
65
|
-
expect(admitted.map((e) => e.evidenceId)).toEqual(['ev-public']);
|
|
66
|
-
expect(excluded).toEqual([
|
|
67
|
-
expect.objectContaining({
|
|
68
|
-
record: expect.objectContaining({ evidenceId: 'ev-direct-only' }),
|
|
69
|
-
reason: 'audience_not_allowed',
|
|
70
|
-
}),
|
|
71
|
-
]);
|
|
72
|
-
});
|
|
73
|
-
test('sensitivity policy excludes private and restricted evidence from public channels', () => {
|
|
74
|
-
const records = [
|
|
75
|
-
{ ...baseRecord, evidenceId: 'ev-pub', sensitivity: 'public', allowedAudiences: ['audience-public'] },
|
|
76
|
-
{ ...baseRecord, evidenceId: 'ev-priv', sensitivity: 'private', allowedAudiences: ['audience-public'] },
|
|
77
|
-
{ ...baseRecord, evidenceId: 'ev-rest', sensitivity: 'restricted', allowedAudiences: ['audience-public'] },
|
|
78
|
-
];
|
|
79
|
-
const { admitted, excluded } = (0, evidence_1.filterEvidenceRecords)(records, {
|
|
80
|
-
companionId: 'companion-a',
|
|
81
|
-
channel: 'public',
|
|
82
|
-
audienceId: 'audience-public',
|
|
83
|
-
});
|
|
84
|
-
expect(admitted.map((e) => e.evidenceId)).toEqual(['ev-pub']);
|
|
85
|
-
expect(excluded.map((e) => e.record.evidenceId)).toEqual(['ev-priv', 'ev-rest']);
|
|
60
|
+
expect(admitted.map((e) => e.evidenceId)).toEqual(['ev-public', 'ev-direct-only']);
|
|
61
|
+
expect(excluded).toEqual([]);
|
|
86
62
|
});
|
|
87
|
-
test('
|
|
63
|
+
test('single-owner companion admits private and restricted sensitivity for companion owner', () => {
|
|
88
64
|
const records = [
|
|
89
|
-
{ ...baseRecord, evidenceId: 'ev-pub', sensitivity: 'public'
|
|
90
|
-
{ ...baseRecord, evidenceId: 'ev-priv', sensitivity: 'private'
|
|
91
|
-
{ ...baseRecord, evidenceId: 'ev-rest', sensitivity: 'restricted'
|
|
65
|
+
{ ...baseRecord, evidenceId: 'ev-pub', sensitivity: 'public' },
|
|
66
|
+
{ ...baseRecord, evidenceId: 'ev-priv', sensitivity: 'private' },
|
|
67
|
+
{ ...baseRecord, evidenceId: 'ev-rest', sensitivity: 'restricted' },
|
|
92
68
|
];
|
|
93
69
|
const { admitted, excluded } = (0, evidence_1.filterEvidenceRecords)(records, {
|
|
94
70
|
companionId: 'companion-a',
|
|
95
|
-
channel: 'direct',
|
|
96
|
-
audienceId: 'audience-direct-a',
|
|
97
71
|
});
|
|
98
|
-
expect(admitted.map((e) => e.evidenceId)).toEqual(['ev-pub', 'ev-priv']);
|
|
99
|
-
expect(excluded
|
|
72
|
+
expect(admitted.map((e) => e.evidenceId)).toEqual(['ev-pub', 'ev-priv', 'ev-rest']);
|
|
73
|
+
expect(excluded).toEqual([]);
|
|
100
74
|
});
|
|
101
75
|
});
|
|
@@ -13,7 +13,6 @@ async function emitExperienceEvents(params) {
|
|
|
13
13
|
companionId,
|
|
14
14
|
correlationId: requestContext.conversation.correlationId,
|
|
15
15
|
channel: requestContext.conversation?.channel,
|
|
16
|
-
audienceId: requestContext.conversation?.audienceId,
|
|
17
16
|
speech,
|
|
18
17
|
language: language || 'ja',
|
|
19
18
|
evidenceIds: gateEval.filteredEvidenceIds,
|
package/dist/experience.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export interface ExperienceEvent {
|
|
|
7
7
|
responseId: string;
|
|
8
8
|
correlationId: string;
|
|
9
9
|
channel?: string;
|
|
10
|
-
audienceId?: string;
|
|
11
10
|
approval: 'APPROVED';
|
|
12
11
|
kind: ExperienceEventKind;
|
|
13
12
|
lifecycle: ExperienceEventLifecycle;
|
|
@@ -39,7 +38,6 @@ export interface CreateExperienceEventsOptions {
|
|
|
39
38
|
companionId: string;
|
|
40
39
|
correlationId: string;
|
|
41
40
|
channel?: string;
|
|
42
|
-
audienceId?: string;
|
|
43
41
|
speech: string;
|
|
44
42
|
language?: string;
|
|
45
43
|
evidenceIds?: string[];
|
package/dist/experience.js
CHANGED
|
@@ -17,7 +17,6 @@ function createExperienceEvents(options) {
|
|
|
17
17
|
responseId: options.responseId,
|
|
18
18
|
correlationId: options.correlationId,
|
|
19
19
|
channel: options.channel,
|
|
20
|
-
audienceId: options.audienceId,
|
|
21
20
|
approval: 'APPROVED',
|
|
22
21
|
kind: 'voice',
|
|
23
22
|
lifecycle: 'STARTED',
|
|
@@ -35,7 +34,6 @@ function createExperienceEvents(options) {
|
|
|
35
34
|
responseId: options.responseId,
|
|
36
35
|
correlationId: options.correlationId,
|
|
37
36
|
channel: options.channel,
|
|
38
|
-
audienceId: options.audienceId,
|
|
39
37
|
approval: 'APPROVED',
|
|
40
38
|
kind: 'avatar',
|
|
41
39
|
lifecycle: 'STARTED',
|
|
@@ -62,9 +60,6 @@ function validateExperienceEvent(event) {
|
|
|
62
60
|
return { valid: false, error: 'Missing or invalid responseId' };
|
|
63
61
|
if (!e.correlationId || typeof e.correlationId !== 'string')
|
|
64
62
|
return { valid: false, error: 'Missing or invalid correlationId' };
|
|
65
|
-
if (e.audienceId !== undefined && typeof e.audienceId !== 'string') {
|
|
66
|
-
return { valid: false, error: 'Invalid audienceId: must be a string' };
|
|
67
|
-
}
|
|
68
63
|
if (e.approval !== 'APPROVED')
|
|
69
64
|
return { valid: false, error: 'Event approval must be APPROVED' };
|
|
70
65
|
if (!['voice', 'caption', 'avatar', 'platform_action'].includes(e.kind)) {
|
package/dist/experience.test.js
CHANGED
|
@@ -7,7 +7,6 @@ describe('T5 Experience Event Contract Suite', () => {
|
|
|
7
7
|
companionId: 'companion-a',
|
|
8
8
|
correlationId: 'corr-123',
|
|
9
9
|
channel: 'public',
|
|
10
|
-
audienceId: 'audience-public',
|
|
11
10
|
speech: 'Hello world',
|
|
12
11
|
language: 'en',
|
|
13
12
|
evidenceIds: ['ev-1'],
|
|
@@ -52,8 +51,5 @@ describe('T5 Experience Event Contract Suite', () => {
|
|
|
52
51
|
expect((0, experience_1.validateExperienceEvent)(missingCompanion).valid).toBe(false);
|
|
53
52
|
const missingResponseId = { ...events[0], responseId: '' };
|
|
54
53
|
expect((0, experience_1.validateExperienceEvent)(missingResponseId).valid).toBe(false);
|
|
55
|
-
const withoutAudience = { ...events[0] };
|
|
56
|
-
delete withoutAudience.audienceId;
|
|
57
|
-
expect((0, experience_1.validateExperienceEvent)(withoutAudience).valid).toBe(true);
|
|
58
54
|
});
|
|
59
55
|
});
|
package/dist/gating.d.ts
CHANGED
package/dist/gating.js
CHANGED
|
@@ -40,7 +40,6 @@ class ResponseGatingEngine {
|
|
|
40
40
|
companionId: requestContext.companionId,
|
|
41
41
|
correlationId: requestContext.conversation.correlationId,
|
|
42
42
|
channel: requestContext.conversation?.channel,
|
|
43
|
-
audienceId: requestContext.conversation?.audienceId,
|
|
44
43
|
speech: options.candidateSpeech,
|
|
45
44
|
language: options.candidateLanguage,
|
|
46
45
|
evidenceIds,
|
|
@@ -90,7 +89,6 @@ class ResponseGatingEngine {
|
|
|
90
89
|
const { admitted, excluded } = (0, evidence_1.filterEvidenceRecords)(attachedEvidence, {
|
|
91
90
|
companionId: staged.companionId,
|
|
92
91
|
channel: staged.channel,
|
|
93
|
-
audienceId: staged.audienceId,
|
|
94
92
|
now,
|
|
95
93
|
});
|
|
96
94
|
// If any evidence attached to this plan violated disclosure in this channel, exclude it
|
package/dist/gating.test.js
CHANGED
|
@@ -14,7 +14,6 @@ describe('T4 Response Gating & Staged Approval Suite', () => {
|
|
|
14
14
|
},
|
|
15
15
|
conversation: {
|
|
16
16
|
channel: 'public',
|
|
17
|
-
audienceId: 'audience-public',
|
|
18
17
|
correlationId: 'corr-gate-1',
|
|
19
18
|
},
|
|
20
19
|
};
|
|
@@ -28,7 +27,6 @@ describe('T4 Response Gating & Staged Approval Suite', () => {
|
|
|
28
27
|
origin: 'knowledge',
|
|
29
28
|
trust: 'configured',
|
|
30
29
|
sensitivity: 'public',
|
|
31
|
-
allowedAudiences: ['audience-public'],
|
|
32
30
|
companionId: 'companion-a',
|
|
33
31
|
correlationId: 'corr-gate-1',
|
|
34
32
|
createdAt: new Date().toISOString(),
|
|
@@ -56,7 +54,6 @@ describe('T4 Response Gating & Staged Approval Suite', () => {
|
|
|
56
54
|
origin: 'ocr',
|
|
57
55
|
trust: 'untrusted',
|
|
58
56
|
sensitivity: 'public',
|
|
59
|
-
allowedAudiences: ['audience-public'],
|
|
60
57
|
companionId: 'companion-a',
|
|
61
58
|
correlationId: 'corr-gate-2',
|
|
62
59
|
createdAt: new Date().toISOString(),
|
|
@@ -162,28 +159,27 @@ describe('T4 Response Gating & Staged Approval Suite', () => {
|
|
|
162
159
|
expect(approveRes.success).toBe(false);
|
|
163
160
|
expect(approveRes.reason).toBe('EVIDENCE_EXPIRED');
|
|
164
161
|
});
|
|
165
|
-
test('
|
|
166
|
-
const
|
|
167
|
-
evidenceId: 'ev-
|
|
162
|
+
test('foreign companion evidence is filtered out and absent from citations/evidence list', () => {
|
|
163
|
+
const foreignEvidence = {
|
|
164
|
+
evidenceId: 'ev-foreign-1',
|
|
168
165
|
sourceId: 'src-secret',
|
|
169
166
|
origin: 'knowledge',
|
|
170
167
|
trust: 'configured',
|
|
171
168
|
sensitivity: 'private',
|
|
172
|
-
|
|
173
|
-
companionId: 'companion-a',
|
|
169
|
+
companionId: 'companion-b',
|
|
174
170
|
correlationId: 'corr-gate-1',
|
|
175
171
|
createdAt: new Date().toISOString(),
|
|
176
172
|
};
|
|
177
173
|
const staged = engine.stageResponse({
|
|
178
|
-
requestContext: validPublicContext, //
|
|
179
|
-
candidateSpeech: '
|
|
174
|
+
requestContext: validPublicContext, // companion-a
|
|
175
|
+
candidateSpeech: 'Response text',
|
|
180
176
|
candidateLanguage: 'en',
|
|
181
|
-
evidenceRecords: [
|
|
177
|
+
evidenceRecords: [foreignEvidence],
|
|
182
178
|
citations: [{ sourceId: 'src-secret' }],
|
|
183
179
|
});
|
|
184
|
-
const evalRes = engine.evaluateGate(staged, [
|
|
180
|
+
const evalRes = engine.evaluateGate(staged, [foreignEvidence]);
|
|
185
181
|
expect(evalRes.admissible).toBe(true);
|
|
186
|
-
//
|
|
182
|
+
// Foreign companion evidence and its citation must be stripped due to companion isolation
|
|
187
183
|
expect(evalRes.filteredEvidenceIds).toEqual([]);
|
|
188
184
|
expect(evalRes.filteredCitations).toEqual([]);
|
|
189
185
|
});
|
package/dist/memory-settler.js
CHANGED
|
@@ -26,7 +26,6 @@ async function settleMemoryProposals(params) {
|
|
|
26
26
|
companionId,
|
|
27
27
|
actorId: requestContext.actor.actorId,
|
|
28
28
|
channel: requestContext.conversation.channel,
|
|
29
|
-
audienceId: requestContext.conversation.audienceId,
|
|
30
29
|
},
|
|
31
30
|
};
|
|
32
31
|
await memory.addSourceEvent(sourceEvent);
|
|
@@ -47,7 +46,6 @@ async function settleMemoryProposals(params) {
|
|
|
47
46
|
userConfirmation: 'none',
|
|
48
47
|
sensitivity: claim.sensitivity ||
|
|
49
48
|
(requestContext.conversation?.channel === 'public' ? 'public' : 'private'),
|
|
50
|
-
allowedAudiences: claim.allowedAudiences || (requestContext.conversation?.audienceId ? [requestContext.conversation.audienceId] : undefined),
|
|
51
49
|
});
|
|
52
50
|
createdMemoryProposals.push(proposal);
|
|
53
51
|
}
|
|
@@ -63,7 +61,6 @@ async function settleMemoryProposals(params) {
|
|
|
63
61
|
sourceEventId: sourceEventId || p.sourceEventId,
|
|
64
62
|
claimType: p.claimType || 'semantic',
|
|
65
63
|
sensitivity: p.sensitivity || 'private',
|
|
66
|
-
allowedAudiences: p.allowedAudiences || (requestContext.conversation?.audienceId ? [requestContext.conversation.audienceId] : undefined),
|
|
67
64
|
});
|
|
68
65
|
createdMemoryProposals.push(proposal);
|
|
69
66
|
}
|
|
@@ -23,7 +23,6 @@ describe('SiduriRuntime Unified Perception Cycle & Session History', () => {
|
|
|
23
23
|
},
|
|
24
24
|
conversation: {
|
|
25
25
|
channel: 'direct',
|
|
26
|
-
audienceId: 'aud-direct',
|
|
27
26
|
correlationId: 'corr-perc-1',
|
|
28
27
|
},
|
|
29
28
|
};
|
|
@@ -89,7 +88,7 @@ describe('SiduriRuntime Unified Perception Cycle & Session History', () => {
|
|
|
89
88
|
capabilities: ['chat:public'],
|
|
90
89
|
authenticated: true,
|
|
91
90
|
},
|
|
92
|
-
conversation: { channel: 'direct',
|
|
91
|
+
conversation: { channel: 'direct', correlationId: 'c1' },
|
|
93
92
|
};
|
|
94
93
|
const bobContext = {
|
|
95
94
|
companionId: 'comp-multi',
|
|
@@ -100,7 +99,7 @@ describe('SiduriRuntime Unified Perception Cycle & Session History', () => {
|
|
|
100
99
|
capabilities: ['chat:public'],
|
|
101
100
|
authenticated: false,
|
|
102
101
|
},
|
|
103
|
-
conversation: { channel: 'public',
|
|
102
|
+
conversation: { channel: 'public', correlationId: 'c2' },
|
|
104
103
|
};
|
|
105
104
|
await runtime.handleUserMessage('Alice secret message', aliceContext);
|
|
106
105
|
await runtime.handleUserMessage('Bob public query', bobContext);
|
|
@@ -122,7 +121,6 @@ describe('SiduriRuntime Unified Perception Cycle & Session History', () => {
|
|
|
122
121
|
origin: 'knowledge',
|
|
123
122
|
trust: 'configured',
|
|
124
123
|
sensitivity: 'public',
|
|
125
|
-
allowedAudiences: ['audience-public'],
|
|
126
124
|
companionId: 'comp-native-ev',
|
|
127
125
|
correlationId: 'corr-test',
|
|
128
126
|
createdAt: new Date().toISOString(),
|
package/dist/prompt-compiler.js
CHANGED
|
@@ -32,11 +32,8 @@ async function compilePrompts(params) {
|
|
|
32
32
|
// Compile Behavior with neutral context metadata
|
|
33
33
|
const behaviorInjections = behavior && typeof behavior.compile === 'function'
|
|
34
34
|
? await behavior.compile({
|
|
35
|
-
activeRole: role,
|
|
36
35
|
directives: activeDirectives,
|
|
37
36
|
companionId,
|
|
38
|
-
channel: requestContext.conversation.channel,
|
|
39
|
-
audienceId: requestContext.conversation.audienceId,
|
|
40
37
|
actorId: requestContext.actor.actorId,
|
|
41
38
|
})
|
|
42
39
|
: '';
|
package/dist/proposals.d.ts
CHANGED
package/dist/runtime.js
CHANGED
|
@@ -214,7 +214,7 @@ class SiduriRuntime {
|
|
|
214
214
|
// 1. Input validation, RequestContext synthesis, and Ear perception routing
|
|
215
215
|
const input = await (0, input_normalizer_1.normalizeUserInput)(rawText, roleOrContext, history, this.id, this.ear);
|
|
216
216
|
const sessionKey = input.requestContext.actor.sessionId ||
|
|
217
|
-
input.requestContext.conversation.
|
|
217
|
+
input.requestContext.conversation.correlationId ||
|
|
218
218
|
'default';
|
|
219
219
|
const currentMessage = { role: 'user', content: input.perceivedText };
|
|
220
220
|
const boundedSessionHistory = [...input.boundedHistory, currentMessage].slice(-20);
|
package/dist/teaching.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ export interface ExtractedTeaching {
|
|
|
4
4
|
behaviorProposals: BehaviorProposal[];
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
* Deterministically extracts teaching candidates from user messages according to
|
|
7
|
+
* Deterministically extracts teaching candidates from user messages according to single-owner model.
|
|
8
8
|
*
|
|
9
9
|
* Rules:
|
|
10
10
|
* - Scoped to the requesting actor context (subject: `actor:${actorId}`), NEVER `primary_user`.
|
|
11
11
|
* - Candidates are pending proposals only, never active/approved.
|
|
12
|
-
* -
|
|
12
|
+
* - In a single-owner companion, preferences apply across the companion instance without audience partitioning.
|
|
13
13
|
* - Companion identity is isolated.
|
|
14
14
|
*/
|
|
15
15
|
export declare function extractDeterministicTeaching(message: string, context?: RequestContext, sourceEventId?: string): ExtractedTeaching;
|
package/dist/teaching.js
CHANGED
|
@@ -5,12 +5,12 @@ function cleanValue(value, limit = 160) {
|
|
|
5
5
|
return value.replace(/\s+/g, ' ').replace(/^[ .,!?:;"']+|[ .,!?:;"']+$/g, '').slice(0, limit);
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Deterministically extracts teaching candidates from user messages according to
|
|
8
|
+
* Deterministically extracts teaching candidates from user messages according to single-owner model.
|
|
9
9
|
*
|
|
10
10
|
* Rules:
|
|
11
11
|
* - Scoped to the requesting actor context (subject: `actor:${actorId}`), NEVER `primary_user`.
|
|
12
12
|
* - Candidates are pending proposals only, never active/approved.
|
|
13
|
-
* -
|
|
13
|
+
* - In a single-owner companion, preferences apply across the companion instance without audience partitioning.
|
|
14
14
|
* - Companion identity is isolated.
|
|
15
15
|
*/
|
|
16
16
|
function extractDeterministicTeaching(message, context, sourceEventId) {
|
|
@@ -23,7 +23,6 @@ function extractDeterministicTeaching(message, context, sourceEventId) {
|
|
|
23
23
|
const actorId = context?.actor?.actorId;
|
|
24
24
|
const actorSubject = actorId ? `actor:${actorId}` : 'actor:anonymous';
|
|
25
25
|
const companionId = context?.companionId || 'default';
|
|
26
|
-
const defaultAudience = context?.conversation?.audienceId || (context?.conversation?.channel === 'direct' ? `audience-direct-${actorId}` : 'audience-public');
|
|
27
26
|
const sensitivity = context?.conversation?.channel === 'public' ? 'public' : 'private';
|
|
28
27
|
// 1. Companion's Name: "your name is X" / "you are called X"
|
|
29
28
|
const companionNameMatch = text.match(/\b(?:your name is|you are called)\s+(.+?)(?=\s+and\s+(?:i\b|my\b|you\b)|[.;,]|$)/i);
|
|
@@ -37,7 +36,6 @@ function extractDeterministicTeaching(message, context, sourceEventId) {
|
|
|
37
36
|
claimType: 'semantic',
|
|
38
37
|
provenance: 'deterministic_teaching',
|
|
39
38
|
sensitivity: 'public',
|
|
40
|
-
allowedAudiences: ['audience-public'],
|
|
41
39
|
sourceEventId,
|
|
42
40
|
});
|
|
43
41
|
behaviorProposals.push({
|
|
@@ -62,36 +60,14 @@ function extractDeterministicTeaching(message, context, sourceEventId) {
|
|
|
62
60
|
claimType: 'preference',
|
|
63
61
|
provenance: 'deterministic_teaching',
|
|
64
62
|
sensitivity,
|
|
65
|
-
allowedAudiences: [defaultAudience],
|
|
66
63
|
sourceEventId,
|
|
67
64
|
});
|
|
68
65
|
}
|
|
69
66
|
// 3. Preferred Address / Call me X: "call me X"
|
|
70
|
-
const callMeMatch = text.match(/\b(?:(?:from now on|only),?\s*)?call me\s+(.+?)(?:\s+(in private|privately|in public|publicly|everywhere|in direct conversations))?(?=\s+and\s+(?:i\b|my\b|you\b)|[.;,]|$)/i);
|
|
67
|
+
const callMeMatch = text.match(/\b(?:(?:from now on|only),?\s*)?call me\s+(.+?)(?:\s+(?:in private|privately|in public|publicly|everywhere|in direct conversations))?(?=\s+and\s+(?:i\b|my\b|you\b)|[.;,]|$)/i);
|
|
71
68
|
if (callMeMatch) {
|
|
72
69
|
const address = cleanValue(callMeMatch[1], 80);
|
|
73
|
-
const
|
|
74
|
-
let claimAudiences = [defaultAudience];
|
|
75
|
-
let claimSensitivity = sensitivity;
|
|
76
|
-
let directiveInstruction = `Address ${actorSubject} as ${address}`;
|
|
77
|
-
if (scopePhrase.includes('private') || scopePhrase.includes('privately')) {
|
|
78
|
-
claimSensitivity = 'private';
|
|
79
|
-
claimAudiences = [context?.conversation?.audienceId || `audience-private-${actorId}`];
|
|
80
|
-
directiveInstruction += ' in private conversations';
|
|
81
|
-
}
|
|
82
|
-
else if (scopePhrase.includes('public') || scopePhrase.includes('publicly')) {
|
|
83
|
-
claimSensitivity = 'public';
|
|
84
|
-
claimAudiences = ['audience-public'];
|
|
85
|
-
directiveInstruction += ' in public conversations';
|
|
86
|
-
}
|
|
87
|
-
else if (scopePhrase.includes('direct')) {
|
|
88
|
-
claimSensitivity = 'private';
|
|
89
|
-
claimAudiences = [context?.conversation?.audienceId || `audience-direct-${actorId}`];
|
|
90
|
-
directiveInstruction += ' in direct conversations';
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
directiveInstruction += ' when addressing the actor';
|
|
94
|
-
}
|
|
70
|
+
const directiveInstruction = `Address ${actorSubject} as ${address}`;
|
|
95
71
|
claims.push({
|
|
96
72
|
subject: actorSubject,
|
|
97
73
|
predicate: 'preferred_address',
|
|
@@ -99,8 +75,7 @@ function extractDeterministicTeaching(message, context, sourceEventId) {
|
|
|
99
75
|
content: `The actor's preferred address is ${address}.`,
|
|
100
76
|
claimType: 'relationship',
|
|
101
77
|
provenance: 'deterministic_teaching',
|
|
102
|
-
sensitivity
|
|
103
|
-
allowedAudiences: claimAudiences,
|
|
78
|
+
sensitivity,
|
|
104
79
|
sourceEventId,
|
|
105
80
|
});
|
|
106
81
|
behaviorProposals.push({
|
|
@@ -125,7 +100,6 @@ function extractDeterministicTeaching(message, context, sourceEventId) {
|
|
|
125
100
|
claimType: 'relationship',
|
|
126
101
|
provenance: 'deterministic_teaching',
|
|
127
102
|
sensitivity: 'private',
|
|
128
|
-
allowedAudiences: [defaultAudience],
|
|
129
103
|
sourceEventId,
|
|
130
104
|
});
|
|
131
105
|
behaviorProposals.push({
|
|
@@ -151,7 +125,6 @@ function extractDeterministicTeaching(message, context, sourceEventId) {
|
|
|
151
125
|
claimType: 'preference',
|
|
152
126
|
provenance: 'deterministic_teaching',
|
|
153
127
|
sensitivity,
|
|
154
|
-
allowedAudiences: [defaultAudience],
|
|
155
128
|
sourceEventId,
|
|
156
129
|
});
|
|
157
130
|
}
|
package/package.json
CHANGED