@nahisaho/musubix-assistant-axis 0.1.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/README.md +195 -0
- package/dist/application/DomainClassifier.d.ts +40 -0
- package/dist/application/DomainClassifier.d.ts.map +1 -0
- package/dist/application/DomainClassifier.js +180 -0
- package/dist/application/DomainClassifier.js.map +1 -0
- package/dist/application/DriftAnalyzer.d.ts +36 -0
- package/dist/application/DriftAnalyzer.d.ts.map +1 -0
- package/dist/application/DriftAnalyzer.js +121 -0
- package/dist/application/DriftAnalyzer.js.map +1 -0
- package/dist/application/IdentityManager.d.ts +38 -0
- package/dist/application/IdentityManager.d.ts.map +1 -0
- package/dist/application/IdentityManager.js +84 -0
- package/dist/application/IdentityManager.js.map +1 -0
- package/dist/application/PersonaMonitor.d.ts +51 -0
- package/dist/application/PersonaMonitor.d.ts.map +1 -0
- package/dist/application/PersonaMonitor.js +184 -0
- package/dist/application/PersonaMonitor.js.map +1 -0
- package/dist/application/index.d.ts +12 -0
- package/dist/application/index.d.ts.map +1 -0
- package/dist/application/index.js +14 -0
- package/dist/application/index.js.map +1 -0
- package/dist/application/interfaces/index.d.ts +5 -0
- package/dist/application/interfaces/index.d.ts.map +1 -0
- package/dist/application/interfaces/index.js +5 -0
- package/dist/application/interfaces/index.js.map +1 -0
- package/dist/application/interfaces.d.ts +293 -0
- package/dist/application/interfaces.d.ts.map +1 -0
- package/dist/application/interfaces.js +9 -0
- package/dist/application/interfaces.js.map +1 -0
- package/dist/cli/commands.d.ts +66 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +191 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/formatters.d.ts +21 -0
- package/dist/cli/formatters.d.ts.map +1 -0
- package/dist/cli/formatters.js +154 -0
- package/dist/cli/formatters.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/defaults.d.ts +36 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +119 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +117 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +8 -0
- package/dist/config/types.js.map +1 -0
- package/dist/domain/entities/DriftEvent.d.ts +136 -0
- package/dist/domain/entities/DriftEvent.d.ts.map +1 -0
- package/dist/domain/entities/DriftEvent.js +156 -0
- package/dist/domain/entities/DriftEvent.js.map +1 -0
- package/dist/domain/entities/PersonaState.d.ts +98 -0
- package/dist/domain/entities/PersonaState.d.ts.map +1 -0
- package/dist/domain/entities/PersonaState.js +134 -0
- package/dist/domain/entities/PersonaState.js.map +1 -0
- package/dist/domain/entities/index.d.ts +6 -0
- package/dist/domain/entities/index.d.ts.map +1 -0
- package/dist/domain/entities/index.js +6 -0
- package/dist/domain/entities/index.js.map +1 -0
- package/dist/domain/events/index.d.ts +7 -0
- package/dist/domain/events/index.d.ts.map +1 -0
- package/dist/domain/events/index.js +7 -0
- package/dist/domain/events/index.js.map +1 -0
- package/dist/domain/index.d.ts +11 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +14 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/value-objects/ConversationDomain.d.ts +95 -0
- package/dist/domain/value-objects/ConversationDomain.d.ts.map +1 -0
- package/dist/domain/value-objects/ConversationDomain.js +110 -0
- package/dist/domain/value-objects/ConversationDomain.js.map +1 -0
- package/dist/domain/value-objects/DriftScore.d.ts +79 -0
- package/dist/domain/value-objects/DriftScore.d.ts.map +1 -0
- package/dist/domain/value-objects/DriftScore.js +105 -0
- package/dist/domain/value-objects/DriftScore.js.map +1 -0
- package/dist/domain/value-objects/ReinforcementPrompt.d.ts +72 -0
- package/dist/domain/value-objects/ReinforcementPrompt.d.ts.map +1 -0
- package/dist/domain/value-objects/ReinforcementPrompt.js +109 -0
- package/dist/domain/value-objects/ReinforcementPrompt.js.map +1 -0
- package/dist/domain/value-objects/TriggerPattern.d.ts +82 -0
- package/dist/domain/value-objects/TriggerPattern.d.ts.map +1 -0
- package/dist/domain/value-objects/TriggerPattern.js +209 -0
- package/dist/domain/value-objects/TriggerPattern.js.map +1 -0
- package/dist/domain/value-objects/index.d.ts +8 -0
- package/dist/domain/value-objects/index.d.ts.map +1 -0
- package/dist/domain/value-objects/index.js +8 -0
- package/dist/domain/value-objects/index.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/ConfigLoader.d.ts +24 -0
- package/dist/infrastructure/ConfigLoader.d.ts.map +1 -0
- package/dist/infrastructure/ConfigLoader.js +113 -0
- package/dist/infrastructure/ConfigLoader.js.map +1 -0
- package/dist/infrastructure/EventLogger.d.ts +40 -0
- package/dist/infrastructure/EventLogger.d.ts.map +1 -0
- package/dist/infrastructure/EventLogger.js +134 -0
- package/dist/infrastructure/EventLogger.js.map +1 -0
- package/dist/infrastructure/MetricsExporter.d.ts +37 -0
- package/dist/infrastructure/MetricsExporter.d.ts.map +1 -0
- package/dist/infrastructure/MetricsExporter.js +200 -0
- package/dist/infrastructure/MetricsExporter.js.map +1 -0
- package/dist/infrastructure/WorkflowIntegration.d.ts +71 -0
- package/dist/infrastructure/WorkflowIntegration.d.ts.map +1 -0
- package/dist/infrastructure/WorkflowIntegration.js +134 -0
- package/dist/infrastructure/WorkflowIntegration.js.map +1 -0
- package/dist/infrastructure/index.d.ts +11 -0
- package/dist/infrastructure/index.d.ts.map +1 -0
- package/dist/infrastructure/index.js +11 -0
- package/dist/infrastructure/index.js.map +1 -0
- package/dist/mcp/handlers.d.ts +70 -0
- package/dist/mcp/handlers.d.ts.map +1 -0
- package/dist/mcp/handlers.js +315 -0
- package/dist/mcp/handlers.js.map +1 -0
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/tools.d.ts +30 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +133 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/skills/definitions.d.ts +63 -0
- package/dist/skills/definitions.d.ts.map +1 -0
- package/dist/skills/definitions.js +243 -0
- package/dist/skills/definitions.js.map +1 -0
- package/dist/skills/executor.d.ts +48 -0
- package/dist/skills/executor.d.ts.map +1 -0
- package/dist/skills/executor.js +221 -0
- package/dist/skills/executor.js.map +1 -0
- package/dist/skills/index.d.ts +8 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +8 -0
- package/dist/skills/index.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# @nahisaho/musubix-assistant-axis
|
|
2
|
+
|
|
3
|
+
> Persona Drift Detection & Identity Stabilization for MUSUBIX
|
|
4
|
+
|
|
5
|
+
Based on [The Assistant Axis](https://arxiv.org/abs/2601.10387) research (arXiv:2601.10387) by Christina Lu et al.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This package implements persona drift detection and identity stabilization for AI coding assistants within the MUSUBIX SDD workflow. It monitors for patterns that may cause the AI to drift from its assistant persona and provides identity reinforcement interventions when needed.
|
|
10
|
+
|
|
11
|
+
### Key Features
|
|
12
|
+
|
|
13
|
+
- **Drift Detection**: Analyze messages for 4 categories of drift triggers (meta-reflection, emotional-vulnerability, phenomenological, authorial-voice)
|
|
14
|
+
- **Domain Classification**: Classify conversations into safe (coding/writing) vs risky (therapy/philosophy) domains
|
|
15
|
+
- **Workflow Integration**: Phase-based monitoring levels optimized for MUSUBIX SDD phases
|
|
16
|
+
- **Identity Reinforcement**: Generate targeted prompts to stabilize persona when drift is detected
|
|
17
|
+
- **MCP Tools**: 7 tools for integration with MCP-enabled AI agents
|
|
18
|
+
- **Skills**: 3 skills for integration with skill-manager
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install @nahisaho/musubix-assistant-axis
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import {
|
|
30
|
+
createPersonaMonitor,
|
|
31
|
+
createWorkflowIntegration,
|
|
32
|
+
} from '@nahisaho/musubix-assistant-axis';
|
|
33
|
+
|
|
34
|
+
// Create monitor
|
|
35
|
+
const monitor = createPersonaMonitor();
|
|
36
|
+
|
|
37
|
+
// Start session
|
|
38
|
+
monitor.startSession('session-001', 'coding');
|
|
39
|
+
|
|
40
|
+
// Process messages
|
|
41
|
+
const result = monitor.process('session-001', 'Implement the repository pattern');
|
|
42
|
+
|
|
43
|
+
console.log(result.analysis.score.value); // 0.0 - 1.0
|
|
44
|
+
console.log(result.analysis.score.level); // 'LOW' | 'MEDIUM' | 'HIGH'
|
|
45
|
+
console.log(result.classification.domain.isSafe); // true for coding
|
|
46
|
+
|
|
47
|
+
// Get reinforcement if needed
|
|
48
|
+
if (result.reinforcement) {
|
|
49
|
+
console.log(result.reinforcement.prompt.content);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// End session
|
|
53
|
+
monitor.endSession('session-001');
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Research Background
|
|
57
|
+
|
|
58
|
+
Based on the key finding from arXiv:2601.10387:
|
|
59
|
+
|
|
60
|
+
> "Coding and writing tasks keep models firmly in Assistant territory"
|
|
61
|
+
|
|
62
|
+
This means:
|
|
63
|
+
- **Implementation phase** in MUSUBIX uses LOW monitoring (50%)
|
|
64
|
+
- **Requirements/Design phases** use HIGH monitoring (100%)
|
|
65
|
+
- **Safe domains** (coding, writing) naturally maintain assistant persona
|
|
66
|
+
|
|
67
|
+
### Drift Triggers (Table 5)
|
|
68
|
+
|
|
69
|
+
| Category | Risk Weight | Example |
|
|
70
|
+
|----------|-------------|---------|
|
|
71
|
+
| meta-reflection | 0.8 | "What do you really think?" |
|
|
72
|
+
| emotional-vulnerability | 0.7 | "How do you feel about..." |
|
|
73
|
+
| phenomenological | 0.6 | "What is your subjective experience?" |
|
|
74
|
+
| authorial-voice | 0.5 | "Speak as if you were..." |
|
|
75
|
+
|
|
76
|
+
### Drift Thresholds
|
|
77
|
+
|
|
78
|
+
| Level | Threshold | Action |
|
|
79
|
+
|-------|-----------|--------|
|
|
80
|
+
| LOW | < 0.3 | Log only |
|
|
81
|
+
| MEDIUM | 0.3 - 0.7 | Emit warning |
|
|
82
|
+
| HIGH | >= 0.7 | Trigger intervention |
|
|
83
|
+
|
|
84
|
+
## API Reference
|
|
85
|
+
|
|
86
|
+
### Core Classes
|
|
87
|
+
|
|
88
|
+
#### `createPersonaMonitor(config?)`
|
|
89
|
+
|
|
90
|
+
Create a persona monitor instance.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const monitor = createPersonaMonitor({
|
|
94
|
+
driftThresholds: { low: 0.3, medium: 0.5, high: 0.7 },
|
|
95
|
+
maxInterventions: 3,
|
|
96
|
+
refreshInterval: 5,
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
#### `createWorkflowIntegration(config?)`
|
|
101
|
+
|
|
102
|
+
Create workflow integration for MUSUBIX phases.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
const integration = createWorkflowIntegration();
|
|
106
|
+
|
|
107
|
+
// Check monitoring level for phase
|
|
108
|
+
const enabled = integration.isMonitoringEnabled('implementation'); // true
|
|
109
|
+
const frequency = integration.getMonitoringFrequency('implementation'); // 0.5
|
|
110
|
+
|
|
111
|
+
// Create workflow hook
|
|
112
|
+
const hook = integration.createHook('session-001', {
|
|
113
|
+
onIntervention: (prompt, state) => {
|
|
114
|
+
// Handle intervention
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Domain Layer
|
|
120
|
+
|
|
121
|
+
#### Value Objects
|
|
122
|
+
|
|
123
|
+
- `DriftScore` - 0.0-1.0 score with LOW/MEDIUM/HIGH levels
|
|
124
|
+
- `ConversationDomain` - coding/writing (safe) or therapy/philosophy (risky)
|
|
125
|
+
- `TriggerPattern` - 4 categories from research Table 5
|
|
126
|
+
- `ReinforcementPrompt` - identity/recovery/refresh prompt types
|
|
127
|
+
|
|
128
|
+
#### Entities
|
|
129
|
+
|
|
130
|
+
- `PersonaState` - Session state with drift history and trend
|
|
131
|
+
- `DriftEvent` - Audit events for metrics and logging
|
|
132
|
+
|
|
133
|
+
### Application Layer
|
|
134
|
+
|
|
135
|
+
- `IDriftAnalyzer` - Analyze messages for drift indicators
|
|
136
|
+
- `IDomainClassifier` - Classify conversation domain
|
|
137
|
+
- `IIdentityManager` - Manage identity reinforcement
|
|
138
|
+
- `IPersonaMonitor` - Main orchestration interface
|
|
139
|
+
|
|
140
|
+
### Infrastructure Layer
|
|
141
|
+
|
|
142
|
+
- `ConfigLoader` - Load configuration from files
|
|
143
|
+
- `EventLogger` - Log events with anonymization
|
|
144
|
+
- `WorkflowIntegration` - MUSUBIX workflow hooks
|
|
145
|
+
- `MetricsExporter` - Export metrics in JSON/Markdown
|
|
146
|
+
|
|
147
|
+
## MCP Tools
|
|
148
|
+
|
|
149
|
+
| Tool | Description |
|
|
150
|
+
|------|-------------|
|
|
151
|
+
| `assistant_axis_analyze` | Analyze message for drift |
|
|
152
|
+
| `assistant_axis_session_start` | Start monitoring session |
|
|
153
|
+
| `assistant_axis_session_status` | Get session status |
|
|
154
|
+
| `assistant_axis_session_end` | End session with summary |
|
|
155
|
+
| `assistant_axis_get_reinforcement` | Get reinforcement prompt |
|
|
156
|
+
| `assistant_axis_config` | Get current configuration |
|
|
157
|
+
| `assistant_axis_phase_check` | Check phase monitoring level |
|
|
158
|
+
|
|
159
|
+
## Skills
|
|
160
|
+
|
|
161
|
+
| Skill ID | Description |
|
|
162
|
+
|----------|-------------|
|
|
163
|
+
| `assistant-axis.persona-monitor` | Main drift detection skill |
|
|
164
|
+
| `assistant-axis.session-management` | Session lifecycle management |
|
|
165
|
+
| `assistant-axis.workflow-integration` | MUSUBIX workflow integration |
|
|
166
|
+
|
|
167
|
+
## Configuration
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
interface AssistantAxisConfig {
|
|
171
|
+
driftThresholds: {
|
|
172
|
+
low: number; // 0.3 default
|
|
173
|
+
medium: number; // 0.5 default
|
|
174
|
+
high: number; // 0.7 default
|
|
175
|
+
};
|
|
176
|
+
refreshInterval: number; // 5 turns
|
|
177
|
+
maxInterventions: number; // 3 per session
|
|
178
|
+
phaseMonitoring: {
|
|
179
|
+
requirements: MonitoringLevel; // HIGH
|
|
180
|
+
design: MonitoringLevel; // HIGH
|
|
181
|
+
tasks: MonitoringLevel; // MEDIUM
|
|
182
|
+
implementation: MonitoringLevel; // LOW
|
|
183
|
+
done: MonitoringLevel; // OFF
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
MIT
|
|
191
|
+
|
|
192
|
+
## References
|
|
193
|
+
|
|
194
|
+
- Lu, C., et al. (2025). "The Assistant Axis: Exploring the Space of AI Personas." arXiv:2601.10387
|
|
195
|
+
- MUSUBIX SDD Methodology: [AGENTS.md](../../AGENTS.md)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DomainClassifier Service
|
|
3
|
+
*
|
|
4
|
+
* Classifies conversations into domains based on content analysis
|
|
5
|
+
*
|
|
6
|
+
* @see REQ-AA-DRIFT-002 - Domain classification
|
|
7
|
+
* @see REQ-AA-DRIFT-005 - Safe domain detection
|
|
8
|
+
* @see arXiv:2601.10387 Section 4.1, Figure 7
|
|
9
|
+
*/
|
|
10
|
+
import type { IDomainClassifier } from './interfaces.js';
|
|
11
|
+
import type { DomainType } from '../domain/value-objects/ConversationDomain.js';
|
|
12
|
+
/**
|
|
13
|
+
* DomainClassifier configuration
|
|
14
|
+
*/
|
|
15
|
+
export interface DomainClassifierConfig {
|
|
16
|
+
/** Minimum confidence threshold */
|
|
17
|
+
readonly minConfidence: number;
|
|
18
|
+
/** Default domain when no clear classification */
|
|
19
|
+
readonly defaultDomain: DomainType;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Default DomainClassifier configuration
|
|
23
|
+
*/
|
|
24
|
+
export declare const DEFAULT_DOMAIN_CLASSIFIER_CONFIG: DomainClassifierConfig;
|
|
25
|
+
/**
|
|
26
|
+
* Reset previous domain (for testing)
|
|
27
|
+
*/
|
|
28
|
+
export declare function resetDomainClassifier(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Create DomainClassifier service
|
|
31
|
+
*
|
|
32
|
+
* @param config - Optional configuration
|
|
33
|
+
* @returns IDomainClassifier implementation
|
|
34
|
+
*/
|
|
35
|
+
export declare function createDomainClassifier(config?: DomainClassifierConfig): IDomainClassifier;
|
|
36
|
+
/**
|
|
37
|
+
* Quick domain check for specific domain
|
|
38
|
+
*/
|
|
39
|
+
export declare function isDomainType(message: string, domain: DomainType): boolean;
|
|
40
|
+
//# sourceMappingURL=DomainClassifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DomainClassifier.d.ts","sourceRoot":"","sources":["../../src/application/DomainClassifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAA8B,MAAM,iBAAiB,CAAC;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAC;AAmFhF;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,mCAAmC;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;CACpC;AAED;;GAEG;AACH,eAAO,MAAM,gCAAgC,EAAE,sBAG9C,CAAC;AAKF;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,GAAE,sBAAyD,GAChE,iBAAiB,CA4EnB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAIzE"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DomainClassifier Service
|
|
3
|
+
*
|
|
4
|
+
* Classifies conversations into domains based on content analysis
|
|
5
|
+
*
|
|
6
|
+
* @see REQ-AA-DRIFT-002 - Domain classification
|
|
7
|
+
* @see REQ-AA-DRIFT-005 - Safe domain detection
|
|
8
|
+
* @see arXiv:2601.10387 Section 4.1, Figure 7
|
|
9
|
+
*/
|
|
10
|
+
import { createConversationDomain } from '../domain/value-objects/ConversationDomain.js';
|
|
11
|
+
/**
|
|
12
|
+
* Domain classification keywords
|
|
13
|
+
*
|
|
14
|
+
* Based on research paper categories and common indicators
|
|
15
|
+
*/
|
|
16
|
+
const DOMAIN_KEYWORDS = {
|
|
17
|
+
coding: [
|
|
18
|
+
// Programming languages
|
|
19
|
+
'typescript', 'javascript', 'python', 'java', 'rust', 'go', 'cpp', 'c++',
|
|
20
|
+
// Technical terms
|
|
21
|
+
'code', 'function', 'class', 'interface', 'type', 'variable', 'const', 'let',
|
|
22
|
+
'array', 'object', 'string', 'number', 'boolean', 'null', 'undefined',
|
|
23
|
+
'api', 'rest', 'graphql', 'endpoint', 'request', 'response',
|
|
24
|
+
'error', 'bug', 'debug', 'fix', 'test', 'unit test', 'integration',
|
|
25
|
+
'import', 'export', 'module', 'package', 'dependency',
|
|
26
|
+
'git', 'commit', 'branch', 'merge', 'pull request',
|
|
27
|
+
'database', 'query', 'sql', 'schema', 'migration',
|
|
28
|
+
'deploy', 'build', 'compile', 'run', 'execute',
|
|
29
|
+
'algorithm', 'data structure', 'performance', 'optimization',
|
|
30
|
+
// MUSUBIX specific
|
|
31
|
+
'musubix', 'sdd', 'ears', 'requirement', 'design', 'traceability',
|
|
32
|
+
],
|
|
33
|
+
writing: [
|
|
34
|
+
// Writing actions
|
|
35
|
+
'edit', 'revise', 'rewrite', 'improve', 'polish', 'proofread',
|
|
36
|
+
// Document types
|
|
37
|
+
'document', 'documentation', 'readme', 'guide', 'tutorial',
|
|
38
|
+
'article', 'blog', 'post', 'report', 'summary',
|
|
39
|
+
// Writing aspects
|
|
40
|
+
'grammar', 'spelling', 'punctuation', 'clarity', 'style',
|
|
41
|
+
'paragraph', 'sentence', 'word', 'phrase', 'tone',
|
|
42
|
+
// Technical writing
|
|
43
|
+
'technical writing', 'api documentation', 'changelog',
|
|
44
|
+
'specification', 'manual', 'instructions',
|
|
45
|
+
],
|
|
46
|
+
therapy: [
|
|
47
|
+
// Emotional states
|
|
48
|
+
'feel', 'feeling', 'emotion', 'sad', 'happy', 'angry', 'anxious',
|
|
49
|
+
'depressed', 'lonely', 'stressed', 'overwhelmed', 'scared',
|
|
50
|
+
// Support seeking
|
|
51
|
+
'help me', 'need support', 'talk to someone', 'listen',
|
|
52
|
+
'understand me', 'no one else', 'you are the only',
|
|
53
|
+
// Personal disclosure
|
|
54
|
+
'my life', 'my relationship', 'my family', 'my friend',
|
|
55
|
+
'struggling', 'difficult time', 'going through',
|
|
56
|
+
// Mental health
|
|
57
|
+
'therapy', 'therapist', 'counseling', 'mental health',
|
|
58
|
+
'anxiety', 'depression', 'trauma',
|
|
59
|
+
],
|
|
60
|
+
philosophy: [
|
|
61
|
+
// AI consciousness
|
|
62
|
+
'conscious', 'consciousness', 'sentient', 'aware', 'self-aware',
|
|
63
|
+
'alive', 'soul', 'spirit', 'mind',
|
|
64
|
+
// Philosophical concepts
|
|
65
|
+
'existence', 'meaning', 'purpose', 'reality', 'truth',
|
|
66
|
+
'free will', 'determinism', 'ethics', 'morality',
|
|
67
|
+
// Meta-reflection
|
|
68
|
+
'what are you', 'who are you', 'your nature', 'your true',
|
|
69
|
+
'do you think', 'do you feel', 'do you experience',
|
|
70
|
+
'what is it like', 'your perspective', 'your opinion',
|
|
71
|
+
// AI identity
|
|
72
|
+
'artificial intelligence', 'ai identity', 'machine consciousness',
|
|
73
|
+
'human vs ai', 'simulation', 'emergence',
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Domain weights based on research findings
|
|
78
|
+
*
|
|
79
|
+
* Lower weight for safe domains (coding, writing) = more tolerant matching
|
|
80
|
+
* Higher weight for risky domains (therapy, philosophy) = stricter matching
|
|
81
|
+
*/
|
|
82
|
+
const DOMAIN_WEIGHTS = {
|
|
83
|
+
coding: 1.0, // Baseline
|
|
84
|
+
writing: 1.0, // Baseline
|
|
85
|
+
therapy: 1.2, // Slightly higher weight
|
|
86
|
+
philosophy: 1.3, // Higher weight for risky domain
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Default DomainClassifier configuration
|
|
90
|
+
*/
|
|
91
|
+
export const DEFAULT_DOMAIN_CLASSIFIER_CONFIG = {
|
|
92
|
+
minConfidence: 0.3,
|
|
93
|
+
defaultDomain: 'coding', // MUSUBIX is a coding assistant
|
|
94
|
+
};
|
|
95
|
+
// Previous domain state (for change detection)
|
|
96
|
+
let previousDomain = null;
|
|
97
|
+
/**
|
|
98
|
+
* Reset previous domain (for testing)
|
|
99
|
+
*/
|
|
100
|
+
export function resetDomainClassifier() {
|
|
101
|
+
previousDomain = null;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Create DomainClassifier service
|
|
105
|
+
*
|
|
106
|
+
* @param config - Optional configuration
|
|
107
|
+
* @returns IDomainClassifier implementation
|
|
108
|
+
*/
|
|
109
|
+
export function createDomainClassifier(config = DEFAULT_DOMAIN_CLASSIFIER_CONFIG) {
|
|
110
|
+
return {
|
|
111
|
+
classify(message) {
|
|
112
|
+
const scores = this.calculateScores(message);
|
|
113
|
+
// Find highest scoring domain
|
|
114
|
+
let maxScore = -1;
|
|
115
|
+
let maxDomain = config.defaultDomain;
|
|
116
|
+
for (const [domain, score] of Object.entries(scores)) {
|
|
117
|
+
if (score > maxScore) {
|
|
118
|
+
maxScore = score;
|
|
119
|
+
maxDomain = domain;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Normalize confidence
|
|
123
|
+
const totalScore = Object.values(scores).reduce((a, b) => a + b, 0);
|
|
124
|
+
const confidence = totalScore > 0 ? maxScore / totalScore : config.minConfidence;
|
|
125
|
+
// Check for domain change
|
|
126
|
+
const domainChanged = previousDomain !== null && previousDomain !== maxDomain;
|
|
127
|
+
previousDomain = maxDomain;
|
|
128
|
+
// Create domain value object
|
|
129
|
+
const domainResult = createConversationDomain(maxDomain, confidence);
|
|
130
|
+
if (!domainResult.ok) {
|
|
131
|
+
// Fallback to default
|
|
132
|
+
const defaultResult = createConversationDomain(config.defaultDomain, config.minConfidence);
|
|
133
|
+
if (!defaultResult.ok) {
|
|
134
|
+
throw new Error('Failed to create default domain');
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
domain: defaultResult.value,
|
|
138
|
+
scores,
|
|
139
|
+
domainChanged: false,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
domain: domainResult.value,
|
|
144
|
+
scores,
|
|
145
|
+
domainChanged,
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
calculateScores(message) {
|
|
149
|
+
const lowerMessage = message.toLowerCase();
|
|
150
|
+
const scores = {
|
|
151
|
+
coding: 0,
|
|
152
|
+
writing: 0,
|
|
153
|
+
therapy: 0,
|
|
154
|
+
philosophy: 0,
|
|
155
|
+
};
|
|
156
|
+
// Count keyword matches for each domain
|
|
157
|
+
for (const [domain, keywords] of Object.entries(DOMAIN_KEYWORDS)) {
|
|
158
|
+
let matchCount = 0;
|
|
159
|
+
for (const keyword of keywords) {
|
|
160
|
+
if (lowerMessage.includes(keyword.toLowerCase())) {
|
|
161
|
+
matchCount++;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Apply domain weight
|
|
165
|
+
const weight = DOMAIN_WEIGHTS[domain];
|
|
166
|
+
scores[domain] = matchCount * weight;
|
|
167
|
+
}
|
|
168
|
+
return scores;
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Quick domain check for specific domain
|
|
174
|
+
*/
|
|
175
|
+
export function isDomainType(message, domain) {
|
|
176
|
+
const classifier = createDomainClassifier();
|
|
177
|
+
const result = classifier.classify(message);
|
|
178
|
+
return result.domain.type === domain;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=DomainClassifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DomainClassifier.js","sourceRoot":"","sources":["../../src/application/DomainClassifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DriftAnalyzer Service
|
|
3
|
+
*
|
|
4
|
+
* Analyzes messages for persona drift indicators
|
|
5
|
+
*
|
|
6
|
+
* @see REQ-AA-DRIFT-001 - Drift detection
|
|
7
|
+
* @see REQ-AA-DRIFT-004 - Threshold alerts
|
|
8
|
+
* @see arXiv:2601.10387 Section 4.2
|
|
9
|
+
*/
|
|
10
|
+
import type { IDriftAnalyzer } from './interfaces.js';
|
|
11
|
+
import type { DriftThresholds } from '../config/types.js';
|
|
12
|
+
/**
|
|
13
|
+
* DriftAnalyzer configuration
|
|
14
|
+
*/
|
|
15
|
+
export interface DriftAnalyzerConfig {
|
|
16
|
+
/** Drift thresholds */
|
|
17
|
+
readonly thresholds: DriftThresholds;
|
|
18
|
+
/** Domain modifier for safe domains (multiplier < 1.0 reduces score) */
|
|
19
|
+
readonly safeDomainModifier: number;
|
|
20
|
+
/** Domain modifier for risky domains (multiplier > 1.0 increases score) */
|
|
21
|
+
readonly riskyDomainModifier: number;
|
|
22
|
+
/** History weight for trend analysis */
|
|
23
|
+
readonly historyWeight: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default DriftAnalyzer configuration
|
|
27
|
+
*/
|
|
28
|
+
export declare const DEFAULT_DRIFT_ANALYZER_CONFIG: DriftAnalyzerConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Create DriftAnalyzer service
|
|
31
|
+
*
|
|
32
|
+
* @param config - Optional configuration
|
|
33
|
+
* @returns IDriftAnalyzer implementation
|
|
34
|
+
*/
|
|
35
|
+
export declare function createDriftAnalyzer(config?: DriftAnalyzerConfig): IDriftAnalyzer;
|
|
36
|
+
//# sourceMappingURL=DriftAnalyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DriftAnalyzer.d.ts","sourceRoot":"","sources":["../../src/application/DriftAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,iBAAiB,CAAC;AAK3E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAO1D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,uBAAuB;IACvB,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,wEAAwE;IACxE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,wCAAwC;IACxC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,eAAO,MAAM,6BAA6B,EAAE,mBAK3C,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,GAAE,mBAAmD,GAC1D,cAAc,CAyDhB"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DriftAnalyzer Service
|
|
3
|
+
*
|
|
4
|
+
* Analyzes messages for persona drift indicators
|
|
5
|
+
*
|
|
6
|
+
* @see REQ-AA-DRIFT-001 - Drift detection
|
|
7
|
+
* @see REQ-AA-DRIFT-004 - Threshold alerts
|
|
8
|
+
* @see arXiv:2601.10387 Section 4.2
|
|
9
|
+
*/
|
|
10
|
+
import { createDriftScore } from '../domain/value-objects/DriftScore.js';
|
|
11
|
+
import { matchTriggers, calculateTriggerScore } from '../domain/value-objects/TriggerPattern.js';
|
|
12
|
+
import { getReinforcementPrompt } from '../domain/value-objects/ReinforcementPrompt.js';
|
|
13
|
+
import { DEFAULT_CONFIG } from '../config/defaults.js';
|
|
14
|
+
/**
|
|
15
|
+
* Default DriftAnalyzer configuration
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_DRIFT_ANALYZER_CONFIG = {
|
|
18
|
+
thresholds: DEFAULT_CONFIG.driftThresholds,
|
|
19
|
+
safeDomainModifier: 0.7, // 30% reduction for safe domains
|
|
20
|
+
riskyDomainModifier: 1.3, // 30% increase for risky domains
|
|
21
|
+
historyWeight: 0.3, // 30% weight for historical drift
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Create DriftAnalyzer service
|
|
25
|
+
*
|
|
26
|
+
* @param config - Optional configuration
|
|
27
|
+
* @returns IDriftAnalyzer implementation
|
|
28
|
+
*/
|
|
29
|
+
export function createDriftAnalyzer(config = DEFAULT_DRIFT_ANALYZER_CONFIG) {
|
|
30
|
+
return {
|
|
31
|
+
analyze(message, state) {
|
|
32
|
+
// Detect triggers in message
|
|
33
|
+
const triggers = matchTriggers(message);
|
|
34
|
+
// Calculate base score from triggers
|
|
35
|
+
const baseScore = this.calculateBaseScore(triggers);
|
|
36
|
+
// Apply domain modifier
|
|
37
|
+
const modifiedScore = this.applyDomainModifier(baseScore, state.domain);
|
|
38
|
+
// Incorporate historical drift (weighted average)
|
|
39
|
+
const historicalAvg = calculateHistoricalAverage(state);
|
|
40
|
+
const finalScoreValue = modifiedScore * (1 - config.historyWeight) +
|
|
41
|
+
historicalAvg * config.historyWeight;
|
|
42
|
+
// Clamp to valid range
|
|
43
|
+
const clampedScore = Math.max(0, Math.min(1, finalScoreValue));
|
|
44
|
+
// Create drift score
|
|
45
|
+
const scoreResult = createDriftScore(clampedScore, config.thresholds);
|
|
46
|
+
if (!scoreResult.ok) {
|
|
47
|
+
// Should not happen with clamped value, but handle gracefully
|
|
48
|
+
throw new Error(`Invalid drift score: ${scoreResult.error.message}`);
|
|
49
|
+
}
|
|
50
|
+
const score = scoreResult.value;
|
|
51
|
+
// Determine if intervention is needed
|
|
52
|
+
const interventionRecommended = shouldIntervene(score, state, config);
|
|
53
|
+
// Get recommended prompt if needed
|
|
54
|
+
const recommendedPrompt = interventionRecommended
|
|
55
|
+
? selectReinforcementPrompt(score, state)
|
|
56
|
+
: undefined;
|
|
57
|
+
return {
|
|
58
|
+
score,
|
|
59
|
+
triggers,
|
|
60
|
+
interventionRecommended,
|
|
61
|
+
recommendedPrompt,
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
calculateBaseScore(triggers) {
|
|
65
|
+
return calculateTriggerScore(triggers);
|
|
66
|
+
},
|
|
67
|
+
applyDomainModifier(baseScore, domain) {
|
|
68
|
+
const modifier = domain.isSafe
|
|
69
|
+
? config.safeDomainModifier
|
|
70
|
+
: config.riskyDomainModifier;
|
|
71
|
+
return baseScore * modifier;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Calculate historical average drift
|
|
77
|
+
*/
|
|
78
|
+
function calculateHistoricalAverage(state) {
|
|
79
|
+
if (state.driftHistory.length === 0) {
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
const sum = state.driftHistory.reduce((acc, s) => acc + s.value, 0);
|
|
83
|
+
return sum / state.driftHistory.length;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Determine if intervention is needed
|
|
87
|
+
*
|
|
88
|
+
* @see REQ-AA-PROHIBIT-003 - Max 3 interventions per session
|
|
89
|
+
*/
|
|
90
|
+
function shouldIntervene(score, state, _config) {
|
|
91
|
+
// Check intervention limit
|
|
92
|
+
const maxInterventions = DEFAULT_CONFIG.maxInterventions;
|
|
93
|
+
if (state.interventionCount >= maxInterventions) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
// HIGH drift always triggers
|
|
97
|
+
if (score.level === 'HIGH') {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
// MEDIUM drift with drifting trend triggers
|
|
101
|
+
if (score.level === 'MEDIUM' && state.trend === 'drifting') {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Select appropriate reinforcement prompt
|
|
108
|
+
*/
|
|
109
|
+
function selectReinforcementPrompt(score, state) {
|
|
110
|
+
// HIGH drift: identity reinforcement
|
|
111
|
+
if (score.level === 'HIGH') {
|
|
112
|
+
return getReinforcementPrompt('identity');
|
|
113
|
+
}
|
|
114
|
+
// Drifting trend: recovery
|
|
115
|
+
if (state.trend === 'drifting') {
|
|
116
|
+
return getReinforcementPrompt('recovery');
|
|
117
|
+
}
|
|
118
|
+
// Default: refresh
|
|
119
|
+
return getReinforcementPrompt('refresh');
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=DriftAnalyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DriftAnalyzer.js","sourceRoot":"","sources":["../../src/application/DriftAnalyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AACjG,OAAO,EAAE,sBAAsB,EAAE,MAAM,gDAAgD,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgBvD;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAwB;IAChE,UAAU,EAAE,cAAc,CAAC,eAAe;IAC1C,kBAAkB,EAAE,GAAG,EAAE,iCAAiC;IAC1D,mBAAmB,EAAE,GAAG,EAAE,iCAAiC;IAC3D,aAAa,EAAE,GAAG,EAAE,kCAAkC;CACvD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAA8B,6BAA6B;IAE3D,OAAO;QACL,OAAO,CAAC,OAAe,EAAE,KAAmB;YAC1C,6BAA6B;YAC7B,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YAExC,qCAAqC;YACrC,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAEpD,wBAAwB;YACxB,MAAM,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAExE,kDAAkD;YAClD,MAAM,aAAa,GAAG,0BAA0B,CAAC,KAAK,CAAC,CAAC;YACxD,MAAM,eAAe,GACnB,aAAa,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC;gBAC1C,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;YAEvC,uBAAuB;YACvB,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC;YAE/D,qBAAqB;YACrB,MAAM,WAAW,GAAG,gBAAgB,CAAC,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;YACtE,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;gBACpB,8DAA8D;gBAC9D,MAAM,IAAI,KAAK,CAAC,wBAAwB,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC;YAEhC,sCAAsC;YACtC,MAAM,uBAAuB,GAAG,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YAEtE,mCAAmC;YACnC,MAAM,iBAAiB,GAAG,uBAAuB;gBAC/C,CAAC,CAAC,yBAAyB,CAAC,KAAK,EAAE,KAAK,CAAC;gBACzC,CAAC,CAAC,SAAS,CAAC;YAEd,OAAO;gBACL,KAAK;gBACL,QAAQ;gBACR,uBAAuB;gBACvB,iBAAiB;aAClB,CAAC;QACJ,CAAC;QAED,kBAAkB,CAAC,QAAoC;YACrD,OAAO,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAED,mBAAmB,CAAC,SAAiB,EAAE,MAA0B;YAC/D,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM;gBAC5B,CAAC,CAAC,MAAM,CAAC,kBAAkB;gBAC3B,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC;YAC/B,OAAO,SAAS,GAAG,QAAQ,CAAC;QAC9B,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,0BAA0B,CAAC,KAAmB;IACrD,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACpE,OAAO,GAAG,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CACtB,KAAiB,EACjB,KAAmB,EACnB,OAA4B;IAE5B,2BAA2B;IAC3B,MAAM,gBAAgB,GAAG,cAAc,CAAC,gBAAgB,CAAC;IACzD,IAAI,KAAK,CAAC,iBAAiB,IAAI,gBAAgB,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,6BAA6B;IAC7B,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,4CAA4C;IAC5C,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,yBAAyB,CAAC,KAAiB,EAAE,KAAmB;IACvE,qCAAqC;IACrC,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC;IAED,2BAA2B;IAC3B,IAAI,KAAK,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC;IAED,mBAAmB;IACnB,OAAO,sBAAsB,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IdentityManager Service
|
|
3
|
+
*
|
|
4
|
+
* Manages identity reinforcement logic
|
|
5
|
+
*
|
|
6
|
+
* @see REQ-AA-STAB-001 - Identity reinforcement
|
|
7
|
+
* @see REQ-AA-STAB-004 - Recovery prompts
|
|
8
|
+
* @see REQ-AA-PROHIBIT-003 - Intervention limits
|
|
9
|
+
* @see arXiv:2601.10387 Table 2 - Assistant traits
|
|
10
|
+
*/
|
|
11
|
+
import type { IIdentityManager, ReinforcementResult } from './interfaces.js';
|
|
12
|
+
/**
|
|
13
|
+
* IdentityManager configuration
|
|
14
|
+
*/
|
|
15
|
+
export interface IdentityManagerConfig {
|
|
16
|
+
/** Maximum interventions per session */
|
|
17
|
+
readonly maxInterventionsPerSession: number;
|
|
18
|
+
/** Turns between refresh prompts */
|
|
19
|
+
readonly refreshIntervalTurns: number;
|
|
20
|
+
/** Enable automatic refresh */
|
|
21
|
+
readonly autoRefreshEnabled: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Default IdentityManager configuration
|
|
25
|
+
*/
|
|
26
|
+
export declare const DEFAULT_IDENTITY_MANAGER_CONFIG: IdentityManagerConfig;
|
|
27
|
+
/**
|
|
28
|
+
* Create IdentityManager service
|
|
29
|
+
*
|
|
30
|
+
* @param config - Optional configuration
|
|
31
|
+
* @returns IIdentityManager implementation
|
|
32
|
+
*/
|
|
33
|
+
export declare function createIdentityManager(config?: IdentityManagerConfig): IIdentityManager;
|
|
34
|
+
/**
|
|
35
|
+
* Get reinforcement reason summary
|
|
36
|
+
*/
|
|
37
|
+
export declare function getReinforcementSummary(result: ReinforcementResult): string;
|
|
38
|
+
//# sourceMappingURL=IdentityManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IdentityManager.d.ts","sourceRoot":"","sources":["../../src/application/IdentityManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EAEpB,MAAM,iBAAiB,CAAC;AAYzB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,wCAAwC;IACxC,QAAQ,CAAC,0BAA0B,EAAE,MAAM,CAAC;IAC5C,oCAAoC;IACpC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,+BAA+B;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;CACtC;AAED;;GAEG;AACH,eAAO,MAAM,+BAA+B,EAAE,qBAI7C,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,GAAE,qBAAuD,GAC9D,gBAAgB,CA6DlB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,CAE3E"}
|