@vorionsys/atsf-core 0.2.2 → 0.2.4

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.
Files changed (135) hide show
  1. package/CHANGELOG.md +3 -3
  2. package/README.md +77 -11
  3. package/dist/api/server.d.ts +4 -1
  4. package/dist/api/server.d.ts.map +1 -1
  5. package/dist/api/server.js +3 -3
  6. package/dist/api/server.js.map +1 -1
  7. package/dist/basis/parser.d.ts +14 -14
  8. package/dist/common/adapters.d.ts +16 -9
  9. package/dist/common/adapters.d.ts.map +1 -1
  10. package/dist/common/adapters.js +69 -58
  11. package/dist/common/adapters.js.map +1 -1
  12. package/dist/common/config.d.ts +4 -3
  13. package/dist/common/config.d.ts.map +1 -1
  14. package/dist/common/config.js +2 -2
  15. package/dist/common/config.js.map +1 -1
  16. package/dist/common/types.d.ts +3 -3
  17. package/dist/crewai/callback.d.ts +91 -0
  18. package/dist/crewai/callback.d.ts.map +1 -0
  19. package/dist/crewai/callback.js +271 -0
  20. package/dist/crewai/callback.js.map +1 -0
  21. package/dist/crewai/executor.d.ts +226 -0
  22. package/dist/crewai/executor.d.ts.map +1 -0
  23. package/dist/crewai/executor.js +822 -0
  24. package/dist/crewai/executor.js.map +1 -0
  25. package/dist/crewai/index.d.ts +12 -0
  26. package/dist/crewai/index.d.ts.map +1 -0
  27. package/dist/crewai/index.js +12 -0
  28. package/dist/crewai/index.js.map +1 -0
  29. package/dist/crewai/tools.d.ts +21 -0
  30. package/dist/crewai/tools.d.ts.map +1 -0
  31. package/dist/crewai/tools.js +163 -0
  32. package/dist/crewai/tools.js.map +1 -0
  33. package/dist/crewai/types.d.ts +202 -0
  34. package/dist/crewai/types.d.ts.map +1 -0
  35. package/dist/crewai/types.js +9 -0
  36. package/dist/crewai/types.js.map +1 -0
  37. package/dist/enforce/index.d.ts +50 -2
  38. package/dist/enforce/index.d.ts.map +1 -1
  39. package/dist/enforce/index.js +73 -4
  40. package/dist/enforce/index.js.map +1 -1
  41. package/dist/enforce/trust-aware-enforcement-service.d.ts +121 -0
  42. package/dist/enforce/trust-aware-enforcement-service.d.ts.map +1 -0
  43. package/dist/enforce/trust-aware-enforcement-service.js +583 -0
  44. package/dist/enforce/trust-aware-enforcement-service.js.map +1 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +4 -0
  48. package/dist/index.js.map +1 -1
  49. package/dist/intent/index.d.ts +18 -3
  50. package/dist/intent/index.d.ts.map +1 -1
  51. package/dist/intent/index.js +37 -6
  52. package/dist/intent/index.js.map +1 -1
  53. package/dist/intent/persistent-intent-service.d.ts +68 -0
  54. package/dist/intent/persistent-intent-service.d.ts.map +1 -0
  55. package/dist/intent/persistent-intent-service.js +265 -0
  56. package/dist/intent/persistent-intent-service.js.map +1 -0
  57. package/dist/intent/supabase-intent-repository.d.ts +124 -0
  58. package/dist/intent/supabase-intent-repository.d.ts.map +1 -0
  59. package/dist/intent/supabase-intent-repository.js +404 -0
  60. package/dist/intent/supabase-intent-repository.js.map +1 -0
  61. package/dist/langchain/tools.d.ts.map +1 -1
  62. package/dist/langchain/tools.js +1 -3
  63. package/dist/langchain/tools.js.map +1 -1
  64. package/dist/layers/implementations/L0-request-format.d.ts +37 -0
  65. package/dist/layers/implementations/L0-request-format.d.ts.map +1 -0
  66. package/dist/layers/implementations/L0-request-format.js +216 -0
  67. package/dist/layers/implementations/L0-request-format.js.map +1 -0
  68. package/dist/layers/implementations/L1-input-size.d.ts +36 -0
  69. package/dist/layers/implementations/L1-input-size.d.ts.map +1 -0
  70. package/dist/layers/implementations/L1-input-size.js +150 -0
  71. package/dist/layers/implementations/L1-input-size.js.map +1 -0
  72. package/dist/layers/implementations/L2-charset-sanitizer.d.ts +28 -0
  73. package/dist/layers/implementations/L2-charset-sanitizer.d.ts.map +1 -0
  74. package/dist/layers/implementations/L2-charset-sanitizer.js +220 -0
  75. package/dist/layers/implementations/L2-charset-sanitizer.js.map +1 -0
  76. package/dist/layers/implementations/L3-schema-conformance.d.ts +47 -0
  77. package/dist/layers/implementations/L3-schema-conformance.d.ts.map +1 -0
  78. package/dist/layers/implementations/L3-schema-conformance.js +258 -0
  79. package/dist/layers/implementations/L3-schema-conformance.js.map +1 -0
  80. package/dist/layers/implementations/L4-injection-detector.d.ts +47 -0
  81. package/dist/layers/implementations/L4-injection-detector.d.ts.map +1 -0
  82. package/dist/layers/implementations/L4-injection-detector.js +256 -0
  83. package/dist/layers/implementations/L4-injection-detector.js.map +1 -0
  84. package/dist/layers/implementations/L5-rate-limiter.d.ts +51 -0
  85. package/dist/layers/implementations/L5-rate-limiter.d.ts.map +1 -0
  86. package/dist/layers/implementations/L5-rate-limiter.js +183 -0
  87. package/dist/layers/implementations/L5-rate-limiter.js.map +1 -0
  88. package/dist/layers/implementations/index.d.ts +16 -0
  89. package/dist/layers/implementations/index.d.ts.map +1 -0
  90. package/dist/layers/implementations/index.js +16 -0
  91. package/dist/layers/implementations/index.js.map +1 -0
  92. package/dist/persistence/sqlite.d.ts.map +1 -1
  93. package/dist/persistence/sqlite.js +4 -3
  94. package/dist/persistence/sqlite.js.map +1 -1
  95. package/dist/persistence/supabase.js +2 -2
  96. package/dist/persistence/supabase.js.map +1 -1
  97. package/dist/phase6/ceiling.js +5 -5
  98. package/dist/phase6/ceiling.js.map +1 -1
  99. package/dist/phase6/context.js +6 -6
  100. package/dist/phase6/context.js.map +1 -1
  101. package/dist/phase6/index.d.ts +1 -1
  102. package/dist/phase6/index.js +1 -1
  103. package/dist/phase6/role-gates.js +2 -2
  104. package/dist/phase6/role-gates.js.map +1 -1
  105. package/dist/phase6/types.d.ts +31 -30
  106. package/dist/phase6/types.d.ts.map +1 -1
  107. package/dist/phase6/types.js +17 -12
  108. package/dist/phase6/types.js.map +1 -1
  109. package/dist/phase6/weight-presets/canonical.d.ts +2 -2
  110. package/dist/phase6/weight-presets/canonical.js +2 -2
  111. package/dist/phase6/weight-presets/index.d.ts +1 -1
  112. package/dist/phase6/weight-presets/index.js +1 -1
  113. package/dist/phase6/weight-presets/merger.d.ts +1 -1
  114. package/dist/phase6/weight-presets/merger.js +1 -1
  115. package/dist/proof/merkle.d.ts +21 -0
  116. package/dist/proof/merkle.d.ts.map +1 -1
  117. package/dist/proof/merkle.js +92 -7
  118. package/dist/proof/merkle.js.map +1 -1
  119. package/dist/trust-engine/ceiling-enforcement/kernel.d.ts +11 -9
  120. package/dist/trust-engine/ceiling-enforcement/kernel.d.ts.map +1 -1
  121. package/dist/trust-engine/ceiling-enforcement/kernel.js +25 -19
  122. package/dist/trust-engine/ceiling-enforcement/kernel.js.map +1 -1
  123. package/dist/trust-engine/decay-profiles.d.ts +37 -136
  124. package/dist/trust-engine/decay-profiles.d.ts.map +1 -1
  125. package/dist/trust-engine/decay-profiles.js +68 -178
  126. package/dist/trust-engine/decay-profiles.js.map +1 -1
  127. package/dist/trust-engine/index.d.ts +96 -63
  128. package/dist/trust-engine/index.d.ts.map +1 -1
  129. package/dist/trust-engine/index.js +183 -112
  130. package/dist/trust-engine/index.js.map +1 -1
  131. package/dist/trust-engine/phase6-types.d.ts +10 -3
  132. package/dist/trust-engine/phase6-types.d.ts.map +1 -1
  133. package/dist/trust-engine/phase6-types.js +19 -13
  134. package/dist/trust-engine/phase6-types.js.map +1 -1
  135. package/package.json +5 -4
