@securecode-ai/mcp 0.5.5 → 0.5.7
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 +52 -12
- package/dist/api/types.d.ts +7 -0
- package/dist/approval/auditLog.d.ts +1 -1
- package/dist/approval/auditLog.js +11 -3
- package/dist/approval/auditLog.js.map +1 -1
- package/dist/approval/broker.d.ts +7 -2
- package/dist/approval/broker.js +239 -110
- package/dist/approval/broker.js.map +1 -1
- package/dist/approval/policy.d.ts +10 -0
- package/dist/approval/policy.js +104 -0
- package/dist/approval/policy.js.map +1 -0
- package/dist/approval/types.d.ts +11 -2
- package/dist/approval/types.js +10 -1
- package/dist/approval/types.js.map +1 -1
- package/dist/attack/agentScanExecutor.d.ts +35 -1
- package/dist/attack/agentScanExecutor.js +405 -76
- package/dist/attack/agentScanExecutor.js.map +1 -1
- package/dist/attack/agentScanLoop.d.ts +20 -0
- package/dist/attack/agentScanLoop.js +1264 -60
- package/dist/attack/agentScanLoop.js.map +1 -1
- package/dist/attack/agentScanProtocol.d.ts +382 -6
- package/dist/attack/agentScanProtocol.js +110 -4
- package/dist/attack/agentScanProtocol.js.map +1 -1
- package/dist/attack/agentTrace.d.ts +73 -0
- package/dist/attack/agentTrace.js +228 -0
- package/dist/attack/agentTrace.js.map +1 -0
- package/dist/attack/architectureScoutExecutor.d.ts +18 -0
- package/dist/attack/architectureScoutExecutor.js +211 -0
- package/dist/attack/architectureScoutExecutor.js.map +1 -0
- package/dist/attack/architectureScoutLoop.d.ts +36 -0
- package/dist/attack/architectureScoutLoop.js +403 -0
- package/dist/attack/architectureScoutLoop.js.map +1 -0
- package/dist/attack/architectureScoutProtocol.d.ts +209 -0
- package/dist/attack/architectureScoutProtocol.js +47 -0
- package/dist/attack/architectureScoutProtocol.js.map +1 -0
- package/dist/attack/candidateStore.d.ts +95 -0
- package/dist/attack/candidateStore.js +231 -0
- package/dist/attack/candidateStore.js.map +1 -0
- package/dist/attack/evidenceLedger.d.ts +67 -0
- package/dist/attack/evidenceLedger.js +192 -0
- package/dist/attack/evidenceLedger.js.map +1 -0
- package/dist/attack/finishGate.d.ts +62 -0
- package/dist/attack/finishGate.js +209 -0
- package/dist/attack/finishGate.js.map +1 -0
- package/dist/attack/fixCodeMerge.d.ts +27 -0
- package/dist/attack/fixCodeMerge.js +42 -0
- package/dist/attack/fixCodeMerge.js.map +1 -0
- package/dist/attack/fixVerifyLoop.d.ts +55 -0
- package/dist/attack/fixVerifyLoop.js +187 -0
- package/dist/attack/fixVerifyLoop.js.map +1 -0
- package/dist/attack/investigationProfiles.d.ts +36 -0
- package/dist/attack/investigationProfiles.js +144 -0
- package/dist/attack/investigationProfiles.js.map +1 -0
- package/dist/attack/investigationState.d.ts +227 -0
- package/dist/attack/investigationState.js +666 -0
- package/dist/attack/investigationState.js.map +1 -0
- package/dist/attack/mutationOperators.d.ts +22 -0
- package/dist/attack/mutationOperators.js +170 -0
- package/dist/attack/mutationOperators.js.map +1 -0
- package/dist/attack/mutationTest.d.ts +33 -0
- package/dist/attack/mutationTest.js +110 -0
- package/dist/attack/mutationTest.js.map +1 -0
- package/dist/attack/proofGate.d.ts +20 -0
- package/dist/attack/proofGate.js +104 -0
- package/dist/attack/proofGate.js.map +1 -0
- package/dist/attack/proofTypes.d.ts +57 -0
- package/dist/attack/proofTypes.js +32 -0
- package/dist/attack/proofTypes.js.map +1 -0
- package/dist/attack/protocolValidator.d.ts +50 -0
- package/dist/attack/protocolValidator.js +427 -0
- package/dist/attack/protocolValidator.js.map +1 -0
- package/dist/attack/qualityMetrics.d.ts +133 -0
- package/dist/attack/qualityMetrics.js +226 -0
- package/dist/attack/qualityMetrics.js.map +1 -0
- package/dist/attack/scanScheduler.d.ts +52 -0
- package/dist/attack/scanScheduler.js +265 -0
- package/dist/attack/scanScheduler.js.map +1 -0
- package/dist/attack/scanState.d.ts +58 -0
- package/dist/attack/scanState.js +102 -0
- package/dist/attack/scanState.js.map +1 -0
- package/dist/attack/searchIntent.d.ts +16 -0
- package/dist/attack/searchIntent.js +57 -0
- package/dist/attack/searchIntent.js.map +1 -0
- package/dist/attack/verifyLoop.d.ts +43 -0
- package/dist/attack/verifyLoop.js +314 -14
- package/dist/attack/verifyLoop.js.map +1 -1
- package/dist/attack/workItem.d.ts +57 -0
- package/dist/attack/workItem.js +225 -0
- package/dist/attack/workItem.js.map +1 -0
- package/dist/audit/findingReviewQueue.d.ts +109 -0
- package/dist/audit/findingReviewQueue.js +335 -0
- package/dist/audit/findingReviewQueue.js.map +1 -0
- package/dist/audit/scanAuditLog.d.ts +160 -0
- package/dist/audit/scanAuditLog.js +404 -0
- package/dist/audit/scanAuditLog.js.map +1 -0
- package/dist/dependency/dependencyChecker.js +35 -9
- package/dist/dependency/dependencyChecker.js.map +1 -1
- package/dist/dependency/exploitPriority.d.ts +33 -0
- package/dist/dependency/exploitPriority.js +78 -0
- package/dist/dependency/exploitPriority.js.map +1 -0
- package/dist/dependency/finding.d.ts +16 -0
- package/dist/dependency/osvClient.js +2 -0
- package/dist/dependency/osvClient.js.map +1 -1
- package/dist/dependency/types.d.ts +12 -1
- package/dist/mcp/server.js +13 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts +1 -0
- package/dist/mcp/tools.js +127 -6
- package/dist/mcp/tools.js.map +1 -1
- package/dist/project-map/agentMemory.d.ts +83 -1
- package/dist/project-map/agentMemory.js +197 -7
- package/dist/project-map/agentMemory.js.map +1 -1
- package/dist/project-map/architectureContext.d.ts +202 -0
- package/dist/project-map/architectureContext.js +421 -0
- package/dist/project-map/architectureContext.js.map +1 -0
- package/dist/project-map/blastRadius.d.ts +54 -0
- package/dist/project-map/blastRadius.js +196 -0
- package/dist/project-map/blastRadius.js.map +1 -0
- package/dist/project-map/callGraphExtractor.d.ts +13 -0
- package/dist/project-map/callGraphExtractor.js +222 -0
- package/dist/project-map/callGraphExtractor.js.map +1 -0
- package/dist/project-map/capabilityRegistry.d.ts +46 -0
- package/dist/project-map/capabilityRegistry.js +91 -0
- package/dist/project-map/capabilityRegistry.js.map +1 -0
- package/dist/project-map/findTests.d.ts +29 -0
- package/dist/project-map/findTests.js +236 -0
- package/dist/project-map/findTests.js.map +1 -0
- package/dist/project-map/handlerInventory.d.ts +112 -0
- package/dist/project-map/handlerInventory.js +184 -0
- package/dist/project-map/handlerInventory.js.map +1 -0
- package/dist/project-map/implementationResolver.d.ts +43 -0
- package/dist/project-map/implementationResolver.js +217 -0
- package/dist/project-map/implementationResolver.js.map +1 -0
- package/dist/project-map/mapContext.d.ts +6 -1
- package/dist/project-map/mapContext.js +1 -0
- package/dist/project-map/mapContext.js.map +1 -1
- package/dist/project-map/scanCache.d.ts +57 -3
- package/dist/project-map/scanCache.js +61 -2
- package/dist/project-map/scanCache.js.map +1 -1
- package/dist/project-map/symbolIndex.d.ts +39 -0
- package/dist/project-map/symbolIndex.js +385 -0
- package/dist/project-map/symbolIndex.js.map +1 -0
- package/dist/tooling/agentEvalScoring.d.ts +77 -0
- package/dist/tooling/agentEvalScoring.js +140 -0
- package/dist/tooling/agentEvalScoring.js.map +1 -0
- package/dist/tooling/agentRegression.d.ts +53 -0
- package/dist/tooling/agentRegression.js +99 -0
- package/dist/tooling/agentRegression.js.map +1 -0
- package/dist/tools/agentScan.d.ts +69 -0
- package/dist/tools/agentScan.js +702 -43
- package/dist/tools/agentScan.js.map +1 -1
- package/dist/tools/findingReviewTools.d.ts +22 -0
- package/dist/tools/findingReviewTools.js +121 -0
- package/dist/tools/findingReviewTools.js.map +1 -0
- package/dist/tools/fix.js +1 -1
- package/dist/tools/fix.js.map +1 -1
- package/dist/tools/map.js +191 -1
- package/dist/tools/map.js.map +1 -1
- package/dist/tools/runTests.d.ts +2 -0
- package/dist/tools/runTests.js +29 -0
- package/dist/tools/runTests.js.map +1 -0
- package/dist/utils/effectMock.d.ts +1 -0
- package/dist/utils/effectMock.js +162 -0
- package/dist/utils/effectMock.js.map +1 -0
- package/dist/utils/gitContext.d.ts +26 -0
- package/dist/utils/gitContext.js +317 -0
- package/dist/utils/gitContext.js.map +1 -0
- package/dist/utils/localTestRunner.d.ts +57 -2
- package/dist/utils/localTestRunner.js +122 -115
- package/dist/utils/localTestRunner.js.map +1 -1
- package/dist/utils/securityConfig.d.ts +17 -0
- package/dist/utils/securityConfig.js +192 -0
- package/dist/utils/securityConfig.js.map +1 -0
- package/dist/utils/testCommandPolicy.d.ts +36 -0
- package/dist/utils/testCommandPolicy.js +252 -0
- package/dist/utils/testCommandPolicy.js.map +1 -0
- package/dist/utils/testRunner.d.ts +56 -0
- package/dist/utils/testRunner.js +246 -0
- package/dist/utils/testRunner.js.map +1 -0
- package/dist/utils/testSafety.d.ts +40 -2
- package/dist/utils/testSafety.js +205 -26
- package/dist/utils/testSafety.js.map +1 -1
- package/dist/utils/verificationSandbox.d.ts +113 -0
- package/dist/utils/verificationSandbox.js +656 -0
- package/dist/utils/verificationSandbox.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evidence ledger — tracks why a task or candidate is complete instead of
|
|
3
|
+
* marking checklist steps complete because a tool was merely called.
|
|
4
|
+
*
|
|
5
|
+
* A tool invocation alone does not satisfy an evidence requirement.
|
|
6
|
+
* The ledger records structured evidence with fingerprints and links it
|
|
7
|
+
* to requirements. Progress is derived from newly accepted evidence,
|
|
8
|
+
* not set manually.
|
|
9
|
+
*/
|
|
10
|
+
import type { LineRange } from './investigationState';
|
|
11
|
+
import type { AgentScanActionType } from './agentScanProtocol';
|
|
12
|
+
export type EvidenceKind = 'source-range' | 'symbol-definition' | 'symbol-reference' | 'handler-inventory' | 'policy-result' | 'guard-result' | 'config-result' | 'cross-file-flow' | 'test-location' | 'test-result' | 'implementation-resolution' | 'proof-result' | 'threat-model-result' | 'reachability-result' | 'ownership-result' | 'capability-result';
|
|
13
|
+
export type EvidenceOutcome = 'positive' | 'negative' | 'empty' | 'blocked' | 'error';
|
|
14
|
+
export interface EvidenceRef {
|
|
15
|
+
id: string;
|
|
16
|
+
kind: EvidenceKind;
|
|
17
|
+
transcriptStep: number;
|
|
18
|
+
tool: AgentScanActionType;
|
|
19
|
+
filePath?: string;
|
|
20
|
+
range?: LineRange;
|
|
21
|
+
symbol?: string;
|
|
22
|
+
outcome: EvidenceOutcome;
|
|
23
|
+
fingerprint: string;
|
|
24
|
+
}
|
|
25
|
+
export interface EvidenceRequirement {
|
|
26
|
+
id: string;
|
|
27
|
+
description: string;
|
|
28
|
+
acceptedKinds: EvidenceKind[];
|
|
29
|
+
targetFiles?: string[];
|
|
30
|
+
requiredTools?: AgentScanActionType[];
|
|
31
|
+
minimumCount: number;
|
|
32
|
+
acceptsNegative?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface ProgressDelta {
|
|
35
|
+
newRanges: LineRange[];
|
|
36
|
+
newSymbols: string[];
|
|
37
|
+
newReferences: number;
|
|
38
|
+
newFlows: number;
|
|
39
|
+
completedRequirementIds: string[];
|
|
40
|
+
meaningful: boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare class EvidenceLedger {
|
|
43
|
+
private evidence;
|
|
44
|
+
private requirementStates;
|
|
45
|
+
private symbols;
|
|
46
|
+
private flows;
|
|
47
|
+
addRequirement(requirement: EvidenceRequirement): void;
|
|
48
|
+
addRequirements(requirements: EvidenceRequirement[]): void;
|
|
49
|
+
recordEvidence(input: Omit<EvidenceRef, 'id' | 'fingerprint'>): {
|
|
50
|
+
ref: EvidenceRef;
|
|
51
|
+
delta: ProgressDelta;
|
|
52
|
+
};
|
|
53
|
+
isRequirementSatisfied(requirementId: string): boolean;
|
|
54
|
+
getUnsatisfiedRequirements(): EvidenceRequirement[];
|
|
55
|
+
getAllEvidence(): EvidenceRef[];
|
|
56
|
+
getEvidenceByKind(kind: EvidenceKind): EvidenceRef[];
|
|
57
|
+
getEvidenceForFile(filePath: string): EvidenceRef[];
|
|
58
|
+
snapshot(): {
|
|
59
|
+
evidenceCount: number;
|
|
60
|
+
requirementCount: number;
|
|
61
|
+
satisfiedCount: number;
|
|
62
|
+
symbolCount: number;
|
|
63
|
+
flowCount: number;
|
|
64
|
+
};
|
|
65
|
+
private emptyDelta;
|
|
66
|
+
private pathMatches;
|
|
67
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Evidence ledger — tracks why a task or candidate is complete instead of
|
|
4
|
+
* marking checklist steps complete because a tool was merely called.
|
|
5
|
+
*
|
|
6
|
+
* A tool invocation alone does not satisfy an evidence requirement.
|
|
7
|
+
* The ledger records structured evidence with fingerprints and links it
|
|
8
|
+
* to requirements. Progress is derived from newly accepted evidence,
|
|
9
|
+
* not set manually.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.EvidenceLedger = void 0;
|
|
46
|
+
const crypto = __importStar(require("crypto"));
|
|
47
|
+
function fingerprintEvidence(input) {
|
|
48
|
+
return crypto
|
|
49
|
+
.createHash('sha256')
|
|
50
|
+
.update(JSON.stringify(input))
|
|
51
|
+
.digest('hex')
|
|
52
|
+
.slice(0, 16);
|
|
53
|
+
}
|
|
54
|
+
class EvidenceLedger {
|
|
55
|
+
evidence = new Map();
|
|
56
|
+
requirementStates = new Map();
|
|
57
|
+
symbols = new Set();
|
|
58
|
+
flows = 0;
|
|
59
|
+
addRequirement(requirement) {
|
|
60
|
+
if (!this.requirementStates.has(requirement.id)) {
|
|
61
|
+
this.requirementStates.set(requirement.id, { requirement, count: 0 });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
addRequirements(requirements) {
|
|
65
|
+
for (const req of requirements) {
|
|
66
|
+
this.addRequirement(req);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
recordEvidence(input) {
|
|
70
|
+
const fingerprint = fingerprintEvidence({
|
|
71
|
+
kind: input.kind,
|
|
72
|
+
tool: input.tool,
|
|
73
|
+
filePath: input.filePath,
|
|
74
|
+
range: input.range,
|
|
75
|
+
symbol: input.symbol,
|
|
76
|
+
outcome: input.outcome,
|
|
77
|
+
});
|
|
78
|
+
// Skip duplicate evidence (same fingerprint)
|
|
79
|
+
if (this.evidence.has(fingerprint)) {
|
|
80
|
+
return {
|
|
81
|
+
ref: this.evidence.get(fingerprint),
|
|
82
|
+
delta: this.emptyDelta(),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const ref = {
|
|
86
|
+
...input,
|
|
87
|
+
id: fingerprint,
|
|
88
|
+
fingerprint,
|
|
89
|
+
};
|
|
90
|
+
this.evidence.set(fingerprint, ref);
|
|
91
|
+
// Track symbols and flows
|
|
92
|
+
const newSymbols = [];
|
|
93
|
+
if (input.symbol && !this.symbols.has(input.symbol)) {
|
|
94
|
+
this.symbols.add(input.symbol);
|
|
95
|
+
newSymbols.push(input.symbol);
|
|
96
|
+
}
|
|
97
|
+
const newFlows = input.kind === 'cross-file-flow' ? 1 : 0;
|
|
98
|
+
this.flows += newFlows;
|
|
99
|
+
// Check if this evidence satisfies any requirements
|
|
100
|
+
const completedRequirementIds = [];
|
|
101
|
+
for (const [reqId, state] of this.requirementStates) {
|
|
102
|
+
if (state.count >= state.requirement.minimumCount)
|
|
103
|
+
continue;
|
|
104
|
+
const req = state.requirement;
|
|
105
|
+
if (!req.acceptedKinds.includes(input.kind))
|
|
106
|
+
continue;
|
|
107
|
+
if (req.targetFiles && input.filePath &&
|
|
108
|
+
!req.targetFiles.some(f => this.pathMatches(f, input.filePath)))
|
|
109
|
+
continue;
|
|
110
|
+
if (req.requiredTools && !req.requiredTools.includes(input.tool))
|
|
111
|
+
continue;
|
|
112
|
+
if (input.outcome === 'blocked' || input.outcome === 'error')
|
|
113
|
+
continue;
|
|
114
|
+
if (input.outcome === 'empty' && !req.acceptsNegative)
|
|
115
|
+
continue;
|
|
116
|
+
state.count++;
|
|
117
|
+
if (state.count >= req.minimumCount) {
|
|
118
|
+
completedRequirementIds.push(reqId);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const meaningful = completedRequirementIds.length > 0 ||
|
|
122
|
+
newSymbols.length > 0 ||
|
|
123
|
+
newFlows > 0 ||
|
|
124
|
+
(input.kind === 'source-range' && input.outcome === 'positive');
|
|
125
|
+
return {
|
|
126
|
+
ref,
|
|
127
|
+
delta: {
|
|
128
|
+
newRanges: input.range && input.kind === 'source-range' ? [input.range] : [],
|
|
129
|
+
newSymbols,
|
|
130
|
+
newReferences: input.kind === 'symbol-reference' ? 1 : 0,
|
|
131
|
+
newFlows,
|
|
132
|
+
completedRequirementIds,
|
|
133
|
+
meaningful,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
isRequirementSatisfied(requirementId) {
|
|
138
|
+
const state = this.requirementStates.get(requirementId);
|
|
139
|
+
if (!state)
|
|
140
|
+
return false;
|
|
141
|
+
return state.count >= state.requirement.minimumCount;
|
|
142
|
+
}
|
|
143
|
+
getUnsatisfiedRequirements() {
|
|
144
|
+
const unsatisfied = [];
|
|
145
|
+
for (const [_, state] of this.requirementStates) {
|
|
146
|
+
if (state.count < state.requirement.minimumCount) {
|
|
147
|
+
unsatisfied.push(state.requirement);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return unsatisfied;
|
|
151
|
+
}
|
|
152
|
+
getAllEvidence() {
|
|
153
|
+
return [...this.evidence.values()];
|
|
154
|
+
}
|
|
155
|
+
getEvidenceByKind(kind) {
|
|
156
|
+
return [...this.evidence.values()].filter(e => e.kind === kind);
|
|
157
|
+
}
|
|
158
|
+
getEvidenceForFile(filePath) {
|
|
159
|
+
return [...this.evidence.values()].filter(e => e.filePath && this.pathMatches(filePath, e.filePath));
|
|
160
|
+
}
|
|
161
|
+
snapshot() {
|
|
162
|
+
let satisfied = 0;
|
|
163
|
+
for (const [_, state] of this.requirementStates) {
|
|
164
|
+
if (state.count >= state.requirement.minimumCount)
|
|
165
|
+
satisfied++;
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
evidenceCount: this.evidence.size,
|
|
169
|
+
requirementCount: this.requirementStates.size,
|
|
170
|
+
satisfiedCount: satisfied,
|
|
171
|
+
symbolCount: this.symbols.size,
|
|
172
|
+
flowCount: this.flows,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
emptyDelta() {
|
|
176
|
+
return {
|
|
177
|
+
newRanges: [],
|
|
178
|
+
newSymbols: [],
|
|
179
|
+
newReferences: 0,
|
|
180
|
+
newFlows: 0,
|
|
181
|
+
completedRequirementIds: [],
|
|
182
|
+
meaningful: false,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
pathMatches(pattern, path) {
|
|
186
|
+
const np = pattern.replace(/\\/g, '/').toLowerCase();
|
|
187
|
+
const np2 = path.replace(/\\/g, '/').toLowerCase();
|
|
188
|
+
return np === np2 || np2.includes(np) || np.includes(np2);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
exports.EvidenceLedger = EvidenceLedger;
|
|
192
|
+
//# sourceMappingURL=evidenceLedger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidenceLedger.js","sourceRoot":"","sources":["../../src/attack/evidenceLedger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hard finish gate — rejects premature finish attempts and continues the
|
|
3
|
+
* investigation while executable work and budget remain.
|
|
4
|
+
*
|
|
5
|
+
* The finish gate is MCP-owned. When the model proposes `finish`, the gate
|
|
6
|
+
* evaluates whether the investigation is actually complete:
|
|
7
|
+
*
|
|
8
|
+
* - Required checklist steps must be complete
|
|
9
|
+
* - Architecture-risk tasks must be resolved, refuted, or blocked
|
|
10
|
+
* - All candidates must be terminal
|
|
11
|
+
* - Security-sensitive handlers must be reviewed
|
|
12
|
+
* - No executable work items remain (when budget is available)
|
|
13
|
+
*
|
|
14
|
+
* If any of these conditions fail and budget remains, finish is REJECTED
|
|
15
|
+
* and the gate returns a recovery action to continue the investigation.
|
|
16
|
+
*
|
|
17
|
+
* If budget is exhausted, finish is accepted as "forced-incomplete" with
|
|
18
|
+
* coverage gaps for every unresolved item.
|
|
19
|
+
*/
|
|
20
|
+
import type { AgentScanAction, AgentScanFinishAction } from './agentScanProtocol';
|
|
21
|
+
import type { ScanRunState } from './scanState';
|
|
22
|
+
import type { EvidenceLedger } from './evidenceLedger';
|
|
23
|
+
import type { WorkItemQueue } from './workItem';
|
|
24
|
+
import type { HandlerInventory } from '../project-map/handlerInventory';
|
|
25
|
+
import type { CandidateStore } from './candidateStore';
|
|
26
|
+
import type { InvestigationState } from './investigationState';
|
|
27
|
+
import type { ScheduleDecision } from './scanScheduler';
|
|
28
|
+
export type FinishGateMode = 'complete' | 'continue' | 'forced-incomplete';
|
|
29
|
+
export interface FinishGateReason {
|
|
30
|
+
code: string;
|
|
31
|
+
description: string;
|
|
32
|
+
}
|
|
33
|
+
export interface FinishGateResult {
|
|
34
|
+
accepted: boolean;
|
|
35
|
+
mode: FinishGateMode;
|
|
36
|
+
reasons: FinishGateReason[];
|
|
37
|
+
recoveryAction?: AgentScanAction;
|
|
38
|
+
normalizedFinish?: AgentScanFinishAction;
|
|
39
|
+
coverageGaps?: {
|
|
40
|
+
title: string;
|
|
41
|
+
detail: string;
|
|
42
|
+
file: string;
|
|
43
|
+
requiredEvidence: string[];
|
|
44
|
+
suggestedNextAction: string;
|
|
45
|
+
priority: 'high' | 'medium' | 'low';
|
|
46
|
+
}[];
|
|
47
|
+
}
|
|
48
|
+
export interface FinishGateInput {
|
|
49
|
+
proposal: AgentScanFinishAction;
|
|
50
|
+
state: ScanRunState;
|
|
51
|
+
evidence: EvidenceLedger;
|
|
52
|
+
workItems: WorkItemQueue;
|
|
53
|
+
handlers: HandlerInventory;
|
|
54
|
+
candidates: CandidateStore;
|
|
55
|
+
investigation: InvestigationState;
|
|
56
|
+
scheduler: ScheduleDecision;
|
|
57
|
+
target: {
|
|
58
|
+
filePath: string;
|
|
59
|
+
fileContent?: string;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export declare function evaluateFinishGate(input: FinishGateInput): FinishGateResult;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Hard finish gate — rejects premature finish attempts and continues the
|
|
4
|
+
* investigation while executable work and budget remain.
|
|
5
|
+
*
|
|
6
|
+
* The finish gate is MCP-owned. When the model proposes `finish`, the gate
|
|
7
|
+
* evaluates whether the investigation is actually complete:
|
|
8
|
+
*
|
|
9
|
+
* - Required checklist steps must be complete
|
|
10
|
+
* - Architecture-risk tasks must be resolved, refuted, or blocked
|
|
11
|
+
* - All candidates must be terminal
|
|
12
|
+
* - Security-sensitive handlers must be reviewed
|
|
13
|
+
* - No executable work items remain (when budget is available)
|
|
14
|
+
*
|
|
15
|
+
* If any of these conditions fail and budget remains, finish is REJECTED
|
|
16
|
+
* and the gate returns a recovery action to continue the investigation.
|
|
17
|
+
*
|
|
18
|
+
* If budget is exhausted, finish is accepted as "forced-incomplete" with
|
|
19
|
+
* coverage gaps for every unresolved item.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.evaluateFinishGate = evaluateFinishGate;
|
|
23
|
+
function evaluateFinishGate(input) {
|
|
24
|
+
const { proposal, state, evidence, workItems, handlers, candidates, investigation, scheduler, target } = input;
|
|
25
|
+
const reasons = [];
|
|
26
|
+
const coverageGaps = [];
|
|
27
|
+
const hasBudget = state.budget.stepsRemaining > 0 &&
|
|
28
|
+
state.budget.costSpentUsd < state.budget.costCapUsd;
|
|
29
|
+
const hasWallClock = Date.now() - state.budget.startedAt < state.budget.wallClockMs;
|
|
30
|
+
// Check 1: Incomplete investigation steps
|
|
31
|
+
const incompleteSteps = investigation.getIncompleteSteps();
|
|
32
|
+
if (incompleteSteps.length > 0) {
|
|
33
|
+
for (const step of incompleteSteps) {
|
|
34
|
+
reasons.push({
|
|
35
|
+
code: 'incomplete-checklist',
|
|
36
|
+
description: `Required investigation step not completed: ${step}`,
|
|
37
|
+
});
|
|
38
|
+
coverageGaps.push({
|
|
39
|
+
title: `Investigation step not completed: ${step}`,
|
|
40
|
+
detail: `The agent finished without completing this required investigation step: ${step}. This means the investigation was incomplete and vulnerabilities may have been missed.`,
|
|
41
|
+
file: target.filePath,
|
|
42
|
+
requiredEvidence: [`Complete the ${step} step before concluding no vulnerabilities exist`],
|
|
43
|
+
suggestedNextAction: step === 'config-inspection' ? 'read_config'
|
|
44
|
+
: step === 'policy-check' ? 'check_policy'
|
|
45
|
+
: step === 'cross-file-flow' ? 'trace_flow_cross_file'
|
|
46
|
+
: step === 'route-discovery' ? 'get_endpoints'
|
|
47
|
+
: step === 'auth-symbol-search' ? 'search_code'
|
|
48
|
+
: 'continue investigation',
|
|
49
|
+
priority: 'high',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Check 2: Unresolved architecture-risk tasks
|
|
54
|
+
const unresolvedTasks = investigation.getUnresolvedTasks();
|
|
55
|
+
if (unresolvedTasks.length > 0) {
|
|
56
|
+
for (const task of unresolvedTasks) {
|
|
57
|
+
reasons.push({
|
|
58
|
+
code: 'unresolved-task',
|
|
59
|
+
description: `Architecture risk task unresolved: ${task.claim}`,
|
|
60
|
+
});
|
|
61
|
+
coverageGaps.push({
|
|
62
|
+
title: `Architecture risk unresolved: ${task.claim}`,
|
|
63
|
+
detail: `This architecture-risk investigation task was not resolved: ${task.claim}. Required evidence: ${task.requiredEvidence.join('; ')}.`,
|
|
64
|
+
file: task.targetFiles[0] || target.filePath,
|
|
65
|
+
requiredEvidence: task.requiredEvidence,
|
|
66
|
+
suggestedNextAction: task.requiredTools[0] || 'continue investigation',
|
|
67
|
+
priority: 'high',
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Check 3: Non-terminal candidates — unsupported candidates block finish
|
|
72
|
+
// when budget remains. When budget is exhausted, they become coverage gaps.
|
|
73
|
+
if (!candidates.allReadyForJuror()) {
|
|
74
|
+
const underInvestigation = candidates.getUnderInvestigation();
|
|
75
|
+
for (const candidate of underInvestigation) {
|
|
76
|
+
const missingDims = candidate.requiredProofDimensions?.filter(d => !candidate.satisfiedDimensions?.includes(d)) || [];
|
|
77
|
+
const dimInfo = missingDims.length > 0
|
|
78
|
+
? ` (missing proof dimensions: ${missingDims.join(', ')})`
|
|
79
|
+
: ` (${candidate.evidenceRefs.length} evidence ref(s))`;
|
|
80
|
+
reasons.push({
|
|
81
|
+
code: 'non-terminal-candidate',
|
|
82
|
+
description: `Candidate needs more evidence: ${candidate.claim} (status: ${candidate.status}${dimInfo})`,
|
|
83
|
+
});
|
|
84
|
+
coverageGaps.push({
|
|
85
|
+
title: `Candidate needs more evidence: ${candidate.claim}`,
|
|
86
|
+
detail: `This vulnerability candidate at ${candidate.locations.map(l => `${l.filePath}:${l.line}`).join(', ')} has status "${candidate.status}" with ${candidate.evidenceRefs.length} evidence reference(s). Missing proof dimensions: ${missingDims.join(', ') || 'none'}. Run trace_flow, check_guard, or check_policy on the finding location to gather more evidence before finishing.`,
|
|
87
|
+
file: candidate.locations[0]?.filePath || target.filePath,
|
|
88
|
+
requiredEvidence: candidate.requiredEvidence.map(e => `${e.description} (tools: ${(e.requiredTools || []).join(', ')})`),
|
|
89
|
+
suggestedNextAction: (candidate.requiredEvidence[0]?.requiredTools || ['trace_flow_cross_file'])[0],
|
|
90
|
+
priority: candidate.severity === 'high' || candidate.severity === 'critical' ? 'high' : 'medium',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Check 3b: Unsatisfied evidence-ledger requirements
|
|
95
|
+
const unsatisfiedReqs = evidence.getUnsatisfiedRequirements();
|
|
96
|
+
if (unsatisfiedReqs.length > 0) {
|
|
97
|
+
for (const req of unsatisfiedReqs) {
|
|
98
|
+
reasons.push({
|
|
99
|
+
code: 'unsatisfied-evidence-requirement',
|
|
100
|
+
description: `Evidence requirement not satisfied: ${req.description}`,
|
|
101
|
+
});
|
|
102
|
+
coverageGaps.push({
|
|
103
|
+
title: `Evidence requirement not satisfied: ${req.description}`,
|
|
104
|
+
detail: `The evidence ledger requirement "${req.description}" was not satisfied. Required tools: ${(req.requiredTools || []).join(', ')}. Accepted kinds: ${req.acceptedKinds.join(', ')}.`,
|
|
105
|
+
file: req.targetFiles?.[0] || target.filePath,
|
|
106
|
+
requiredEvidence: [req.description],
|
|
107
|
+
suggestedNextAction: req.requiredTools?.[0] || 'continue investigation',
|
|
108
|
+
priority: 'medium',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Check 4: Unreviewed security-sensitive handlers
|
|
113
|
+
const unreviewedSensitive = handlers.getUnreviewedSensitiveCount();
|
|
114
|
+
if (unreviewedSensitive > 0) {
|
|
115
|
+
reasons.push({
|
|
116
|
+
code: 'unreviewed-handlers',
|
|
117
|
+
description: `${unreviewedSensitive} security-sensitive handler(s) unreviewed`,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// Check 5: Executable work items remain (only when budget is available)
|
|
121
|
+
const executableWork = workItems.getExecutable();
|
|
122
|
+
if (executableWork.length > 0 && hasBudget && hasWallClock) {
|
|
123
|
+
reasons.push({
|
|
124
|
+
code: 'executable-work-remaining',
|
|
125
|
+
description: `${executableWork.length} executable work item(s) remain`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
// Check 6: Scheduler has a deterministic action (only when checklist incomplete)
|
|
129
|
+
if (incompleteSteps.length > 0 && scheduler.kind === 'deterministic-action' && hasBudget && hasWallClock) {
|
|
130
|
+
reasons.push({
|
|
131
|
+
code: 'scheduler-has-action',
|
|
132
|
+
description: `Scheduler has a deterministic action available: ${scheduler.reason}`,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
// Check 7: High-priority unread ranges — security-relevant code that
|
|
136
|
+
// was never read. This prevents finishing while authentication,
|
|
137
|
+
// authorization, or command-execution code remains uninspected.
|
|
138
|
+
if (hasBudget && hasWallClock && target.fileContent) {
|
|
139
|
+
const uncoveredRanges = investigation.getUncoveredRanges(target.filePath);
|
|
140
|
+
if (uncoveredRanges.length > 0) {
|
|
141
|
+
const lines = target.fileContent.split('\n');
|
|
142
|
+
const HIGH_PRIORITY_KEYWORDS = [
|
|
143
|
+
'authenticat', 'authorize', 'authorization', 'token', 'session',
|
|
144
|
+
'credential', 'password', 'execfile', 'exec(', 'spawn(',
|
|
145
|
+
'child_process', 'writefile', 'permission', 'ownership',
|
|
146
|
+
'bootstrap', 'pairing', 'sql', 'queryraw', 'eval(',
|
|
147
|
+
];
|
|
148
|
+
for (const range of uncoveredRanges) {
|
|
149
|
+
const rangeLines = lines.slice(Math.max(0, range.start - 1), Math.min(lines.length, range.end));
|
|
150
|
+
const rangeText = rangeLines.join('\n').toLowerCase();
|
|
151
|
+
const hasHighPriority = HIGH_PRIORITY_KEYWORDS.some(kw => rangeText.includes(kw));
|
|
152
|
+
if (hasHighPriority) {
|
|
153
|
+
reasons.push({
|
|
154
|
+
code: 'high-priority-unread-range',
|
|
155
|
+
description: `Unread range lines ${range.start}-${range.end} contains security-relevant code (auth, exec, token, etc.)`,
|
|
156
|
+
});
|
|
157
|
+
coverageGaps.push({
|
|
158
|
+
title: `Unread high-priority range: lines ${range.start}-${range.end} of ${target.filePath}`,
|
|
159
|
+
detail: `This unread range contains security-relevant code (authentication, authorization, command execution, or token handling). Vulnerabilities in this range were not checked.`,
|
|
160
|
+
file: target.filePath,
|
|
161
|
+
requiredEvidence: [`Read lines ${range.start}-${range.end} and analyze for vulnerabilities`],
|
|
162
|
+
suggestedNextAction: 'read_file',
|
|
163
|
+
priority: 'high',
|
|
164
|
+
});
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Decision:
|
|
171
|
+
// - If no reasons → accept as complete
|
|
172
|
+
// - If reasons exist but no budget/wall-clock → accept as forced-incomplete
|
|
173
|
+
// - If reasons exist and budget remains → reject and continue
|
|
174
|
+
if (reasons.length === 0) {
|
|
175
|
+
return {
|
|
176
|
+
accepted: true,
|
|
177
|
+
mode: 'complete',
|
|
178
|
+
reasons: [],
|
|
179
|
+
normalizedFinish: proposal,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
// Check if we can continue (budget + wall clock available)
|
|
183
|
+
const canContinue = hasBudget && hasWallClock && !isScanTerminal(state);
|
|
184
|
+
if (!canContinue) {
|
|
185
|
+
// Forced-incomplete: budget or wall clock exhausted
|
|
186
|
+
return {
|
|
187
|
+
accepted: true,
|
|
188
|
+
mode: 'forced-incomplete',
|
|
189
|
+
reasons,
|
|
190
|
+
coverageGaps,
|
|
191
|
+
normalizedFinish: proposal,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
// Reject finish — continue investigation
|
|
195
|
+
const recoveryAction = scheduler.kind === 'deterministic-action' && scheduler.action
|
|
196
|
+
? scheduler.action
|
|
197
|
+
: undefined;
|
|
198
|
+
return {
|
|
199
|
+
accepted: false,
|
|
200
|
+
mode: 'continue',
|
|
201
|
+
reasons,
|
|
202
|
+
recoveryAction,
|
|
203
|
+
coverageGaps,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function isScanTerminal(state) {
|
|
207
|
+
return state.phase === 'completed' || state.phase === 'terminated';
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=finishGate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finishGate.js","sourceRoot":"","sources":["../../src/attack/finishGate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed-code merge helper — reconstructs the full file by replacing the
|
|
3
|
+
* declared line range with the proposed fixed code.
|
|
4
|
+
*
|
|
5
|
+
* The fixer API returns `fixed_code` + `replace_range` (start_line, end_line).
|
|
6
|
+
* Before fix verification, we need the FULL file with the fix applied so the
|
|
7
|
+
* verify subagent can test whether the original exploit still reproduces.
|
|
8
|
+
*
|
|
9
|
+
* Rules:
|
|
10
|
+
* - Lines are 1-indexed, end_line is inclusive.
|
|
11
|
+
* - Lines before start_line and after end_line are preserved.
|
|
12
|
+
* - Malformed ranges (start > end, start < 1, end > total lines) are rejected.
|
|
13
|
+
* - The merged code is kept in memory only — never written to the workspace.
|
|
14
|
+
*/
|
|
15
|
+
export interface ReplaceRange {
|
|
16
|
+
start_line: number;
|
|
17
|
+
end_line: number;
|
|
18
|
+
}
|
|
19
|
+
export interface MergeResult {
|
|
20
|
+
ok: true;
|
|
21
|
+
mergedCode: string;
|
|
22
|
+
}
|
|
23
|
+
export interface MergeError {
|
|
24
|
+
ok: false;
|
|
25
|
+
error: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function mergeFixedCode(originalCode: string, fixedCode: string, replaceRange: ReplaceRange): MergeResult | MergeError;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Fixed-code merge helper — reconstructs the full file by replacing the
|
|
4
|
+
* declared line range with the proposed fixed code.
|
|
5
|
+
*
|
|
6
|
+
* The fixer API returns `fixed_code` + `replace_range` (start_line, end_line).
|
|
7
|
+
* Before fix verification, we need the FULL file with the fix applied so the
|
|
8
|
+
* verify subagent can test whether the original exploit still reproduces.
|
|
9
|
+
*
|
|
10
|
+
* Rules:
|
|
11
|
+
* - Lines are 1-indexed, end_line is inclusive.
|
|
12
|
+
* - Lines before start_line and after end_line are preserved.
|
|
13
|
+
* - Malformed ranges (start > end, start < 1, end > total lines) are rejected.
|
|
14
|
+
* - The merged code is kept in memory only — never written to the workspace.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.mergeFixedCode = mergeFixedCode;
|
|
18
|
+
function mergeFixedCode(originalCode, fixedCode, replaceRange) {
|
|
19
|
+
const { start_line, end_line } = replaceRange;
|
|
20
|
+
if (!Number.isInteger(start_line) || !Number.isInteger(end_line)) {
|
|
21
|
+
return { ok: false, error: `replace_range lines must be integers (got start=${start_line}, end=${end_line})` };
|
|
22
|
+
}
|
|
23
|
+
if (start_line < 1) {
|
|
24
|
+
return { ok: false, error: `replace_range start_line must be >= 1 (got ${start_line})` };
|
|
25
|
+
}
|
|
26
|
+
if (end_line < start_line) {
|
|
27
|
+
return { ok: false, error: `replace_range end_line (${end_line}) must be >= start_line (${start_line})` };
|
|
28
|
+
}
|
|
29
|
+
const originalLines = originalCode.split('\n');
|
|
30
|
+
if (end_line > originalLines.length) {
|
|
31
|
+
return { ok: false, error: `replace_range end_line (${end_line}) exceeds file length (${originalLines.length} lines)` };
|
|
32
|
+
}
|
|
33
|
+
// Lines before the replacement (1-indexed → 0-indexed slice).
|
|
34
|
+
const before = originalLines.slice(0, start_line - 1);
|
|
35
|
+
// Lines after the replacement (end_line is inclusive → slice from end_line).
|
|
36
|
+
const after = originalLines.slice(end_line);
|
|
37
|
+
// The fixed code may be multi-line — split it and join with the preserved lines.
|
|
38
|
+
const fixedLines = fixedCode.length > 0 ? fixedCode.split('\n') : [];
|
|
39
|
+
const mergedLines = [...before, ...fixedLines, ...after];
|
|
40
|
+
return { ok: true, mergedCode: mergedLines.join('\n') };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=fixCodeMerge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixCodeMerge.js","sourceRoot":"","sources":["../../src/attack/fixCodeMerge.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;AAiBH,wCAgCC;AAhCD,SAAgB,cAAc,CAC1B,YAAoB,EACpB,SAAiB,EACjB,YAA0B;IAE1B,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC;IAE9C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mDAAmD,UAAU,SAAS,QAAQ,GAAG,EAAE,CAAC;IACnH,CAAC;IACD,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,8CAA8C,UAAU,GAAG,EAAE,CAAC;IAC7F,CAAC;IACD,IAAI,QAAQ,GAAG,UAAU,EAAE,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B,QAAQ,4BAA4B,UAAU,GAAG,EAAE,CAAC;IAC9G,CAAC;IAED,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,QAAQ,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B,QAAQ,0BAA0B,aAAa,CAAC,MAAM,SAAS,EAAE,CAAC;IAC5H,CAAC;IAED,8DAA8D;IAC9D,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;IACtD,6EAA6E;IAC7E,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE5C,iFAAiF;IACjF,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAErE,MAAM,WAAW,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,UAAU,EAAE,GAAG,KAAK,CAAC,CAAC;IACzD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC5D,CAAC"}
|