@@ -0,0 +1,822 @@
1
+ /**
2
+ * Trust-Aware CrewAI Executor
3
+ *
4
+ * Wraps CrewAI crews and tasks with trust-based access control.
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+ import { createLogger } from '../common/logger.js';
9
+ import { TrustInsufficientError } from '../common/types.js';
10
+ import { TRUST_LEVEL_NAMES } from '../trust-engine/index.js';
11
+ import { createCrewTrustCallback } from './callback.js';
12
+ const logger = createLogger({ component: 'crewai-executor' });
13
+ // =============================================================================
14
+ // CREW AGENT EXECUTOR
15
+ // =============================================================================
16
+ /**
17
+ * Trust-aware executor for a single crew agent
18
+ *
19
+ * Provides trust-gated task execution and delegation for CrewAI agents.
20
+ */
21
+ export class CrewAgentExecutor {
22
+ trustEngine;
23
+ callback;
24
+ config;
25
+ constructor(trustEngine, config) {
26
+ this.trustEngine = trustEngine;
27
+ this.config = config;
28
+ this.callback = createCrewTrustCallback(trustEngine, config);
29
+ }
30
+ /**
31
+ * Get the callback handler
32
+ */
33
+ get callbackHandler() {
34
+ return this.callback;
35
+ }
36
+ /**
37
+ * Get the agent ID
38
+ */
39
+ get agentId() {
40
+ return this.config.agentId;
41
+ }
42
+ /**
43
+ * Get the agent role
44
+ */
45
+ get role() {
46
+ return this.config.role;
47
+ }
48
+ /**
49
+ * Initialize the executor
50
+ */
51
+ async initialize() {
52
+ await this.callback.initialize();
53
+ }
54
+ /**
55
+ * Check if the agent has sufficient trust
56
+ */
57
+ async checkTrust(requiredLevel) {
58
+ const minLevel = requiredLevel ?? this.config.minTrustLevel ?? 1;
59
+ const record = await this.trustEngine.getScore(this.config.agentId);
60
+ if (!record) {
61
+ return {
62
+ allowed: false,
63
+ agentId: this.config.agentId,
64
+ currentLevel: 0,
65
+ currentScore: 0,
66
+ requiredLevel: minLevel,
67
+ reason: 'Agent not initialized in trust engine',
68
+ };
69
+ }
70
+ const allowed = record.level >= minLevel;
71
+ return {
72
+ allowed,
73
+ agentId: this.config.agentId,
74
+ currentLevel: record.level,
75
+ currentScore: record.score,
76
+ requiredLevel: minLevel,
77
+ reason: allowed
78
+ ? `Trust level ${TRUST_LEVEL_NAMES[record.level]} meets requirement`
79
+ : `Trust level ${TRUST_LEVEL_NAMES[record.level]} below required ${TRUST_LEVEL_NAMES[minLevel]}`,
80
+ };
81
+ }
82
+ /**
83
+ * Execute a task with trust gating
84
+ *
85
+ * @param task - Task configuration
86
+ * @param fn - The function to execute (typically the actual CrewAI task runner)
87
+ * @throws TrustInsufficientError if trust is too low
88
+ */
89
+ async executeTask(task, fn) {
90
+ const requiredLevel = task.minTrustLevel ?? this.config.minTrustLevel ?? 1;
91
+ const trustCheck = await this.checkTrust(requiredLevel);
92
+ if (!trustCheck.allowed) {
93
+ logger.warn({
94
+ agentId: this.config.agentId,
95
+ taskId: task.taskId,
96
+ currentLevel: trustCheck.currentLevel,
97
+ requiredLevel: trustCheck.requiredLevel,
98
+ }, 'Task execution blocked due to insufficient trust');
99
+ throw new TrustInsufficientError(trustCheck.requiredLevel, trustCheck.currentLevel);
100
+ }
101
+ const runId = crypto.randomUUID();
102
+ const initialSignals = this.callback.signalsRecorded;
103
+ await this.callback.handleTaskStart(task.taskId, runId);
104
+ try {
105
+ const result = await fn();
106
+ await this.callback.handleTaskEnd(task.taskId, runId);
107
+ const finalRecord = await this.trustEngine.getScore(this.config.agentId);
108
+ logger.info({
109
+ agentId: this.config.agentId,
110
+ taskId: task.taskId,
111
+ signalsRecorded: this.callback.signalsRecorded - initialSignals,
112
+ finalScore: finalRecord?.score,
113
+ }, 'Trusted task execution completed');
114
+ return {
115
+ result,
116
+ taskId: task.taskId,
117
+ agentId: this.config.agentId,
118
+ trustCheck,
119
+ signalsRecorded: this.callback.signalsRecorded - initialSignals,
120
+ finalScore: finalRecord?.score ?? 0,
121
+ finalLevel: finalRecord?.level ?? 0,
122
+ };
123
+ }
124
+ catch (error) {
125
+ await this.callback.handleTaskError(task.taskId, error instanceof Error ? error : new Error(String(error)), runId);
126
+ throw error;
127
+ }
128
+ }
129
+ /**
130
+ * Delegate a task to another agent with trust gating on both sides
131
+ *
132
+ * @param task - Task to delegate
133
+ * @param targetExecutor - The target agent's executor
134
+ * @param fn - The function to execute on the target agent
135
+ * @throws TrustInsufficientError if either agent lacks trust
136
+ */
137
+ async delegateTask(task, targetExecutor, fn) {
138
+ if (this.config.allowDelegation === false) {
139
+ throw new Error(`Agent ${this.config.agentId} is not allowed to delegate tasks`);
140
+ }
141
+ // Check delegator trust
142
+ const delegatorCheck = await this.checkTrust();
143
+ if (!delegatorCheck.allowed) {
144
+ throw new TrustInsufficientError(delegatorCheck.requiredLevel, delegatorCheck.currentLevel);
145
+ }
146
+ // Check delegatee trust
147
+ const delegateeCheck = await targetExecutor.checkTrust(task.minTrustLevel ?? this.config.minTrustLevel ?? 1);
148
+ if (!delegateeCheck.allowed) {
149
+ throw new TrustInsufficientError(delegateeCheck.requiredLevel, delegateeCheck.currentLevel);
150
+ }
151
+ const runId = crypto.randomUUID();
152
+ await this.callback.handleDelegationStart(targetExecutor.agentId, task.taskId, runId);
153
+ try {
154
+ const result = await fn();
155
+ await this.callback.handleDelegationEnd(targetExecutor.agentId, task.taskId, runId);
156
+ logger.info({
157
+ from: this.config.agentId,
158
+ to: targetExecutor.agentId,
159
+ taskId: task.taskId,
160
+ }, 'Task delegation completed');
161
+ return {
162
+ result,
163
+ fromAgentId: this.config.agentId,
164
+ toAgentId: targetExecutor.agentId,
165
+ trustCheck: delegatorCheck,
166
+ delegateeTrustCheck: delegateeCheck,
167
+ };
168
+ }
169
+ catch (error) {
170
+ await this.callback.handleDelegationError(targetExecutor.agentId, task.taskId, error instanceof Error ? error : new Error(String(error)), runId);
171
+ throw error;
172
+ }
173
+ }
174
+ /**
175
+ * Get current trust record for the agent
176
+ */
177
+ async getTrustRecord() {
178
+ return this.trustEngine.getScore(this.config.agentId);
179
+ }
180
+ /**
181
+ * Manually record a positive signal
182
+ */
183
+ async recordSuccess(type, value = 0.85) {
184
+ await this.trustEngine.recordSignal({
185
+ id: crypto.randomUUID(),
186
+ entityId: this.config.agentId,
187
+ type: `behavioral.${type}`,
188
+ value,
189
+ source: 'crewai-manual',
190
+ timestamp: new Date().toISOString(),
191
+ metadata: { role: this.config.role },
192
+ });
193
+ }
194
+ /**
195
+ * Manually record a negative signal
196
+ */
197
+ async recordFailure(type, value = 0.1) {
198
+ await this.trustEngine.recordSignal({
199
+ id: crypto.randomUUID(),
200
+ entityId: this.config.agentId,
201
+ type: `behavioral.${type}`,
202
+ value,
203
+ source: 'crewai-manual',
204
+ timestamp: new Date().toISOString(),
205
+ metadata: { role: this.config.role },
206
+ });
207
+ }
208
+ }
209
+ // =============================================================================
210
+ // CREW EXECUTOR
211
+ // =============================================================================
212
+ /**
213
+ * Trust-aware crew executor
214
+ *
215
+ * Manages a crew of agents with collective trust governance.
216
+ * Ensures all agents meet minimum trust requirements before crew execution.
217
+ */
218
+ export class CrewExecutor {
219
+ trustEngine;
220
+ config;
221
+ agents = new Map();
222
+ constructor(trustEngine, config) {
223
+ this.trustEngine = trustEngine;
224
+ this.config = {
225
+ crewId: config.crewId,
226
+ process: config.process ?? 'sequential',
227
+ minCrewTrust: config.minCrewTrust ?? 1,
228
+ maxTaskFailures: config.maxTaskFailures ?? 0,
229
+ recordCrewEvents: config.recordCrewEvents ?? true,
230
+ };
231
+ }
232
+ /**
233
+ * Get the crew ID
234
+ */
235
+ get crewId() {
236
+ return this.config.crewId;
237
+ }
238
+ /**
239
+ * Get the execution process type
240
+ */
241
+ get process() {
242
+ return this.config.process;
243
+ }
244
+ /**
245
+ * Get all agent executors
246
+ */
247
+ get agentExecutors() {
248
+ return Array.from(this.agents.values());
249
+ }
250
+ /**
251
+ * Add an agent to the crew
252
+ */
253
+ addAgent(executor) {
254
+ this.agents.set(executor.agentId, executor);
255
+ }
256
+ /**
257
+ * Get an agent executor by ID
258
+ */
259
+ getAgent(agentId) {
260
+ return this.agents.get(agentId);
261
+ }
262
+ /**
263
+ * Initialize all agents in the crew
264
+ */
265
+ async initialize() {
266
+ for (const agent of this.agents.values()) {
267
+ await agent.initialize();
268
+ }
269
+ logger.info({ crewId: this.config.crewId, agentCount: this.agents.size }, 'Crew initialized');
270
+ }
271
+ /**
272
+ * Get the average trust level across all crew members
273
+ */
274
+ async getCrewTrust() {
275
+ if (this.agents.size === 0) {
276
+ return { averageScore: 0, averageLevel: 0, allMeetMinimum: false };
277
+ }
278
+ let totalScore = 0;
279
+ let totalLevel = 0;
280
+ let allMeet = true;
281
+ for (const agent of this.agents.values()) {
282
+ const record = await this.trustEngine.getScore(agent.agentId);
283
+ const score = record?.score ?? 0;
284
+ const level = record?.level ?? 0;
285
+ totalScore += score;
286
+ totalLevel += level;
287
+ if (level < this.config.minCrewTrust) {
288
+ allMeet = false;
289
+ }
290
+ }
291
+ return {
292
+ averageScore: totalScore / this.agents.size,
293
+ averageLevel: totalLevel / this.agents.size,
294
+ allMeetMinimum: allMeet,
295
+ };
296
+ }
297
+ /**
298
+ * Execute a set of tasks with the crew
299
+ *
300
+ * Tasks are assigned to agents based on the configured process (sequential/hierarchical).
301
+ * All agents must meet the minimum crew trust requirement.
302
+ *
303
+ * @param tasks - Tasks to execute
304
+ * @param taskRunner - Function that runs a single task given task config and agent executor
305
+ * @throws TrustInsufficientError if any agent fails trust check
306
+ */
307
+ async kickoff(tasks, taskRunner) {
308
+ // Check crew-level trust
309
+ const crewTrust = await this.getCrewTrust();
310
+ if (!crewTrust.allMeetMinimum) {
311
+ throw new TrustInsufficientError(this.config.minCrewTrust, Math.floor(crewTrust.averageLevel));
312
+ }
313
+ const agentList = Array.from(this.agents.values());
314
+ if (agentList.length === 0) {
315
+ throw new Error('Crew has no agents');
316
+ }
317
+ const results = [];
318
+ let tasksFailed = 0;
319
+ for (let i = 0; i < tasks.length; i++) {
320
+ const task = tasks[i];
321
+ // Determine which agent handles this task
322
+ let agent;
323
+ if (task.assignedAgentId && this.agents.has(task.assignedAgentId)) {
324
+ agent = this.agents.get(task.assignedAgentId);
325
+ }
326
+ else {
327
+ // Round-robin assignment
328
+ agent = agentList[i % agentList.length];
329
+ }
330
+ try {
331
+ const taskResult = await agent.executeTask(task, () => taskRunner(task, agent));
332
+ results.push(taskResult);
333
+ }
334
+ catch (error) {
335
+ tasksFailed++;
336
+ if (tasksFailed > this.config.maxTaskFailures) {
337
+ logger.warn({
338
+ crewId: this.config.crewId,
339
+ tasksFailed,
340
+ maxAllowed: this.config.maxTaskFailures,
341
+ }, 'Crew aborted due to too many task failures');
342
+ throw error;
343
+ }
344
+ logger.warn({
345
+ crewId: this.config.crewId,
346
+ taskId: task.taskId,
347
+ agentId: agent.agentId,
348
+ error: error instanceof Error ? error.message : String(error),
349
+ }, 'Task failed within tolerance, continuing');
350
+ }
351
+ }
352
+ let totalSignals = 0;
353
+ for (const agent of this.agents.values()) {
354
+ totalSignals += agent.callbackHandler.signalsRecorded;
355
+ }
356
+ return {
357
+ results,
358
+ crewId: this.config.crewId,
359
+ crewTrust: crewTrust.averageScore,
360
+ totalSignalsRecorded: totalSignals,
361
+ tasksFailed,
362
+ tasksCompleted: results.length,
363
+ };
364
+ }
365
+ }
366
+ // =============================================================================
367
+ // FACTORY FUNCTIONS
368
+ // =============================================================================
369
+ /**
370
+ * Create a trust-aware crew agent executor
371
+ */
372
+ export function createCrewAgentExecutor(trustEngine, config) {
373
+ return new CrewAgentExecutor(trustEngine, config);
374
+ }
375
+ /**
376
+ * Create a trust-aware crew executor
377
+ */
378
+ export function createCrewExecutor(trustEngine, config) {
379
+ return new CrewExecutor(trustEngine, config);
380
+ }
381
+ // =============================================================================
382
+ // TRUST-GATED CREW EXECUTOR
383
+ // =============================================================================
384
+ const gatedLogger = createLogger({ component: 'trust-gated-crew-executor' });
385
+ /**
386
+ * Trust-Gated Crew Executor
387
+ *
388
+ * High-level wrapper that composes TrustEngine + CrewExecutor + TrustAwareEnforcementService
389
+ * to provide a full intent -> enforce -> execute pipeline with live trust gating.
390
+ *
391
+ * Features:
392
+ * - Pre-task trust score checks with configurable thresholds
393
+ * - Optional enforcement service integration (intent -> enforce -> execute)
394
+ * - Automatic trust decay signals on task failures
395
+ * - Automatic trust recovery signals on task successes
396
+ * - Detailed logging of all trust decisions
397
+ * - Backwards-compatible: enforcement service is optional
398
+ */
399
+ export class TrustGatedCrewExecutor {
400
+ trustEngine;
401
+ crewExecutor;
402
+ enforcementService;
403
+ config;
404
+ constructor(trustEngine, config, enforcementService) {
405
+ this.trustEngine = trustEngine;
406
+ this.enforcementService = enforcementService ?? null;
407
+ this.config = {
408
+ crew: config.crew,
409
+ agents: config.agents,
410
+ trustScoreThreshold: config.trustScoreThreshold ?? 200,
411
+ trustLevelThreshold: config.trustLevelThreshold ?? 1,
412
+ failureDecaySignalValue: config.failureDecaySignalValue ?? 0.1,
413
+ successRecoverySignalValue: config.successRecoverySignalValue ?? 0.85,
414
+ tenantId: config.tenantId ?? 'default',
415
+ enableEnforcement: config.enableEnforcement ?? true,
416
+ };
417
+ // Create the inner crew executor
418
+ this.crewExecutor = new CrewExecutor(trustEngine, config.crew);
419
+ // Create and add agent executors
420
+ for (const agentConfig of this.config.agents) {
421
+ const agentExecutor = new CrewAgentExecutor(trustEngine, agentConfig);
422
+ this.crewExecutor.addAgent(agentExecutor);
423
+ }
424
+ gatedLogger.info({
425
+ crewId: config.crew.crewId,
426
+ agentCount: config.agents.length,
427
+ trustScoreThreshold: this.config.trustScoreThreshold,
428
+ trustLevelThreshold: this.config.trustLevelThreshold,
429
+ enforcementEnabled: this.config.enableEnforcement && this.enforcementService !== null,
430
+ }, 'TrustGatedCrewExecutor created');
431
+ }
432
+ /**
433
+ * Get the inner CrewExecutor
434
+ */
435
+ get executor() {
436
+ return this.crewExecutor;
437
+ }
438
+ /**
439
+ * Get the TrustEngine instance
440
+ */
441
+ get engine() {
442
+ return this.trustEngine;
443
+ }
444
+ /**
445
+ * Get the crew ID
446
+ */
447
+ get crewId() {
448
+ return this.crewExecutor.crewId;
449
+ }
450
+ /**
451
+ * Initialize all agents in the crew
452
+ */
453
+ async initialize() {
454
+ await this.crewExecutor.initialize();
455
+ gatedLogger.info({ crewId: this.crewId }, 'TrustGatedCrewExecutor initialized');
456
+ }
457
+ /**
458
+ * Check if an agent passes the trust gate for a task.
459
+ *
460
+ * Performs two checks:
461
+ * 1. Trust score threshold check (score >= configured threshold)
462
+ * 2. Trust level threshold check (level >= configured threshold)
463
+ *
464
+ * If enforcement service is available and enabled, also runs full enforcement.
465
+ */
466
+ async checkTrustGate(agentId, task) {
467
+ const t0 = performance.now();
468
+ const record = await this.trustEngine.getScore(agentId);
469
+ if (!record) {
470
+ gatedLogger.warn({ agentId, taskId: task.taskId }, 'Trust gate denied: agent has no trust record');
471
+ return {
472
+ allowed: false,
473
+ trustScore: 0,
474
+ trustLevel: 0,
475
+ reason: `Agent ${agentId} has no trust record in the engine`,
476
+ };
477
+ }
478
+ const currentScore = record.score;
479
+ const currentLevel = record.level;
480
+ // Check score threshold
481
+ if (currentScore < this.config.trustScoreThreshold) {
482
+ const reason = `Trust score ${currentScore} is below threshold ${this.config.trustScoreThreshold}`;
483
+ gatedLogger.warn({
484
+ agentId,
485
+ taskId: task.taskId,
486
+ currentScore,
487
+ threshold: this.config.trustScoreThreshold,
488
+ latencyMs: Math.round(performance.now() - t0),
489
+ }, `Trust gate denied: ${reason}`);
490
+ return { allowed: false, trustScore: currentScore, trustLevel: currentLevel, reason };
491
+ }
492
+ // Check level threshold
493
+ const requiredLevel = task.minTrustLevel ?? this.config.trustLevelThreshold;
494
+ if (currentLevel < requiredLevel) {
495
+ const reason = `Trust level ${TRUST_LEVEL_NAMES[currentLevel]} (T${currentLevel}) is below required ${TRUST_LEVEL_NAMES[requiredLevel]} (T${requiredLevel})`;
496
+ gatedLogger.warn({
497
+ agentId,
498
+ taskId: task.taskId,
499
+ currentLevel,
500
+ requiredLevel,
501
+ latencyMs: Math.round(performance.now() - t0),
502
+ }, `Trust gate denied: ${reason}`);
503
+ return { allowed: false, trustScore: currentScore, trustLevel: currentLevel, reason };
504
+ }
505
+ // If enforcement service is available and enabled, run full enforcement
506
+ if (this.enforcementService && this.config.enableEnforcement) {
507
+ const enforcementResult = await this.runEnforcement(agentId, task, currentScore, currentLevel);
508
+ if (enforcementResult) {
509
+ const tier = enforcementResult.tier;
510
+ if (tier === 'RED') {
511
+ const reason = `Enforcement denied (RED): ${enforcementResult.decision.denialReason ?? 'policy violation'}`;
512
+ gatedLogger.warn({
513
+ agentId,
514
+ taskId: task.taskId,
515
+ tier,
516
+ decisionId: enforcementResult.decision.id,
517
+ latencyMs: Math.round(performance.now() - t0),
518
+ }, `Trust gate denied via enforcement: ${reason}`);
519
+ return {
520
+ allowed: false,
521
+ trustScore: currentScore,
522
+ trustLevel: currentLevel,
523
+ enforcementResult,
524
+ reason,
525
+ };
526
+ }
527
+ if (tier === 'YELLOW') {
528
+ const reason = `Enforcement requires refinement (YELLOW): ${enforcementResult.decision.reasoning.join('; ')}`;
529
+ gatedLogger.info({
530
+ agentId,
531
+ taskId: task.taskId,
532
+ tier,
533
+ decisionId: enforcementResult.decision.id,
534
+ refinementOptions: enforcementResult.refinementOptions?.length ?? 0,
535
+ latencyMs: Math.round(performance.now() - t0),
536
+ }, `Trust gate pending refinement: ${reason}`);
537
+ // YELLOW is treated as denied for automatic execution; callers can refine manually
538
+ return {
539
+ allowed: false,
540
+ trustScore: currentScore,
541
+ trustLevel: currentLevel,
542
+ enforcementResult,
543
+ reason,
544
+ };
545
+ }
546
+ // GREEN - allowed
547
+ gatedLogger.info({
548
+ agentId,
549
+ taskId: task.taskId,
550
+ tier,
551
+ decisionId: enforcementResult.decision.id,
552
+ trustScore: currentScore,
553
+ trustLevel: currentLevel,
554
+ latencyMs: Math.round(performance.now() - t0),
555
+ }, 'Trust gate allowed via enforcement (GREEN)');
556
+ return {
557
+ allowed: true,
558
+ trustScore: currentScore,
559
+ trustLevel: currentLevel,
560
+ enforcementResult,
561
+ reason: `Enforcement approved (GREEN): trust T${currentLevel} (${TRUST_LEVEL_NAMES[currentLevel]}), score ${currentScore}`,
562
+ };
563
+ }
564
+ }
565
+ // No enforcement service or enforcement disabled - use direct trust check
566
+ const reason = `Trust gate passed: T${currentLevel} (${TRUST_LEVEL_NAMES[currentLevel]}), score ${currentScore}`;
567
+ gatedLogger.info({
568
+ agentId,
569
+ taskId: task.taskId,
570
+ trustScore: currentScore,
571
+ trustLevel: currentLevel,
572
+ latencyMs: Math.round(performance.now() - t0),
573
+ }, reason);
574
+ return { allowed: true, trustScore: currentScore, trustLevel: currentLevel, reason };
575
+ }
576
+ /**
577
+ * Execute a single task through the trust gate.
578
+ *
579
+ * Pipeline: check trust -> (optional) enforce -> execute -> record signals
580
+ */
581
+ async executeGatedTask(task, taskRunner) {
582
+ const t0 = performance.now();
583
+ // Resolve agent
584
+ const agent = this.resolveAgent(task);
585
+ if (!agent) {
586
+ return {
587
+ allowed: false,
588
+ agentId: task.assignedAgentId ?? 'unassigned',
589
+ taskId: task.taskId,
590
+ trustScoreAtDecision: 0,
591
+ trustLevelAtDecision: 0,
592
+ reason: `No agent available for task ${task.taskId}`,
593
+ gatingLatencyMs: Math.round(performance.now() - t0),
594
+ };
595
+ }
596
+ // Check trust gate
597
+ const gateResult = await this.checkTrustGate(agent.agentId, task);
598
+ const gatingLatencyMs = Math.round(performance.now() - t0);
599
+ if (!gateResult.allowed) {
600
+ // Record failure signal for trust decay on denial
601
+ await this.recordTrustSignal(agent.agentId, 'behavioral.task_gated_denied', this.config.failureDecaySignalValue, { taskId: task.taskId, reason: gateResult.reason });
602
+ return {
603
+ allowed: false,
604
+ agentId: agent.agentId,
605
+ taskId: task.taskId,
606
+ trustScoreAtDecision: gateResult.trustScore,
607
+ trustLevelAtDecision: gateResult.trustLevel,
608
+ enforcementTier: gateResult.enforcementResult?.tier,
609
+ reason: gateResult.reason,
610
+ gatingLatencyMs,
611
+ };
612
+ }
613
+ // Execute the task through the agent executor
614
+ try {
615
+ const taskResult = await agent.executeTask(task, () => taskRunner(task, agent));
616
+ // Record success signal for trust recovery
617
+ await this.recordTrustSignal(agent.agentId, 'behavioral.task_gated_success', this.config.successRecoverySignalValue, { taskId: task.taskId });
618
+ gatedLogger.info({
619
+ agentId: agent.agentId,
620
+ taskId: task.taskId,
621
+ finalScore: taskResult.finalScore,
622
+ finalLevel: taskResult.finalLevel,
623
+ gatingLatencyMs,
624
+ }, 'Trust-gated task completed successfully');
625
+ return {
626
+ allowed: true,
627
+ result: taskResult,
628
+ agentId: agent.agentId,
629
+ taskId: task.taskId,
630
+ trustScoreAtDecision: gateResult.trustScore,
631
+ trustLevelAtDecision: gateResult.trustLevel,
632
+ enforcementTier: gateResult.enforcementResult?.tier,
633
+ reason: gateResult.reason,
634
+ gatingLatencyMs,
635
+ };
636
+ }
637
+ catch (error) {
638
+ // Record failure signal for trust decay
639
+ await this.recordTrustSignal(agent.agentId, 'behavioral.task_gated_failure', this.config.failureDecaySignalValue, {
640
+ taskId: task.taskId,
641
+ error: error instanceof Error ? error.message : String(error),
642
+ });
643
+ gatedLogger.warn({
644
+ agentId: agent.agentId,
645
+ taskId: task.taskId,
646
+ error: error instanceof Error ? error.message : String(error),
647
+ gatingLatencyMs,
648
+ }, 'Trust-gated task failed during execution');
649
+ throw error;
650
+ }
651
+ }
652
+ /**
653
+ * Execute a full crew kickoff with trust gating on every task.
654
+ *
655
+ * Unlike the inner CrewExecutor.kickoff(), this method:
656
+ * - Checks trust gate before each task individually
657
+ * - Skips tasks that fail the trust gate (instead of throwing)
658
+ * - Records trust signals after each success/failure
659
+ * - Returns a comprehensive result including denied tasks
660
+ */
661
+ async kickoff(tasks, taskRunner) {
662
+ gatedLogger.info({ crewId: this.crewId, taskCount: tasks.length }, 'Trust-gated crew kickoff starting');
663
+ const taskResults = [];
664
+ let tasksCompleted = 0;
665
+ let tasksDeniedByTrust = 0;
666
+ let tasksFailed = 0;
667
+ for (const task of tasks) {
668
+ try {
669
+ const result = await this.executeGatedTask(task, taskRunner);
670
+ taskResults.push(result);
671
+ if (result.allowed && result.result) {
672
+ tasksCompleted++;
673
+ }
674
+ else if (!result.allowed) {
675
+ tasksDeniedByTrust++;
676
+ }
677
+ }
678
+ catch (error) {
679
+ tasksFailed++;
680
+ // Capture as a failed result rather than propagating
681
+ const agent = this.resolveAgent(task);
682
+ taskResults.push({
683
+ allowed: true, // it was allowed, but failed during execution
684
+ agentId: agent?.agentId ?? task.assignedAgentId ?? 'unknown',
685
+ taskId: task.taskId,
686
+ trustScoreAtDecision: 0,
687
+ trustLevelAtDecision: 0,
688
+ reason: `Task execution failed: ${error instanceof Error ? error.message : String(error)}`,
689
+ gatingLatencyMs: 0,
690
+ });
691
+ // Check if we've exceeded max task failures
692
+ if (tasksFailed > (this.config.crew.maxTaskFailures ?? 0)) {
693
+ gatedLogger.warn({
694
+ crewId: this.crewId,
695
+ tasksFailed,
696
+ maxAllowed: this.config.crew.maxTaskFailures ?? 0,
697
+ }, 'Trust-gated crew aborted due to too many task failures');
698
+ break;
699
+ }
700
+ }
701
+ }
702
+ gatedLogger.info({
703
+ crewId: this.crewId,
704
+ totalTasks: tasks.length,
705
+ tasksCompleted,
706
+ tasksDeniedByTrust,
707
+ tasksFailed,
708
+ }, 'Trust-gated crew kickoff completed');
709
+ return {
710
+ taskResults,
711
+ totalTasks: tasks.length,
712
+ tasksCompleted,
713
+ tasksDeniedByTrust,
714
+ tasksFailed,
715
+ crewId: this.crewId,
716
+ };
717
+ }
718
+ // ===========================================================================
719
+ // Private helpers
720
+ // ===========================================================================
721
+ /**
722
+ * Resolve the agent executor for a given task
723
+ */
724
+ resolveAgent(task) {
725
+ if (task.assignedAgentId) {
726
+ return this.crewExecutor.getAgent(task.assignedAgentId);
727
+ }
728
+ // Return the first available agent as fallback
729
+ const agents = this.crewExecutor.agentExecutors;
730
+ return agents.length > 0 ? agents[0] : undefined;
731
+ }
732
+ /**
733
+ * Run enforcement pipeline: build intent -> call TrustAwareEnforcementService.decide()
734
+ */
735
+ async runEnforcement(agentId, task, trustScore, trustLevel) {
736
+ if (!this.enforcementService)
737
+ return null;
738
+ try {
739
+ // Build a synthetic intent from the task
740
+ const intent = {
741
+ id: `crew-task-${task.taskId}-${crypto.randomUUID()}`,
742
+ entityId: agentId,
743
+ goal: task.description,
744
+ context: { taskId: task.taskId, crewId: this.crewId },
745
+ metadata: { source: 'trust-gated-crew-executor', expectedOutput: task.expectedOutput },
746
+ status: 'pending',
747
+ createdAt: new Date().toISOString(),
748
+ updatedAt: new Date().toISOString(),
749
+ actionType: 'execute',
750
+ dataSensitivity: 'CONFIDENTIAL',
751
+ reversibility: 'REVERSIBLE',
752
+ };
753
+ // Build a minimal passing evaluation (the trust check is what matters)
754
+ const evaluation = {
755
+ passed: true,
756
+ finalAction: 'allow',
757
+ rulesEvaluated: [],
758
+ violatedRules: [],
759
+ totalDurationMs: 0,
760
+ evaluatedAt: new Date().toISOString(),
761
+ };
762
+ const context = {
763
+ intent,
764
+ evaluation,
765
+ trustScore,
766
+ trustLevel,
767
+ tenantId: this.config.tenantId,
768
+ };
769
+ const result = await this.enforcementService.decide(context);
770
+ gatedLogger.debug({
771
+ agentId,
772
+ taskId: task.taskId,
773
+ tier: result.tier,
774
+ decisionId: result.decision.id,
775
+ }, 'Enforcement decision completed for trust-gated task');
776
+ return result;
777
+ }
778
+ catch (error) {
779
+ gatedLogger.error({
780
+ agentId,
781
+ taskId: task.taskId,
782
+ error: error instanceof Error ? error.message : String(error),
783
+ }, 'Enforcement service error during trust-gated execution; falling back to trust-only check');
784
+ return null;
785
+ }
786
+ }
787
+ /**
788
+ * Record a trust signal to the engine
789
+ */
790
+ async recordTrustSignal(agentId, type, value, metadata) {
791
+ try {
792
+ await this.trustEngine.recordSignal({
793
+ id: crypto.randomUUID(),
794
+ entityId: agentId,
795
+ type,
796
+ value,
797
+ source: 'trust-gated-crew-executor',
798
+ timestamp: new Date().toISOString(),
799
+ metadata: { ...metadata, crewId: this.crewId },
800
+ });
801
+ }
802
+ catch (error) {
803
+ gatedLogger.error({
804
+ agentId,
805
+ type,
806
+ value,
807
+ error: error instanceof Error ? error.message : String(error),
808
+ }, 'Failed to record trust signal');
809
+ }
810
+ }
811
+ }
812
+ /**
813
+ * Create a TrustGatedCrewExecutor
814
+ *
815
+ * @param trustEngine - The TrustEngine instance for score lookups and signal recording
816
+ * @param config - Configuration for the gated executor
817
+ * @param enforcementService - Optional TrustAwareEnforcementService for full intent enforcement
818
+ */
819
+ export function createTrustGatedCrewExecutor(trustEngine, config, enforcementService) {
820
+ return new TrustGatedCrewExecutor(trustEngine, config, enforcementService);
821
+ }
822
+ //# sourceMappingURL=executor.js.map