diff --git a/.gitignore b/.gitignore index ecd4c4b9..32528369 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,32 @@ +# Dependencies node_modules/ +.venv/ dist/ +build/ + +# Environment .env -Risk/Model/ -.venv -my_vector_db -.env -__pycache__/ \ No newline at end of file + +# IDEs +.idea/ +.vscode/ +.DS_Store + +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +.pytest_cache/ +.coverage +htmlcov/ +.ipynb_checkpoints/ + +# Vector Databases & Data +my_vector_db/ +commit_vector_db/ +commit_vector_db_nomic/ +*.sqlite3 + +# Models +Risk/Model/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index edc55ceb..c74e6445 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "snyk.advanced.autoSelectOrganization": true + "snyk.advanced.autoSelectOrganization": true, + "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python" } \ No newline at end of file diff --git a/Backend/API/obj/Codience.API.csproj.nuget.dgspec.json b/Backend/API/obj/Codience.API.csproj.nuget.dgspec.json new file mode 100644 index 00000000..952970b8 --- /dev/null +++ b/Backend/API/obj/Codience.API.csproj.nuget.dgspec.json @@ -0,0 +1,566 @@ +{ + "format": 1, + "restore": { + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/Codience.API.csproj": {} + }, + "projects": { + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/Codience.API.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/Codience.API.csproj", + "projectName": "Codience.API", + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/Codience.API.csproj", + "packagesPath": "/Users/rebuy/.nuget/packages/", + "outputPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/rebuy/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": { + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Persistence/Infrastructure.Persistence.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Persistence/Infrastructure.Persistence.csproj" + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Presentation/Infrastructure.Presentation.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Presentation/Infrastructure.Presentation.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "dependencies": { + "Microsoft.AspNetCore.OpenApi": { + "target": "Package", + "version": "[9.0.2, )" + }, + "Microsoft.EntityFrameworkCore.Tools": { + "include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive", + "suppressParent": "All", + "target": "Package", + "version": "[9.0.9, )" + }, + "Microsoft.Extensions.DependencyInjection": { + "target": "Package", + "version": "[9.0.9, )" + }, + "Swashbuckle.AspNetCore.SwaggerGen": { + "target": "Package", + "version": "[9.0.5, )" + }, + "Swashbuckle.AspNetCore.SwaggerUI": { + "target": "Package", + "version": "[9.0.5, )" + }, + "System.IdentityModel.Tokens.Jwt": { + "target": "Package", + "version": "[8.17.0, )" + }, + "dotenv.net": { + "target": "Package", + "version": "[4.0.2, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/Users/rebuy/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Abstraction/Core.Abstraction.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Abstraction/Core.Abstraction.csproj", + "projectName": "Core.Abstraction", + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Abstraction/Core.Abstraction.csproj", + "packagesPath": "/Users/rebuy/.nuget/packages/", + "outputPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Abstraction/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/rebuy/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": { + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj" + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Share/Share.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Share/Share.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/Users/rebuy/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj", + "projectName": "Core.Domain", + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj", + "packagesPath": "/Users/rebuy/.nuget/packages/", + "outputPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/rebuy/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/Users/rebuy/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Services/Core.Services.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Services/Core.Services.csproj", + "projectName": "Core.Services", + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Services/Core.Services.csproj", + "packagesPath": "/Users/rebuy/.nuget/packages/", + "outputPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Services/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/rebuy/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": { + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Abstraction/Core.Abstraction.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Abstraction/Core.Abstraction.csproj" + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "dependencies": { + "CsvHelper": { + "target": "Package", + "version": "[33.1.0, )" + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "target": "Package", + "version": "[9.0.9, )" + }, + "Microsoft.Extensions.Http": { + "target": "Package", + "version": "[9.0.5, )" + }, + "Newtonsoft.Json": { + "target": "Package", + "version": "[13.0.4, )" + }, + "Polly": { + "target": "Package", + "version": "[8.6.4, )" + }, + "System.IdentityModel.Tokens.Jwt": { + "target": "Package", + "version": "[8.17.0, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/Users/rebuy/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Persistence/Infrastructure.Persistence.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Persistence/Infrastructure.Persistence.csproj", + "projectName": "Infrastructure.Persistence", + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Persistence/Infrastructure.Persistence.csproj", + "packagesPath": "/Users/rebuy/.nuget/packages/", + "outputPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Persistence/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/rebuy/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": { + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Domain/Core.Domain.csproj" + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Services/Core.Services.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Services/Core.Services.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "dependencies": { + "CsvHelper": { + "target": "Package", + "version": "[33.1.0, )" + }, + "Microsoft.EntityFrameworkCore": { + "target": "Package", + "version": "[9.0.9, )" + }, + "Microsoft.EntityFrameworkCore.Design": { + "suppressParent": "All", + "target": "Package", + "version": "[9.0.9, )" + }, + "Microsoft.EntityFrameworkCore.Tools": { + "include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive", + "suppressParent": "All", + "target": "Package", + "version": "[9.0.9, )" + }, + "Microsoft.Extensions.Http": { + "target": "Package", + "version": "[9.0.5, )" + }, + "Npgsql.EntityFrameworkCore.PostgreSQL": { + "target": "Package", + "version": "[9.0.4, )" + }, + "Polly": { + "target": "Package", + "version": "[8.6.4, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/Users/rebuy/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Presentation/Infrastructure.Presentation.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Presentation/Infrastructure.Presentation.csproj", + "projectName": "Infrastructure.Presentation", + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Presentation/Infrastructure.Presentation.csproj", + "packagesPath": "/Users/rebuy/.nuget/packages/", + "outputPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Presentation/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/rebuy/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": { + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Abstraction/Core.Abstraction.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Abstraction/Core.Abstraction.csproj" + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Services/Core.Services.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Core/Services/Core.Services.csproj" + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Share/Share.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Share/Share.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "dependencies": { + "Microsoft.Extensions.Http": { + "target": "Package", + "version": "[9.0.5, )" + }, + "Polly": { + "target": "Package", + "version": "[8.6.4, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/Users/rebuy/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Share/Share.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Share/Share.csproj", + "projectName": "Share", + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Share/Share.csproj", + "packagesPath": "/Users/rebuy/.nuget/packages/", + "outputPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Share/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/rebuy/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/Users/rebuy/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + } + } +} \ No newline at end of file diff --git a/Backend/API/obj/Codience.API.csproj.nuget.g.props b/Backend/API/obj/Codience.API.csproj.nuget.g.props new file mode 100644 index 00000000..88e62815 --- /dev/null +++ b/Backend/API/obj/Codience.API.csproj.nuget.g.props @@ -0,0 +1,24 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + /Users/rebuy/.nuget/packages/ + /Users/rebuy/.nuget/packages/ + PackageReference + 6.14.0 + + + + + + + + + + + /Users/rebuy/.nuget/packages/microsoft.codeanalysis.analyzers/3.3.4 + /Users/rebuy/.nuget/packages/microsoft.entityframeworkcore.tools/9.0.9 + + \ No newline at end of file diff --git a/Backend/API/obj/Codience.API.csproj.nuget.g.targets b/Backend/API/obj/Codience.API.csproj.nuget.g.targets new file mode 100644 index 00000000..cace18d5 --- /dev/null +++ b/Backend/API/obj/Codience.API.csproj.nuget.g.targets @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Backend/API/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs b/Backend/API/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs new file mode 100644 index 00000000..feda5e9f --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/.NETCoreApp,Version=v9.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v9.0", FrameworkDisplayName = ".NET 9.0")] diff --git a/Backend/API/obj/Debug/net9.0/Codience.3B30C0E2.Up2Date b/Backend/API/obj/Debug/net9.0/Codience.3B30C0E2.Up2Date new file mode 100644 index 00000000..e69de29b diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.AssemblyInfo.cs b/Backend/API/obj/Debug/net9.0/Codience.API.AssemblyInfo.cs new file mode 100644 index 00000000..3c0cb558 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.AssemblyInfo.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("Codience.API")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+32ab38f54d89655cd6eec400dbc4078ef42dcaa3")] +[assembly: System.Reflection.AssemblyProductAttribute("Codience.API")] +[assembly: System.Reflection.AssemblyTitleAttribute("Codience.API")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.AssemblyInfoInputs.cache b/Backend/API/obj/Debug/net9.0/Codience.API.AssemblyInfoInputs.cache new file mode 100644 index 00000000..b324b46a --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +c51cb0ff742312f7b9a4e6611025181006f829507bdf248858fec202d276e9dc diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.GeneratedMSBuildEditorConfig.editorconfig b/Backend/API/obj/Debug/net9.0/Codience.API.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 00000000..d17388c0 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,29 @@ +is_global = true +build_property.TargetFramework = net9.0 +build_property.TargetFramework = net9.0 +build_property.TargetPlatformMinVersion = +build_property.TargetPlatformMinVersion = +build_property.UsingMicrosoftNETSdkWeb = true +build_property.UsingMicrosoftNETSdkWeb = true +build_property.ProjectTypeGuids = +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property.EnforceExtendedAnalyzerRules = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = Codience.API +build_property.RootNamespace = Codience.API +build_property.ProjectDir = /Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.RazorLangVersion = 9.0 +build_property.SupportLocalizedComponentNames = +build_property.GenerateRazorMetadataSourceChecksumAttributes = +build_property.MSBuildProjectDirectory = /Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API +build_property._RazorSourceGeneratorDebug = +build_property.EffectiveAnalysisLevelStyle = 9.0 +build_property.EnableCodeStyleSeverity = diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.GlobalUsings.g.cs b/Backend/API/obj/Debug/net9.0/Codience.API.GlobalUsings.g.cs new file mode 100644 index 00000000..025530a2 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.GlobalUsings.g.cs @@ -0,0 +1,17 @@ +// +global using global::Microsoft.AspNetCore.Builder; +global using global::Microsoft.AspNetCore.Hosting; +global using global::Microsoft.AspNetCore.Http; +global using global::Microsoft.AspNetCore.Routing; +global using global::Microsoft.Extensions.Configuration; +global using global::Microsoft.Extensions.DependencyInjection; +global using global::Microsoft.Extensions.Hosting; +global using global::Microsoft.Extensions.Logging; +global using global::System; +global using global::System.Collections.Generic; +global using global::System.IO; +global using global::System.Linq; +global using global::System.Net.Http; +global using global::System.Net.Http.Json; +global using global::System.Threading; +global using global::System.Threading.Tasks; diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.MvcApplicationPartsAssemblyInfo.cache b/Backend/API/obj/Debug/net9.0/Codience.API.MvcApplicationPartsAssemblyInfo.cache new file mode 100644 index 00000000..e69de29b diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.MvcApplicationPartsAssemblyInfo.cs b/Backend/API/obj/Debug/net9.0/Codience.API.MvcApplicationPartsAssemblyInfo.cs new file mode 100644 index 00000000..724ab3bf --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.MvcApplicationPartsAssemblyInfo.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute("Infrastructure.Presentation")] +[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute("Microsoft.AspNetCore.OpenApi")] +[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute("Swashbuckle.AspNetCore.SwaggerGen")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.assets.cache b/Backend/API/obj/Debug/net9.0/Codience.API.assets.cache new file mode 100644 index 00000000..510cbcf7 Binary files /dev/null and b/Backend/API/obj/Debug/net9.0/Codience.API.assets.cache differ diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.csproj.AssemblyReference.cache b/Backend/API/obj/Debug/net9.0/Codience.API.csproj.AssemblyReference.cache new file mode 100644 index 00000000..aeb59531 Binary files /dev/null and b/Backend/API/obj/Debug/net9.0/Codience.API.csproj.AssemblyReference.cache differ diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.csproj.CoreCompileInputs.cache b/Backend/API/obj/Debug/net9.0/Codience.API.csproj.CoreCompileInputs.cache new file mode 100644 index 00000000..49435c79 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +9f671aeb4e0e2d70e005d6145ebd3598d4775fdccec7ae3912e256de8e0c8f7e diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.csproj.FileListAbsolute.txt b/Backend/API/obj/Debug/net9.0/Codience.API.csproj.FileListAbsolute.txt new file mode 100644 index 00000000..fcdac4d8 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.csproj.FileListAbsolute.txt @@ -0,0 +1,161 @@ +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/appsettings.Development.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/appsettings.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Codience.API.staticwebassets.endpoints.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Codience.API +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Codience.API.deps.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Codience.API.runtimeconfig.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Codience.API.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Codience.API.pdb +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/CsvHelper.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/dotenv.net.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Humanizer.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.AspNetCore.OpenApi.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Bcl.AsyncInterfaces.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Build.Locator.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.CodeAnalysis.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.CodeAnalysis.CSharp.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.CodeAnalysis.Workspaces.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.EntityFrameworkCore.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.EntityFrameworkCore.Abstractions.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.EntityFrameworkCore.Design.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.EntityFrameworkCore.Relational.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Caching.Abstractions.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Caching.Memory.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Configuration.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Configuration.Abstractions.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Configuration.Binder.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.DependencyInjection.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.DependencyModel.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Diagnostics.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Http.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Logging.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Logging.Abstractions.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Options.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.Extensions.Primitives.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.IdentityModel.Abstractions.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.IdentityModel.JsonWebTokens.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.IdentityModel.Logging.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.IdentityModel.Tokens.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Microsoft.OpenApi.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Mono.TextTemplating.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Newtonsoft.Json.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Npgsql.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Npgsql.EntityFrameworkCore.PostgreSQL.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Polly.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Polly.Core.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Swashbuckle.AspNetCore.Swagger.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/System.CodeDom.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/System.Composition.AttributedModel.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/System.Composition.Convention.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/System.Composition.Hosting.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/System.Composition.Runtime.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/System.Composition.TypedParts.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/System.IdentityModel.Tokens.Jwt.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/cs/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/de/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/es/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/fr/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/it/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ja/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ko/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pl/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pt-BR/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ru/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/tr/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/it/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Core.Abstraction.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Core.Domain.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Core.Services.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Infrastructure.Persistence.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Infrastructure.Presentation.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Share.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Infrastructure.Persistence.pdb +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Infrastructure.Presentation.pdb +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Core.Abstraction.pdb +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Core.Domain.pdb +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Core.Services.pdb +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/bin/Debug/net9.0/Share.pdb +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.csproj.AssemblyReference.cache +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/rpswa.dswa.cache.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.GeneratedMSBuildEditorConfig.editorconfig +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.AssemblyInfoInputs.cache +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.AssemblyInfo.cs +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.csproj.CoreCompileInputs.cache +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.MvcApplicationPartsAssemblyInfo.cs +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.MvcApplicationPartsAssemblyInfo.cache +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.sourcelink.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/rjimswa.dswa.cache.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/rjsmrazor.dswa.cache.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/scopedcss/bundle/Codience.API.styles.css +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/staticwebassets.build.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/staticwebassets.build.json.cache +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/staticwebassets.development.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/staticwebassets.build.endpoints.json +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.3B30C0E2.Up2Date +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/refint/Codience.API.dll +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.pdb +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/Codience.API.genruntimeconfig.cache +/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/Debug/net9.0/ref/Codience.API.dll diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.dll b/Backend/API/obj/Debug/net9.0/Codience.API.dll new file mode 100644 index 00000000..87feebb6 Binary files /dev/null and b/Backend/API/obj/Debug/net9.0/Codience.API.dll differ diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.genruntimeconfig.cache b/Backend/API/obj/Debug/net9.0/Codience.API.genruntimeconfig.cache new file mode 100644 index 00000000..538211e7 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.genruntimeconfig.cache @@ -0,0 +1 @@ +817d5efe4c0780d8f010aaff3d281d2eabefc8839d27f8c7d67075921134be42 diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.pdb b/Backend/API/obj/Debug/net9.0/Codience.API.pdb new file mode 100644 index 00000000..5c9aba93 Binary files /dev/null and b/Backend/API/obj/Debug/net9.0/Codience.API.pdb differ diff --git a/Backend/API/obj/Debug/net9.0/Codience.API.sourcelink.json b/Backend/API/obj/Debug/net9.0/Codience.API.sourcelink.json new file mode 100644 index 00000000..017e104e --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/Codience.API.sourcelink.json @@ -0,0 +1 @@ +{"documents":{"/Users/rebuy/Desktop/FCAI/GP/CodienceProject/*":"https://raw.githubusercontent.com/SH-code12/Codience/32ab38f54d89655cd6eec400dbc4078ef42dcaa3/*"}} \ No newline at end of file diff --git a/Backend/API/obj/Debug/net9.0/apphost b/Backend/API/obj/Debug/net9.0/apphost new file mode 100755 index 00000000..7a487d72 Binary files /dev/null and b/Backend/API/obj/Debug/net9.0/apphost differ diff --git a/Backend/API/obj/Debug/net9.0/ref/Codience.API.dll b/Backend/API/obj/Debug/net9.0/ref/Codience.API.dll new file mode 100644 index 00000000..eea11514 Binary files /dev/null and b/Backend/API/obj/Debug/net9.0/ref/Codience.API.dll differ diff --git a/Backend/API/obj/Debug/net9.0/refint/Codience.API.dll b/Backend/API/obj/Debug/net9.0/refint/Codience.API.dll new file mode 100644 index 00000000..eea11514 Binary files /dev/null and b/Backend/API/obj/Debug/net9.0/refint/Codience.API.dll differ diff --git a/Backend/API/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json b/Backend/API/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json new file mode 100644 index 00000000..76be8394 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json @@ -0,0 +1 @@ +{"GlobalPropertiesHash":"yJlN0nyAunT1b6I6X/meeIE97eUPJAtOeARnDcQUJgg=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["fyRnfkRSZM\u002BPQQu6vP\u002BUBcynQocAQV9O0Iht5\u002BnVEts=","VAT65fwZtF5cDPp/X/c4gn0FjM\u002BQt1F1cd43JkMFtU4=","b5K5QtDoXb9o7RUpQG60g8SlcrnZ7qa84Lyhh35v5jY=","J74napuYY8IKyPAdhZ9vemdKcY5I\u002BDwglOJ/cu/Gm6A=","gLKJatau5yqKdQwBBcsMLxC\u002BqD3dPRyhzqNmgUyUvIs=","govvZRRtVh9T4yCua3OO34y\u002Bh7HahkWy0yGsARbb\u002BjA="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Backend/API/obj/Debug/net9.0/rjsmrazor.dswa.cache.json b/Backend/API/obj/Debug/net9.0/rjsmrazor.dswa.cache.json new file mode 100644 index 00000000..f82f696b --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/rjsmrazor.dswa.cache.json @@ -0,0 +1 @@ +{"GlobalPropertiesHash":"s7kZuO3R5odgc//ARMcsX9QXyki9uH/LqhnmAUUhuIQ=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["fyRnfkRSZM\u002BPQQu6vP\u002BUBcynQocAQV9O0Iht5\u002BnVEts=","VAT65fwZtF5cDPp/X/c4gn0FjM\u002BQt1F1cd43JkMFtU4=","b5K5QtDoXb9o7RUpQG60g8SlcrnZ7qa84Lyhh35v5jY=","J74napuYY8IKyPAdhZ9vemdKcY5I\u002BDwglOJ/cu/Gm6A=","gLKJatau5yqKdQwBBcsMLxC\u002BqD3dPRyhzqNmgUyUvIs=","govvZRRtVh9T4yCua3OO34y\u002Bh7HahkWy0yGsARbb\u002BjA="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Backend/API/obj/Debug/net9.0/rpswa.dswa.cache.json b/Backend/API/obj/Debug/net9.0/rpswa.dswa.cache.json new file mode 100644 index 00000000..29add9dc --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/rpswa.dswa.cache.json @@ -0,0 +1 @@ +{"GlobalPropertiesHash":"lXI7otBHwCsBsO8Wt9x8Mc2nJsrgZeOG3+KDVJ+Ibtc=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["fyRnfkRSZM\u002BPQQu6vP\u002BUBcynQocAQV9O0Iht5\u002BnVEts=","VAT65fwZtF5cDPp/X/c4gn0FjM\u002BQt1F1cd43JkMFtU4="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Backend/API/obj/Debug/net9.0/staticwebassets.build.endpoints.json b/Backend/API/obj/Debug/net9.0/staticwebassets.build.endpoints.json new file mode 100644 index 00000000..5576e889 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/staticwebassets.build.endpoints.json @@ -0,0 +1 @@ +{"Version":1,"ManifestType":"Build","Endpoints":[]} \ No newline at end of file diff --git a/Backend/API/obj/Debug/net9.0/staticwebassets.build.json b/Backend/API/obj/Debug/net9.0/staticwebassets.build.json new file mode 100644 index 00000000..b7b26d2a --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/staticwebassets.build.json @@ -0,0 +1 @@ +{"Version":1,"Hash":"+NkZzWLfuSUmOEFefZcUBJbHF+N0G/kZowb6okzCSJA=","Source":"Codience.API","BasePath":"_content/Codience.API","Mode":"Default","ManifestType":"Build","ReferencedProjectsConfiguration":[],"DiscoveryPatterns":[],"Assets":[],"Endpoints":[]} \ No newline at end of file diff --git a/Backend/API/obj/Debug/net9.0/staticwebassets.build.json.cache b/Backend/API/obj/Debug/net9.0/staticwebassets.build.json.cache new file mode 100644 index 00000000..e11a16a1 --- /dev/null +++ b/Backend/API/obj/Debug/net9.0/staticwebassets.build.json.cache @@ -0,0 +1 @@ ++NkZzWLfuSUmOEFefZcUBJbHF+N0G/kZowb6okzCSJA= \ No newline at end of file diff --git a/Backend/API/obj/project.assets.json b/Backend/API/obj/project.assets.json new file mode 100644 index 00000000..da1f03db --- /dev/null +++ b/Backend/API/obj/project.assets.json @@ -0,0 +1,3919 @@ +{ + "version": 3, + "targets": { + "net9.0": { + "CsvHelper/33.1.0": { + "type": "package", + "compile": { + "lib/net9.0/CsvHelper.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/CsvHelper.dll": { + "related": ".xml" + } + } + }, + "dotenv.net/4.0.2": { + "type": "package", + "compile": { + "lib/netstandard2.1/dotenv.net.dll": {} + }, + "runtime": { + "lib/netstandard2.1/dotenv.net.dll": {} + } + }, + "Humanizer.Core/2.14.1": { + "type": "package", + "compile": { + "lib/net6.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/Humanizer.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.OpenApi/9.0.2": { + "type": "package", + "dependencies": { + "Microsoft.OpenApi": "1.6.17" + }, + "compile": { + "lib/net9.0/Microsoft.AspNetCore.OpenApi.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.AspNetCore.OpenApi.dll": { + "related": ".xml" + } + }, + "frameworkReferences": [ + "Microsoft.AspNetCore.App" + ] + }, + "Microsoft.Bcl.AsyncInterfaces/7.0.0": { + "type": "package", + "compile": { + "lib/netstandard2.1/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Build.Framework/17.8.3": { + "type": "package", + "compile": { + "ref/net8.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/_._": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.Build.Locator/1.7.8": { + "type": "package", + "compile": { + "lib/net6.0/_._": {} + }, + "runtime": { + "lib/net6.0/Microsoft.Build.Locator.dll": {} + }, + "build": { + "build/_._": {} + } + }, + "Microsoft.CodeAnalysis.Analyzers/3.3.4": { + "type": "package", + "build": { + "buildTransitive/Microsoft.CodeAnalysis.Analyzers.props": {}, + "buildTransitive/Microsoft.CodeAnalysis.Analyzers.targets": {} + } + }, + "Microsoft.CodeAnalysis.Common/4.8.0": { + "type": "package", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "3.3.4", + "System.Collections.Immutable": "7.0.0", + "System.Reflection.Metadata": "7.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net7.0/Microsoft.CodeAnalysis.dll": { + "related": ".pdb;.xml" + } + }, + "resource": { + "lib/net7.0/cs/Microsoft.CodeAnalysis.resources.dll": { + "locale": "cs" + }, + "lib/net7.0/de/Microsoft.CodeAnalysis.resources.dll": { + "locale": "de" + }, + "lib/net7.0/es/Microsoft.CodeAnalysis.resources.dll": { + "locale": "es" + }, + "lib/net7.0/fr/Microsoft.CodeAnalysis.resources.dll": { + "locale": "fr" + }, + "lib/net7.0/it/Microsoft.CodeAnalysis.resources.dll": { + "locale": "it" + }, + "lib/net7.0/ja/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ja" + }, + "lib/net7.0/ko/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ko" + }, + "lib/net7.0/pl/Microsoft.CodeAnalysis.resources.dll": { + "locale": "pl" + }, + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.resources.dll": { + "locale": "pt-BR" + }, + "lib/net7.0/ru/Microsoft.CodeAnalysis.resources.dll": { + "locale": "ru" + }, + "lib/net7.0/tr/Microsoft.CodeAnalysis.resources.dll": { + "locale": "tr" + }, + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll": { + "locale": "zh-Hans" + }, + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.CSharp/4.8.0": { + "type": "package", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[4.8.0]" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net7.0/Microsoft.CodeAnalysis.CSharp.dll": { + "related": ".pdb;.xml" + } + }, + "resource": { + "lib/net7.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "cs" + }, + "lib/net7.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "de" + }, + "lib/net7.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "es" + }, + "lib/net7.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "fr" + }, + "lib/net7.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "it" + }, + "lib/net7.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ja" + }, + "lib/net7.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ko" + }, + "lib/net7.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "pl" + }, + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "pt-BR" + }, + "lib/net7.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "ru" + }, + "lib/net7.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "tr" + }, + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "zh-Hans" + }, + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.CSharp.Workspaces/4.8.0": { + "type": "package", + "dependencies": { + "Humanizer.Core": "2.14.1", + "Microsoft.CodeAnalysis.CSharp": "[4.8.0]", + "Microsoft.CodeAnalysis.Common": "[4.8.0]", + "Microsoft.CodeAnalysis.Workspaces.Common": "[4.8.0]" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net7.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll": { + "related": ".pdb;.xml" + } + }, + "resource": { + "lib/net7.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "cs" + }, + "lib/net7.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "de" + }, + "lib/net7.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "es" + }, + "lib/net7.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "fr" + }, + "lib/net7.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "it" + }, + "lib/net7.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "ja" + }, + "lib/net7.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "ko" + }, + "lib/net7.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "pl" + }, + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "pt-BR" + }, + "lib/net7.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "ru" + }, + "lib/net7.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "tr" + }, + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "zh-Hans" + }, + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.Workspaces.Common/4.8.0": { + "type": "package", + "dependencies": { + "Humanizer.Core": "2.14.1", + "Microsoft.Bcl.AsyncInterfaces": "7.0.0", + "Microsoft.CodeAnalysis.Common": "[4.8.0]", + "System.Composition": "7.0.0", + "System.IO.Pipelines": "7.0.0", + "System.Threading.Channels": "7.0.0" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.dll": { + "related": ".pdb;.xml" + } + }, + "resource": { + "lib/net7.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "cs" + }, + "lib/net7.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "de" + }, + "lib/net7.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "es" + }, + "lib/net7.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "fr" + }, + "lib/net7.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "it" + }, + "lib/net7.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "ja" + }, + "lib/net7.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "ko" + }, + "lib/net7.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "pl" + }, + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "pt-BR" + }, + "lib/net7.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "ru" + }, + "lib/net7.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "tr" + }, + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "zh-Hans" + }, + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.CodeAnalysis.Workspaces.MSBuild/4.8.0": { + "type": "package", + "dependencies": { + "Microsoft.Build.Framework": "16.10.0", + "Microsoft.CodeAnalysis.Common": "[4.8.0]", + "Microsoft.CodeAnalysis.Workspaces.Common": "[4.8.0]", + "System.Text.Json": "7.0.3" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".pdb;.runtimeconfig.json;.xml" + } + }, + "runtime": { + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll": { + "related": ".pdb;.runtimeconfig.json;.xml" + }, + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll": { + "related": ".BuildHost.pdb;.BuildHost.runtimeconfig.json;.BuildHost.xml;.pdb;.xml" + } + }, + "resource": { + "lib/net7.0/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "cs" + }, + "lib/net7.0/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "de" + }, + "lib/net7.0/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "es" + }, + "lib/net7.0/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "fr" + }, + "lib/net7.0/it/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "it" + }, + "lib/net7.0/ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "ja" + }, + "lib/net7.0/ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "ko" + }, + "lib/net7.0/pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "pl" + }, + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "pt-BR" + }, + "lib/net7.0/ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "ru" + }, + "lib/net7.0/tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "tr" + }, + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "zh-Hans" + }, + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.EntityFrameworkCore/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "9.0.9", + "Microsoft.EntityFrameworkCore.Analyzers": "9.0.9", + "Microsoft.Extensions.Caching.Memory": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9" + }, + "compile": { + "lib/net8.0/Microsoft.EntityFrameworkCore.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.EntityFrameworkCore.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/Microsoft.EntityFrameworkCore.props": {} + } + }, + "Microsoft.EntityFrameworkCore.Abstractions/9.0.9": { + "type": "package", + "compile": { + "lib/net8.0/Microsoft.EntityFrameworkCore.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.EntityFrameworkCore.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.EntityFrameworkCore.Analyzers/9.0.9": { + "type": "package" + }, + "Microsoft.EntityFrameworkCore.Design/9.0.9": { + "type": "package", + "dependencies": { + "Humanizer.Core": "2.14.1", + "Microsoft.Build.Framework": "17.8.3", + "Microsoft.Build.Locator": "1.7.8", + "Microsoft.CodeAnalysis.CSharp": "4.8.0", + "Microsoft.CodeAnalysis.CSharp.Workspaces": "4.8.0", + "Microsoft.CodeAnalysis.Workspaces.MSBuild": "4.8.0", + "Microsoft.EntityFrameworkCore.Relational": "9.0.9", + "Microsoft.Extensions.Caching.Memory": "9.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.DependencyModel": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9", + "Mono.TextTemplating": "3.0.0", + "System.Text.Json": "9.0.9" + }, + "compile": { + "lib/net8.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.EntityFrameworkCore.Design.dll": { + "related": ".xml" + } + }, + "build": { + "build/net8.0/Microsoft.EntityFrameworkCore.Design.props": {} + } + }, + "Microsoft.EntityFrameworkCore.Relational/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore": "9.0.9", + "Microsoft.Extensions.Caching.Memory": "9.0.9", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging": "9.0.9" + }, + "compile": { + "lib/net8.0/Microsoft.EntityFrameworkCore.Relational.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.EntityFrameworkCore.Relational.dll": { + "related": ".xml" + } + } + }, + "Microsoft.EntityFrameworkCore.Tools/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore.Design": "9.0.9" + } + }, + "Microsoft.Extensions.Caching.Abstractions/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "9.0.9" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Caching.Memory/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "9.0.9", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9", + "Microsoft.Extensions.Primitives": "9.0.9" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Caching.Memory.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Caching.Memory.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Configuration/9.0.5": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.Primitives": "9.0.5" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Configuration.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Configuration.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Configuration.Abstractions/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "9.0.9" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Configuration.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Configuration.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Configuration.Binder/9.0.5": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Configuration.Binder.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Configuration.Binder.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netstandard2.0/Microsoft.Extensions.Configuration.Binder.targets": {} + } + }, + "Microsoft.Extensions.DependencyInjection/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.DependencyInjection.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.DependencyInjection.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.9": { + "type": "package", + "compile": { + "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.DependencyModel/9.0.9": { + "type": "package", + "compile": { + "lib/net9.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.DependencyModel.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Diagnostics/9.0.5": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "9.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.5" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Diagnostics.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Diagnostics.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions/9.0.5": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Http/9.0.5": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Diagnostics": "9.0.5", + "Microsoft.Extensions.Logging": "9.0.5", + "Microsoft.Extensions.Logging.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Http.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Http.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Logging/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "9.0.9", + "Microsoft.Extensions.Logging.Abstractions": "9.0.9", + "Microsoft.Extensions.Options": "9.0.9" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Logging.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Logging.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Logging.Abstractions/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets": {} + } + }, + "Microsoft.Extensions.Options/9.0.9": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.9", + "Microsoft.Extensions.Primitives": "9.0.9" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Options.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Options.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/Microsoft.Extensions.Options.targets": {} + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions/9.0.5": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.Configuration.Binder": "9.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5", + "Microsoft.Extensions.Primitives": "9.0.5" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Primitives/9.0.9": { + "type": "package", + "compile": { + "lib/net9.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.IdentityModel.Abstractions/8.17.0": { + "type": "package", + "compile": { + "lib/net9.0/Microsoft.IdentityModel.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.IdentityModel.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.IdentityModel.JsonWebTokens/8.17.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "8.17.0" + }, + "compile": { + "lib/net9.0/Microsoft.IdentityModel.JsonWebTokens.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.IdentityModel.JsonWebTokens.dll": { + "related": ".xml" + } + } + }, + "Microsoft.IdentityModel.Logging/8.17.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Abstractions": "8.17.0" + }, + "compile": { + "lib/net9.0/Microsoft.IdentityModel.Logging.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.IdentityModel.Logging.dll": { + "related": ".xml" + } + } + }, + "Microsoft.IdentityModel.Tokens/8.17.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.IdentityModel.Logging": "8.17.0" + }, + "compile": { + "lib/net9.0/Microsoft.IdentityModel.Tokens.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.IdentityModel.Tokens.dll": { + "related": ".xml" + } + } + }, + "Microsoft.OpenApi/1.6.25": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.OpenApi.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.OpenApi.dll": { + "related": ".pdb;.xml" + } + } + }, + "Mono.TextTemplating/3.0.0": { + "type": "package", + "dependencies": { + "System.CodeDom": "6.0.0" + }, + "compile": { + "lib/net6.0/_._": {} + }, + "runtime": { + "lib/net6.0/Mono.TextTemplating.dll": {} + }, + "build": { + "buildTransitive/Mono.TextTemplating.targets": {} + } + }, + "Newtonsoft.Json/13.0.4": { + "type": "package", + "compile": { + "lib/net6.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + } + }, + "Npgsql/9.0.3": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "8.0.2" + }, + "compile": { + "lib/net8.0/Npgsql.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Npgsql.dll": { + "related": ".xml" + } + } + }, + "Npgsql.EntityFrameworkCore.PostgreSQL/9.0.4": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore": "[9.0.1, 10.0.0)", + "Microsoft.EntityFrameworkCore.Relational": "[9.0.1, 10.0.0)", + "Npgsql": "9.0.3" + }, + "compile": { + "lib/net8.0/Npgsql.EntityFrameworkCore.PostgreSQL.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Npgsql.EntityFrameworkCore.PostgreSQL.dll": { + "related": ".xml" + } + } + }, + "Polly/8.6.4": { + "type": "package", + "dependencies": { + "Polly.Core": "8.6.4" + }, + "compile": { + "lib/net6.0/Polly.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net6.0/Polly.dll": { + "related": ".pdb;.xml" + } + } + }, + "Polly.Core/8.6.4": { + "type": "package", + "compile": { + "lib/net8.0/Polly.Core.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net8.0/Polly.Core.dll": { + "related": ".pdb;.xml" + } + } + }, + "Swashbuckle.AspNetCore.Swagger/9.0.5": { + "type": "package", + "dependencies": { + "Microsoft.OpenApi": "1.6.25" + }, + "compile": { + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.dll": { + "related": ".pdb;.xml" + } + }, + "frameworkReferences": [ + "Microsoft.AspNetCore.App" + ] + }, + "Swashbuckle.AspNetCore.SwaggerGen/9.0.5": { + "type": "package", + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "9.0.5" + }, + "compile": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll": { + "related": ".pdb;.xml" + } + } + }, + "Swashbuckle.AspNetCore.SwaggerUI/9.0.5": { + "type": "package", + "compile": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll": { + "related": ".pdb;.xml" + } + }, + "frameworkReferences": [ + "Microsoft.AspNetCore.App" + ] + }, + "System.CodeDom/6.0.0": { + "type": "package", + "compile": { + "lib/net6.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.CodeDom.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.Collections.Immutable/7.0.0": { + "type": "package", + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.Collections.Immutable.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.Composition/7.0.0": { + "type": "package", + "dependencies": { + "System.Composition.AttributedModel": "7.0.0", + "System.Composition.Convention": "7.0.0", + "System.Composition.Hosting": "7.0.0", + "System.Composition.Runtime": "7.0.0", + "System.Composition.TypedParts": "7.0.0" + }, + "compile": { + "lib/netcoreapp2.0/_._": {} + }, + "runtime": { + "lib/netcoreapp2.0/_._": {} + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.Composition.AttributedModel/7.0.0": { + "type": "package", + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.Composition.AttributedModel.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.Composition.Convention/7.0.0": { + "type": "package", + "dependencies": { + "System.Composition.AttributedModel": "7.0.0" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.Composition.Convention.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.Composition.Hosting/7.0.0": { + "type": "package", + "dependencies": { + "System.Composition.Runtime": "7.0.0" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.Composition.Hosting.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.Composition.Runtime/7.0.0": { + "type": "package", + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.Composition.Runtime.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.Composition.TypedParts/7.0.0": { + "type": "package", + "dependencies": { + "System.Composition.AttributedModel": "7.0.0", + "System.Composition.Hosting": "7.0.0", + "System.Composition.Runtime": "7.0.0" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.Composition.TypedParts.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.IdentityModel.Tokens.Jwt/8.17.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "8.17.0", + "Microsoft.IdentityModel.Tokens": "8.17.0" + }, + "compile": { + "lib/net9.0/System.IdentityModel.Tokens.Jwt.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/System.IdentityModel.Tokens.Jwt.dll": { + "related": ".xml" + } + } + }, + "System.IO.Pipelines/7.0.0": { + "type": "package", + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.IO.Pipelines.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.Reflection.Metadata/7.0.0": { + "type": "package", + "dependencies": { + "System.Collections.Immutable": "7.0.0" + }, + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.Reflection.Metadata.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "compile": { + "lib/net6.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.Text.Json/9.0.9": { + "type": "package", + "compile": { + "lib/net9.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/System.Text.Json.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/System.Text.Json.targets": {} + } + }, + "System.Threading.Channels/7.0.0": { + "type": "package", + "compile": { + "lib/net7.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/net7.0/System.Threading.Channels.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "Core.Abstraction/1.0.0": { + "type": "project", + "framework": ".NETCoreApp,Version=v9.0", + "dependencies": { + "Core.Domain": "1.0.0", + "Share": "1.0.0" + }, + "compile": { + "bin/placeholder/Core.Abstraction.dll": {} + }, + "runtime": { + "bin/placeholder/Core.Abstraction.dll": {} + } + }, + "Core.Domain/1.0.0": { + "type": "project", + "framework": ".NETCoreApp,Version=v9.0", + "compile": { + "bin/placeholder/Core.Domain.dll": {} + }, + "runtime": { + "bin/placeholder/Core.Domain.dll": {} + } + }, + "Core.Services/1.0.0": { + "type": "project", + "framework": ".NETCoreApp,Version=v9.0", + "dependencies": { + "Core.Abstraction": "1.0.0", + "Core.Domain": "1.0.0", + "CsvHelper": "33.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "9.0.9", + "Microsoft.Extensions.Http": "9.0.5", + "Newtonsoft.Json": "13.0.4", + "Polly": "8.6.4", + "System.IdentityModel.Tokens.Jwt": "8.17.0" + }, + "compile": { + "bin/placeholder/Core.Services.dll": {} + }, + "runtime": { + "bin/placeholder/Core.Services.dll": {} + } + }, + "Infrastructure.Persistence/1.0.0": { + "type": "project", + "framework": ".NETCoreApp,Version=v9.0", + "dependencies": { + "Core.Domain": "1.0.0", + "Core.Services": "1.0.0", + "CsvHelper": "33.1.0", + "Microsoft.EntityFrameworkCore": "9.0.9", + "Microsoft.Extensions.Http": "9.0.5", + "Npgsql.EntityFrameworkCore.PostgreSQL": "9.0.4", + "Polly": "8.6.4" + }, + "compile": { + "bin/placeholder/Infrastructure.Persistence.dll": {} + }, + "runtime": { + "bin/placeholder/Infrastructure.Persistence.dll": {} + } + }, + "Infrastructure.Presentation/1.0.0": { + "type": "project", + "framework": ".NETCoreApp,Version=v9.0", + "dependencies": { + "Core.Abstraction": "1.0.0", + "Core.Services": "1.0.0", + "Microsoft.Extensions.Http": "9.0.5", + "Polly": "8.6.4", + "Share": "1.0.0" + }, + "compile": { + "bin/placeholder/Infrastructure.Presentation.dll": {} + }, + "runtime": { + "bin/placeholder/Infrastructure.Presentation.dll": {} + }, + "frameworkReferences": [ + "Microsoft.AspNetCore.App" + ] + }, + "Share/1.0.0": { + "type": "project", + "framework": ".NETCoreApp,Version=v9.0", + "compile": { + "bin/placeholder/Share.dll": {} + }, + "runtime": { + "bin/placeholder/Share.dll": {} + } + } + } + }, + "libraries": { + "CsvHelper/33.1.0": { + "sha512": "kqfTOZGrn7NarNeXgjh86JcpTHUoeQDMB8t9NVa/ZtlSYiV1rxfRnQ49WaJsob4AiGrbK0XDzpyKkBwai4F8eg==", + "type": "package", + "path": "csvhelper/33.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "csvhelper.33.1.0.nupkg.sha512", + "csvhelper.nuspec", + "lib/net462/CsvHelper.dll", + "lib/net462/CsvHelper.xml", + "lib/net47/CsvHelper.dll", + "lib/net47/CsvHelper.xml", + "lib/net48/CsvHelper.dll", + "lib/net48/CsvHelper.xml", + "lib/net8.0/CsvHelper.dll", + "lib/net8.0/CsvHelper.xml", + "lib/net9.0/CsvHelper.dll", + "lib/net9.0/CsvHelper.xml", + "lib/netstandard2.0/CsvHelper.dll", + "lib/netstandard2.0/CsvHelper.xml", + "lib/netstandard2.1/CsvHelper.dll", + "lib/netstandard2.1/CsvHelper.xml" + ] + }, + "dotenv.net/4.0.2": { + "sha512": "6xpiqKV1aKWIkSSDP7J+60GEKUitiDweD4yOsn9giCMysSfCghJQuYfXQwbzgdmt0Bsv/2ajUCbjvemGavqItA==", + "type": "package", + "path": "dotenv.net/4.0.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "dotenv.net.4.0.2.nupkg.sha512", + "dotenv.net.nuspec", + "lib/netstandard2.0/dotenv.net.dll", + "lib/netstandard2.1/dotenv.net.dll" + ] + }, + "Humanizer.Core/2.14.1": { + "sha512": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw==", + "type": "package", + "path": "humanizer.core/2.14.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "humanizer.core.2.14.1.nupkg.sha512", + "humanizer.core.nuspec", + "lib/net6.0/Humanizer.dll", + "lib/net6.0/Humanizer.xml", + "lib/netstandard1.0/Humanizer.dll", + "lib/netstandard1.0/Humanizer.xml", + "lib/netstandard2.0/Humanizer.dll", + "lib/netstandard2.0/Humanizer.xml", + "logo.png" + ] + }, + "Microsoft.AspNetCore.OpenApi/9.0.2": { + "sha512": "JUndpjRNdG8GvzBLH/J4hen4ehWaPcshtiQ6+sUs1Bcj3a7dOsmWpDloDlpPeMOVSlhHwUJ3Xld0ClZjsFLgFQ==", + "type": "package", + "path": "microsoft.aspnetcore.openapi/9.0.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "lib/net9.0/Microsoft.AspNetCore.OpenApi.dll", + "lib/net9.0/Microsoft.AspNetCore.OpenApi.xml", + "microsoft.aspnetcore.openapi.9.0.2.nupkg.sha512", + "microsoft.aspnetcore.openapi.nuspec" + ] + }, + "Microsoft.Bcl.AsyncInterfaces/7.0.0": { + "sha512": "3aeMZ1N0lJoSyzqiP03hqemtb1BijhsJADdobn/4nsMJ8V1H+CrpuduUe4hlRdx+ikBQju1VGjMD1GJ3Sk05Eg==", + "type": "package", + "path": "microsoft.bcl.asyncinterfaces/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Bcl.AsyncInterfaces.targets", + "buildTransitive/net462/_._", + "lib/net462/Microsoft.Bcl.AsyncInterfaces.dll", + "lib/net462/Microsoft.Bcl.AsyncInterfaces.xml", + "lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll", + "lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.xml", + "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll", + "lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.xml", + "microsoft.bcl.asyncinterfaces.7.0.0.nupkg.sha512", + "microsoft.bcl.asyncinterfaces.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Build.Framework/17.8.3": { + "sha512": "NrQZJW8TlKVPx72yltGb8SVz3P5mNRk9fNiD/ao8jRSk48WqIIdCn99q4IjlVmPcruuQ+yLdjNQLL8Rb4c916g==", + "type": "package", + "path": "microsoft.build.framework/17.8.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "MSBuild-NuGet-Icon.png", + "README.md", + "lib/net472/Microsoft.Build.Framework.dll", + "lib/net472/Microsoft.Build.Framework.pdb", + "lib/net472/Microsoft.Build.Framework.xml", + "lib/net8.0/Microsoft.Build.Framework.dll", + "lib/net8.0/Microsoft.Build.Framework.pdb", + "lib/net8.0/Microsoft.Build.Framework.xml", + "microsoft.build.framework.17.8.3.nupkg.sha512", + "microsoft.build.framework.nuspec", + "notices/THIRDPARTYNOTICES.txt", + "ref/net472/Microsoft.Build.Framework.dll", + "ref/net472/Microsoft.Build.Framework.xml", + "ref/net8.0/Microsoft.Build.Framework.dll", + "ref/net8.0/Microsoft.Build.Framework.xml", + "ref/netstandard2.0/Microsoft.Build.Framework.dll", + "ref/netstandard2.0/Microsoft.Build.Framework.xml" + ] + }, + "Microsoft.Build.Locator/1.7.8": { + "sha512": "sPy10x527Ph16S2u0yGME4S6ohBKJ69WfjeGG/bvELYeZVmJdKjxgnlL8cJJJLGV/cZIRqSfB12UDB8ICakOog==", + "type": "package", + "path": "microsoft.build.locator/1.7.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "MSBuild-NuGet-Icon.png", + "build/Microsoft.Build.Locator.props", + "build/Microsoft.Build.Locator.targets", + "lib/net46/Microsoft.Build.Locator.dll", + "lib/net6.0/Microsoft.Build.Locator.dll", + "microsoft.build.locator.1.7.8.nupkg.sha512", + "microsoft.build.locator.nuspec" + ] + }, + "Microsoft.CodeAnalysis.Analyzers/3.3.4": { + "sha512": "AxkxcPR+rheX0SmvpLVIGLhOUXAKG56a64kV9VQZ4y9gR9ZmPXnqZvHJnmwLSwzrEP6junUF11vuc+aqo5r68g==", + "type": "package", + "path": "microsoft.codeanalysis.analyzers/3.3.4", + "hasTools": true, + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "ThirdPartyNotices.txt", + "analyzers/dotnet/cs/Microsoft.CodeAnalysis.Analyzers.dll", + "analyzers/dotnet/cs/Microsoft.CodeAnalysis.CSharp.Analyzers.dll", + "analyzers/dotnet/cs/cs/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/de/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/es/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/fr/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/it/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/ja/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/ko/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/pl/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/pt-BR/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/ru/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/tr/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/zh-Hans/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/cs/zh-Hant/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/Microsoft.CodeAnalysis.Analyzers.dll", + "analyzers/dotnet/vb/Microsoft.CodeAnalysis.VisualBasic.Analyzers.dll", + "analyzers/dotnet/vb/cs/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/de/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/es/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/fr/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/it/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/ja/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/ko/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/pl/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/pt-BR/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/ru/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/tr/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/zh-Hans/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "analyzers/dotnet/vb/zh-Hant/Microsoft.CodeAnalysis.Analyzers.resources.dll", + "buildTransitive/Microsoft.CodeAnalysis.Analyzers.props", + "buildTransitive/Microsoft.CodeAnalysis.Analyzers.targets", + "buildTransitive/config/analysislevel_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevel_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevel_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_all.globalconfig", + "buildTransitive/config/analysislevel_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_default.globalconfig", + "buildTransitive/config/analysislevel_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevel_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_none.globalconfig", + "buildTransitive/config/analysislevel_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevel_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_all.globalconfig", + "buildTransitive/config/analysislevel_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_default.globalconfig", + "buildTransitive/config/analysislevel_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_minimum.globalconfig", + "buildTransitive/config/analysislevel_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_none.globalconfig", + "buildTransitive/config/analysislevel_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_3_recommended.globalconfig", + "buildTransitive/config/analysislevel_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_4_3_all.globalconfig", + "buildTransitive/config/analysislevel_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_4_3_default.globalconfig", + "buildTransitive/config/analysislevel_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevel_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_4_3_none.globalconfig", + "buildTransitive/config/analysislevel_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevel_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevel_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevelcorrectness_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_all.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_default.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_none.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_all.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_default.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_minimum.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_none.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_recommended.globalconfig", + "buildTransitive/config/analysislevelcorrectness_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_all.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_default.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_none.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevelcorrectness_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevellibrary_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_all.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_default.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_none.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevellibrary_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_all.globalconfig", + "buildTransitive/config/analysislevellibrary_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_default.globalconfig", + "buildTransitive/config/analysislevellibrary_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_minimum.globalconfig", + "buildTransitive/config/analysislevellibrary_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_none.globalconfig", + "buildTransitive/config/analysislevellibrary_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_3_recommended.globalconfig", + "buildTransitive/config/analysislevellibrary_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_all.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_default.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_none.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevellibrary_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscompatibility_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysiscorrectness_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdesign_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisdocumentation_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysislocalization_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisperformance_4_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_2_9_8_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_3_recommended_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_all.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_all_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_default.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_default_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_minimum.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_minimum_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_none.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_none_warnaserror.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_recommended.globalconfig", + "buildTransitive/config/analysislevelmicrosoftcodeanalysisreleasetracking_4_3_recommended_warnaserror.globalconfig", + "documentation/Analyzer Configuration.md", + "documentation/Microsoft.CodeAnalysis.Analyzers.md", + "documentation/Microsoft.CodeAnalysis.Analyzers.sarif", + "editorconfig/AllRulesDefault/.editorconfig", + "editorconfig/AllRulesDisabled/.editorconfig", + "editorconfig/AllRulesEnabled/.editorconfig", + "editorconfig/CorrectnessRulesDefault/.editorconfig", + "editorconfig/CorrectnessRulesEnabled/.editorconfig", + "editorconfig/DataflowRulesDefault/.editorconfig", + "editorconfig/DataflowRulesEnabled/.editorconfig", + "editorconfig/LibraryRulesDefault/.editorconfig", + "editorconfig/LibraryRulesEnabled/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisCompatibilityRulesDefault/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisCompatibilityRulesEnabled/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisCorrectnessRulesDefault/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisCorrectnessRulesEnabled/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisDesignRulesDefault/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisDesignRulesEnabled/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisDocumentationRulesDefault/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisDocumentationRulesEnabled/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisLocalizationRulesDefault/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisLocalizationRulesEnabled/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisPerformanceRulesDefault/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisPerformanceRulesEnabled/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisReleaseTrackingRulesDefault/.editorconfig", + "editorconfig/MicrosoftCodeAnalysisReleaseTrackingRulesEnabled/.editorconfig", + "editorconfig/PortedFromFxCopRulesDefault/.editorconfig", + "editorconfig/PortedFromFxCopRulesEnabled/.editorconfig", + "microsoft.codeanalysis.analyzers.3.3.4.nupkg.sha512", + "microsoft.codeanalysis.analyzers.nuspec", + "rulesets/AllRulesDefault.ruleset", + "rulesets/AllRulesDisabled.ruleset", + "rulesets/AllRulesEnabled.ruleset", + "rulesets/CorrectnessRulesDefault.ruleset", + "rulesets/CorrectnessRulesEnabled.ruleset", + "rulesets/DataflowRulesDefault.ruleset", + "rulesets/DataflowRulesEnabled.ruleset", + "rulesets/LibraryRulesDefault.ruleset", + "rulesets/LibraryRulesEnabled.ruleset", + "rulesets/MicrosoftCodeAnalysisCompatibilityRulesDefault.ruleset", + "rulesets/MicrosoftCodeAnalysisCompatibilityRulesEnabled.ruleset", + "rulesets/MicrosoftCodeAnalysisCorrectnessRulesDefault.ruleset", + "rulesets/MicrosoftCodeAnalysisCorrectnessRulesEnabled.ruleset", + "rulesets/MicrosoftCodeAnalysisDesignRulesDefault.ruleset", + "rulesets/MicrosoftCodeAnalysisDesignRulesEnabled.ruleset", + "rulesets/MicrosoftCodeAnalysisDocumentationRulesDefault.ruleset", + "rulesets/MicrosoftCodeAnalysisDocumentationRulesEnabled.ruleset", + "rulesets/MicrosoftCodeAnalysisLocalizationRulesDefault.ruleset", + "rulesets/MicrosoftCodeAnalysisLocalizationRulesEnabled.ruleset", + "rulesets/MicrosoftCodeAnalysisPerformanceRulesDefault.ruleset", + "rulesets/MicrosoftCodeAnalysisPerformanceRulesEnabled.ruleset", + "rulesets/MicrosoftCodeAnalysisReleaseTrackingRulesDefault.ruleset", + "rulesets/MicrosoftCodeAnalysisReleaseTrackingRulesEnabled.ruleset", + "rulesets/PortedFromFxCopRulesDefault.ruleset", + "rulesets/PortedFromFxCopRulesEnabled.ruleset", + "tools/install.ps1", + "tools/uninstall.ps1" + ] + }, + "Microsoft.CodeAnalysis.Common/4.8.0": { + "sha512": "/jR+e/9aT+BApoQJABlVCKnnggGQbvGh7BKq2/wI1LamxC+LbzhcLj4Vj7gXCofl1n4E521YfF9w0WcASGg/KA==", + "type": "package", + "path": "microsoft.codeanalysis.common/4.8.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "ThirdPartyNotices.rtf", + "lib/net6.0/Microsoft.CodeAnalysis.dll", + "lib/net6.0/Microsoft.CodeAnalysis.pdb", + "lib/net6.0/Microsoft.CodeAnalysis.xml", + "lib/net6.0/cs/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/de/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/es/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/fr/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/it/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/ja/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/ko/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/pl/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/pt-BR/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/ru/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/tr/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll", + "lib/net6.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/Microsoft.CodeAnalysis.dll", + "lib/net7.0/Microsoft.CodeAnalysis.pdb", + "lib/net7.0/Microsoft.CodeAnalysis.xml", + "lib/net7.0/cs/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/de/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/es/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/fr/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/it/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/ja/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/ko/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/pl/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/ru/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/tr/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll", + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.pdb", + "lib/netstandard2.0/Microsoft.CodeAnalysis.xml", + "lib/netstandard2.0/cs/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/de/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/es/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/fr/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/it/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/ja/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/ko/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/pl/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/pt-BR/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/ru/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/tr/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/zh-Hans/Microsoft.CodeAnalysis.resources.dll", + "lib/netstandard2.0/zh-Hant/Microsoft.CodeAnalysis.resources.dll", + "microsoft.codeanalysis.common.4.8.0.nupkg.sha512", + "microsoft.codeanalysis.common.nuspec" + ] + }, + "Microsoft.CodeAnalysis.CSharp/4.8.0": { + "sha512": "+3+qfdb/aaGD8PZRCrsdobbzGs1m9u119SkkJt8e/mk3xLJz/udLtS2T6nY27OTXxBBw10HzAbC8Z9w08VyP/g==", + "type": "package", + "path": "microsoft.codeanalysis.csharp/4.8.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "ThirdPartyNotices.rtf", + "lib/net6.0/Microsoft.CodeAnalysis.CSharp.dll", + "lib/net6.0/Microsoft.CodeAnalysis.CSharp.pdb", + "lib/net6.0/Microsoft.CodeAnalysis.CSharp.xml", + "lib/net6.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net6.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/Microsoft.CodeAnalysis.CSharp.dll", + "lib/net7.0/Microsoft.CodeAnalysis.CSharp.pdb", + "lib/net7.0/Microsoft.CodeAnalysis.CSharp.xml", + "lib/net7.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.CSharp.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.CSharp.pdb", + "lib/netstandard2.0/Microsoft.CodeAnalysis.CSharp.xml", + "lib/netstandard2.0/cs/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/de/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/es/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/fr/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/it/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/ja/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/ko/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/pl/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/ru/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/tr/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.dll", + "lib/netstandard2.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.dll", + "microsoft.codeanalysis.csharp.4.8.0.nupkg.sha512", + "microsoft.codeanalysis.csharp.nuspec" + ] + }, + "Microsoft.CodeAnalysis.CSharp.Workspaces/4.8.0": { + "sha512": "3amm4tq4Lo8/BGvg9p3BJh3S9nKq2wqCXfS7138i69TUpo/bD+XvD0hNurpEBtcNZhi1FyutiomKJqVF39ugYA==", + "type": "package", + "path": "microsoft.codeanalysis.csharp.workspaces/4.8.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "ThirdPartyNotices.rtf", + "lib/net6.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll", + "lib/net6.0/Microsoft.CodeAnalysis.CSharp.Workspaces.pdb", + "lib/net6.0/Microsoft.CodeAnalysis.CSharp.Workspaces.xml", + "lib/net6.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net6.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll", + "lib/net7.0/Microsoft.CodeAnalysis.CSharp.Workspaces.pdb", + "lib/net7.0/Microsoft.CodeAnalysis.CSharp.Workspaces.xml", + "lib/net7.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.CSharp.Workspaces.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.CSharp.Workspaces.pdb", + "lib/netstandard2.0/Microsoft.CodeAnalysis.CSharp.Workspaces.xml", + "lib/netstandard2.0/cs/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/de/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/es/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/fr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/it/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/ja/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/ko/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/pl/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/pt-BR/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/ru/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/tr/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/zh-Hans/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "lib/netstandard2.0/zh-Hant/Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll", + "microsoft.codeanalysis.csharp.workspaces.4.8.0.nupkg.sha512", + "microsoft.codeanalysis.csharp.workspaces.nuspec" + ] + }, + "Microsoft.CodeAnalysis.Workspaces.Common/4.8.0": { + "sha512": "LXyV+MJKsKRu3FGJA3OmSk40OUIa/dQCFLOnm5X8MNcujx7hzGu8o+zjXlb/cy5xUdZK2UKYb9YaQ2E8m9QehQ==", + "type": "package", + "path": "microsoft.codeanalysis.workspaces.common/4.8.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "ThirdPartyNotices.rtf", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.dll", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.pdb", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.xml", + "lib/net6.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net6.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.dll", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.pdb", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.xml", + "lib/net7.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.Workspaces.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.Workspaces.pdb", + "lib/netstandard2.0/Microsoft.CodeAnalysis.Workspaces.xml", + "lib/netstandard2.0/cs/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/de/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/es/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/fr/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/it/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/ja/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/ko/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/pl/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/ru/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/tr/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "lib/netstandard2.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.resources.dll", + "microsoft.codeanalysis.workspaces.common.4.8.0.nupkg.sha512", + "microsoft.codeanalysis.workspaces.common.nuspec" + ] + }, + "Microsoft.CodeAnalysis.Workspaces.MSBuild/4.8.0": { + "sha512": "IEYreI82QZKklp54yPHxZNG9EKSK6nHEkeuf+0Asie9llgS1gp0V1hw7ODG+QyoB7MuAnNQHmeV1Per/ECpv6A==", + "type": "package", + "path": "microsoft.codeanalysis.workspaces.msbuild/4.8.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "ThirdPartyNotices.rtf", + "lib/net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe", + "lib/net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.pdb", + "lib/net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.xml", + "lib/net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll", + "lib/net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.pdb", + "lib/net472/Microsoft.CodeAnalysis.Workspaces.MSBuild.xml", + "lib/net472/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/it/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net472/zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.pdb", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.runtimeconfig.json", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.xml", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.pdb", + "lib/net6.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.xml", + "lib/net6.0/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/it/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net6.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.pdb", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.runtimeconfig.json", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.xml", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.dll", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.pdb", + "lib/net7.0/Microsoft.CodeAnalysis.Workspaces.MSBuild.xml", + "lib/net7.0/cs/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/de/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/es/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/fr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/it/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/ja/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/ko/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/pl/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/pt-BR/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/ru/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/tr/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/zh-Hans/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "lib/net7.0/zh-Hant/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.resources.dll", + "microsoft.codeanalysis.workspaces.msbuild.4.8.0.nupkg.sha512", + "microsoft.codeanalysis.workspaces.msbuild.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore/9.0.9": { + "sha512": "zkt5yQgnpWKX3rOxn+ZcV23Aj0296XCTqg4lx1hKY+wMXBgkn377UhBrY/A4H6kLpNT7wqZN98xCV0YHXu9VRA==", + "type": "package", + "path": "microsoft.entityframeworkcore/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "buildTransitive/net8.0/Microsoft.EntityFrameworkCore.props", + "lib/net8.0/Microsoft.EntityFrameworkCore.dll", + "lib/net8.0/Microsoft.EntityFrameworkCore.xml", + "microsoft.entityframeworkcore.9.0.9.nupkg.sha512", + "microsoft.entityframeworkcore.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Abstractions/9.0.9": { + "sha512": "QdM2k3Mnip2QsaxJbCI95dc2SajRMENdmaMhVKj4jPC5dmkoRcu3eEdvZAgDbd4bFVV1jtPGdHtXewtoBMlZqA==", + "type": "package", + "path": "microsoft.entityframeworkcore.abstractions/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "lib/net8.0/Microsoft.EntityFrameworkCore.Abstractions.dll", + "lib/net8.0/Microsoft.EntityFrameworkCore.Abstractions.xml", + "microsoft.entityframeworkcore.abstractions.9.0.9.nupkg.sha512", + "microsoft.entityframeworkcore.abstractions.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Analyzers/9.0.9": { + "sha512": "uiKeU/qR0YpaDUa4+g0rAjKCuwfq8YWZGcpPptnFWIr1K7dXQTm/15D2HDwwU4ln3Uf66krYybymuY58ua4hhw==", + "type": "package", + "path": "microsoft.entityframeworkcore.analyzers/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "analyzers/dotnet/cs/Microsoft.EntityFrameworkCore.Analyzers.dll", + "docs/PACKAGE.md", + "microsoft.entityframeworkcore.analyzers.9.0.9.nupkg.sha512", + "microsoft.entityframeworkcore.analyzers.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Design/9.0.9": { + "sha512": "cFxH70tohWe3ugCjLhZB01mR7WHpg5dEK6zHsbkDFfpLxWT+HoZQKgchTJgF4bPWBPTyrlYlqfPY212fFtmJjg==", + "type": "package", + "path": "microsoft.entityframeworkcore.design/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "build/net8.0/Microsoft.EntityFrameworkCore.Design.props", + "lib/net8.0/Microsoft.EntityFrameworkCore.Design.dll", + "lib/net8.0/Microsoft.EntityFrameworkCore.Design.xml", + "microsoft.entityframeworkcore.design.9.0.9.nupkg.sha512", + "microsoft.entityframeworkcore.design.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Relational/9.0.9": { + "sha512": "SonFU9a8x4jZIhIBtCw1hIE3QKjd4c7Y3mjptoh682dfQe7K9pUPGcEV/sk4n8AJdq4fkyJPCaOdYaObhae/Iw==", + "type": "package", + "path": "microsoft.entityframeworkcore.relational/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "PACKAGE.md", + "lib/net8.0/Microsoft.EntityFrameworkCore.Relational.dll", + "lib/net8.0/Microsoft.EntityFrameworkCore.Relational.xml", + "microsoft.entityframeworkcore.relational.9.0.9.nupkg.sha512", + "microsoft.entityframeworkcore.relational.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Tools/9.0.9": { + "sha512": "Q8n1PXXJApa1qX8HI3r/YuHoJ1HuLwjI2hLqaCV9K9pqQhGpi6Z38laOYwL2ElUOTWCxTKMDEMMYWfPlw6rwgg==", + "type": "package", + "path": "microsoft.entityframeworkcore.tools/9.0.9", + "hasTools": true, + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "docs/PACKAGE.md", + "microsoft.entityframeworkcore.tools.9.0.9.nupkg.sha512", + "microsoft.entityframeworkcore.tools.nuspec", + "tools/EntityFrameworkCore.PS2.psd1", + "tools/EntityFrameworkCore.PS2.psm1", + "tools/EntityFrameworkCore.psd1", + "tools/EntityFrameworkCore.psm1", + "tools/about_EntityFrameworkCore.help.txt", + "tools/init.ps1", + "tools/net472/any/ef.exe", + "tools/net472/win-arm64/ef.exe", + "tools/net472/win-x86/ef.exe", + "tools/netcoreapp2.0/any/ef.dll", + "tools/netcoreapp2.0/any/ef.runtimeconfig.json" + ] + }, + "Microsoft.Extensions.Caching.Abstractions/9.0.9": { + "sha512": "NgtRHOdPrAEacfjXLSrH/SRrSqGf6Vaa6d16mW2yoyJdg7AJr0BnBvxkv7PkCm/CHVyzojTK7Y+oUDEulqY1Qw==", + "type": "package", + "path": "microsoft.extensions.caching.abstractions/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Caching.Abstractions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Caching.Abstractions.targets", + "lib/net462/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net462/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.xml", + "microsoft.extensions.caching.abstractions.9.0.9.nupkg.sha512", + "microsoft.extensions.caching.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Caching.Memory/9.0.9": { + "sha512": "ln31BtsDsBQxykJgxuCtiUXWRET9FmqeEq0BpPIghkYtGpDDVs8ZcLHAjCCzbw6aGoLek4Z7JaDjSO/CjOD0iw==", + "type": "package", + "path": "microsoft.extensions.caching.memory/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Caching.Memory.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Caching.Memory.targets", + "lib/net462/Microsoft.Extensions.Caching.Memory.dll", + "lib/net462/Microsoft.Extensions.Caching.Memory.xml", + "lib/net8.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/net8.0/Microsoft.Extensions.Caching.Memory.xml", + "lib/net9.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/net9.0/Microsoft.Extensions.Caching.Memory.xml", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.xml", + "microsoft.extensions.caching.memory.9.0.9.nupkg.sha512", + "microsoft.extensions.caching.memory.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Configuration/9.0.5": { + "sha512": "uYXLg2Gt8KUH5nT3u+TBpg9VrRcN5+2zPmIjqEHR4kOoBwsbtMDncEJw9HiLvZqGgIo2TR4oraibAoy5hXn2bQ==", + "type": "package", + "path": "microsoft.extensions.configuration/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Configuration.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Configuration.targets", + "lib/net462/Microsoft.Extensions.Configuration.dll", + "lib/net462/Microsoft.Extensions.Configuration.xml", + "lib/net8.0/Microsoft.Extensions.Configuration.dll", + "lib/net8.0/Microsoft.Extensions.Configuration.xml", + "lib/net9.0/Microsoft.Extensions.Configuration.dll", + "lib/net9.0/Microsoft.Extensions.Configuration.xml", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.xml", + "microsoft.extensions.configuration.9.0.5.nupkg.sha512", + "microsoft.extensions.configuration.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Configuration.Abstractions/9.0.9": { + "sha512": "p5RKAY9POvs3axwA/AQRuJeM8AHuE8h4qbP1NxQeGm0ep46aXz1oCLAp/oOYxX1GsjStgdhHrN3XXLLXr0+b3w==", + "type": "package", + "path": "microsoft.extensions.configuration.abstractions/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Configuration.Abstractions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Configuration.Abstractions.targets", + "lib/net462/Microsoft.Extensions.Configuration.Abstractions.dll", + "lib/net462/Microsoft.Extensions.Configuration.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.Configuration.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.Configuration.Abstractions.xml", + "lib/net9.0/Microsoft.Extensions.Configuration.Abstractions.dll", + "lib/net9.0/Microsoft.Extensions.Configuration.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.xml", + "microsoft.extensions.configuration.abstractions.9.0.9.nupkg.sha512", + "microsoft.extensions.configuration.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Configuration.Binder/9.0.5": { + "sha512": "7pQ4Tkyofm8DFWFhqn9ZmG8qSAC2VitWleATj5qob9V9KtoxCVdwRtmiVl/ha3WAgjkEfW++JLWXox9MJwMgkg==", + "type": "package", + "path": "microsoft.extensions.configuration.binder/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/cs/Microsoft.Extensions.Configuration.Binder.SourceGeneration.dll", + "analyzers/dotnet/cs/cs/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/de/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/es/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/fr/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/it/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/ja/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/ko/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/pl/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/pt-BR/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/ru/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/tr/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/zh-Hans/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "analyzers/dotnet/cs/zh-Hant/Microsoft.Extensions.Configuration.Binder.SourceGeneration.resources.dll", + "buildTransitive/netstandard2.0/Microsoft.Extensions.Configuration.Binder.targets", + "lib/net462/Microsoft.Extensions.Configuration.Binder.dll", + "lib/net462/Microsoft.Extensions.Configuration.Binder.xml", + "lib/net8.0/Microsoft.Extensions.Configuration.Binder.dll", + "lib/net8.0/Microsoft.Extensions.Configuration.Binder.xml", + "lib/net9.0/Microsoft.Extensions.Configuration.Binder.dll", + "lib/net9.0/Microsoft.Extensions.Configuration.Binder.xml", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.xml", + "microsoft.extensions.configuration.binder.9.0.5.nupkg.sha512", + "microsoft.extensions.configuration.binder.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.DependencyInjection/9.0.9": { + "sha512": "zQV2WOSP+3z1EuK91ULxfGgo2Y75bTRnmJHp08+w/YXAyekZutX/qCd88/HOMNh35MDW9mJJJxPpMPS+1Rww8A==", + "type": "package", + "path": "microsoft.extensions.dependencyinjection/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.DependencyInjection.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.targets", + "lib/net462/Microsoft.Extensions.DependencyInjection.dll", + "lib/net462/Microsoft.Extensions.DependencyInjection.xml", + "lib/net8.0/Microsoft.Extensions.DependencyInjection.dll", + "lib/net8.0/Microsoft.Extensions.DependencyInjection.xml", + "lib/net9.0/Microsoft.Extensions.DependencyInjection.dll", + "lib/net9.0/Microsoft.Extensions.DependencyInjection.xml", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.xml", + "lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.dll", + "lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.xml", + "microsoft.extensions.dependencyinjection.9.0.9.nupkg.sha512", + "microsoft.extensions.dependencyinjection.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.9": { + "sha512": "/hymojfWbE9AlDOa0mczR44m00Jj+T3+HZO0ZnVTI032fVycI0ZbNOVFP6kqZMcXiLSYXzR2ilcwaRi6dzeGyA==", + "type": "package", + "path": "microsoft.extensions.dependencyinjection.abstractions/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.DependencyInjection.Abstractions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.Abstractions.targets", + "lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "microsoft.extensions.dependencyinjection.abstractions.9.0.9.nupkg.sha512", + "microsoft.extensions.dependencyinjection.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.DependencyModel/9.0.9": { + "sha512": "fNGvKct2De8ghm0Bpfq0iWthtzIWabgOTi+gJhNOPhNJIowXNEUE2eZNW/zNCzrHVA3PXg2yZ+3cWZndC2IqYA==", + "type": "package", + "path": "microsoft.extensions.dependencymodel/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.DependencyModel.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.DependencyModel.targets", + "lib/net462/Microsoft.Extensions.DependencyModel.dll", + "lib/net462/Microsoft.Extensions.DependencyModel.xml", + "lib/net8.0/Microsoft.Extensions.DependencyModel.dll", + "lib/net8.0/Microsoft.Extensions.DependencyModel.xml", + "lib/net9.0/Microsoft.Extensions.DependencyModel.dll", + "lib/net9.0/Microsoft.Extensions.DependencyModel.xml", + "lib/netstandard2.0/Microsoft.Extensions.DependencyModel.dll", + "lib/netstandard2.0/Microsoft.Extensions.DependencyModel.xml", + "microsoft.extensions.dependencymodel.9.0.9.nupkg.sha512", + "microsoft.extensions.dependencymodel.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Diagnostics/9.0.5": { + "sha512": "fRiUjmhm9e4vMp6WEO9MgWNxVtWSr4Pcgh1W4DyJIr8bRANlZz9JU7uicf7ShzMspDxo/9Ejo9zJ6qQZY0IhVw==", + "type": "package", + "path": "microsoft.extensions.diagnostics/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Diagnostics.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Diagnostics.targets", + "lib/net462/Microsoft.Extensions.Diagnostics.dll", + "lib/net462/Microsoft.Extensions.Diagnostics.xml", + "lib/net8.0/Microsoft.Extensions.Diagnostics.dll", + "lib/net8.0/Microsoft.Extensions.Diagnostics.xml", + "lib/net9.0/Microsoft.Extensions.Diagnostics.dll", + "lib/net9.0/Microsoft.Extensions.Diagnostics.xml", + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.dll", + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.xml", + "microsoft.extensions.diagnostics.9.0.5.nupkg.sha512", + "microsoft.extensions.diagnostics.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Diagnostics.Abstractions/9.0.5": { + "sha512": "6YfTcULCYREMTqtk+s3UiszsFV2xN2FXtxdQpurmQJY9Cp/QGiM4MTKfJKUo7AzdLuzjOKKMWjQITmvtK7AsUg==", + "type": "package", + "path": "microsoft.extensions.diagnostics.abstractions/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Diagnostics.Abstractions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Diagnostics.Abstractions.targets", + "lib/net462/Microsoft.Extensions.Diagnostics.Abstractions.dll", + "lib/net462/Microsoft.Extensions.Diagnostics.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.Diagnostics.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.Diagnostics.Abstractions.xml", + "lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll", + "lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.Abstractions.xml", + "microsoft.extensions.diagnostics.abstractions.9.0.5.nupkg.sha512", + "microsoft.extensions.diagnostics.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Http/9.0.5": { + "sha512": "6vbo3XjyEc+w/kv/Dkfv9NA7iSdIdX5dlU9Shk3wJJ0fiZpCVzVW5FJtNoIePX5hS0ENNpHPClq/qtq06yM4FQ==", + "type": "package", + "path": "microsoft.extensions.http/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Http.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Http.targets", + "lib/net462/Microsoft.Extensions.Http.dll", + "lib/net462/Microsoft.Extensions.Http.xml", + "lib/net8.0/Microsoft.Extensions.Http.dll", + "lib/net8.0/Microsoft.Extensions.Http.xml", + "lib/net9.0/Microsoft.Extensions.Http.dll", + "lib/net9.0/Microsoft.Extensions.Http.xml", + "lib/netstandard2.0/Microsoft.Extensions.Http.dll", + "lib/netstandard2.0/Microsoft.Extensions.Http.xml", + "microsoft.extensions.http.9.0.5.nupkg.sha512", + "microsoft.extensions.http.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Logging/9.0.9": { + "sha512": "MaCB0Y9hNDs4YLu3HCJbo199WnJT8xSgajG1JYGANz9FkseQ5f3v/llu3HxLI6mjDlu7pa7ps9BLPWjKzsAAzQ==", + "type": "package", + "path": "microsoft.extensions.logging/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Logging.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Logging.targets", + "lib/net462/Microsoft.Extensions.Logging.dll", + "lib/net462/Microsoft.Extensions.Logging.xml", + "lib/net8.0/Microsoft.Extensions.Logging.dll", + "lib/net8.0/Microsoft.Extensions.Logging.xml", + "lib/net9.0/Microsoft.Extensions.Logging.dll", + "lib/net9.0/Microsoft.Extensions.Logging.xml", + "lib/netstandard2.0/Microsoft.Extensions.Logging.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.xml", + "lib/netstandard2.1/Microsoft.Extensions.Logging.dll", + "lib/netstandard2.1/Microsoft.Extensions.Logging.xml", + "microsoft.extensions.logging.9.0.9.nupkg.sha512", + "microsoft.extensions.logging.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Logging.Abstractions/9.0.9": { + "sha512": "FEgpSF+Z9StMvrsSViaybOBwR0f0ZZxDm8xV5cSOFiXN/t+ys+rwAlTd/6yG7Ld1gfppgvLcMasZry3GsI9lGA==", + "type": "package", + "path": "microsoft.extensions.logging.abstractions/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn3.11/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn3.11/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn4.0/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "buildTransitive/net461/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/net462/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.targets", + "lib/net462/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net462/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.xml", + "microsoft.extensions.logging.abstractions.9.0.9.nupkg.sha512", + "microsoft.extensions.logging.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Options/9.0.9": { + "sha512": "loxGGHE1FC2AefwPHzrjPq7X92LQm64qnU/whKfo6oWaceewPUVYQJBJs3S3E2qlWwnCpeZ+dGCPTX+5dgVAuQ==", + "type": "package", + "path": "microsoft.extensions.options/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn4.4/cs/Microsoft.Extensions.Options.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "buildTransitive/net461/Microsoft.Extensions.Options.targets", + "buildTransitive/net462/Microsoft.Extensions.Options.targets", + "buildTransitive/net8.0/Microsoft.Extensions.Options.targets", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Options.targets", + "buildTransitive/netstandard2.0/Microsoft.Extensions.Options.targets", + "lib/net462/Microsoft.Extensions.Options.dll", + "lib/net462/Microsoft.Extensions.Options.xml", + "lib/net8.0/Microsoft.Extensions.Options.dll", + "lib/net8.0/Microsoft.Extensions.Options.xml", + "lib/net9.0/Microsoft.Extensions.Options.dll", + "lib/net9.0/Microsoft.Extensions.Options.xml", + "lib/netstandard2.0/Microsoft.Extensions.Options.dll", + "lib/netstandard2.0/Microsoft.Extensions.Options.xml", + "lib/netstandard2.1/Microsoft.Extensions.Options.dll", + "lib/netstandard2.1/Microsoft.Extensions.Options.xml", + "microsoft.extensions.options.9.0.9.nupkg.sha512", + "microsoft.extensions.options.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Options.ConfigurationExtensions/9.0.5": { + "sha512": "CJbAVdovKPFh2FoKxesu20odRVSbL/vtvzzObnG+5u38sOfzRS2Ncy25id0TjYUGQzMhNnJUHgTUzTMDl/3c9g==", + "type": "package", + "path": "microsoft.extensions.options.configurationextensions/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Options.ConfigurationExtensions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Options.ConfigurationExtensions.targets", + "lib/net462/Microsoft.Extensions.Options.ConfigurationExtensions.dll", + "lib/net462/Microsoft.Extensions.Options.ConfigurationExtensions.xml", + "lib/net8.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll", + "lib/net8.0/Microsoft.Extensions.Options.ConfigurationExtensions.xml", + "lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll", + "lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Options.ConfigurationExtensions.xml", + "microsoft.extensions.options.configurationextensions.9.0.5.nupkg.sha512", + "microsoft.extensions.options.configurationextensions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Primitives/9.0.9": { + "sha512": "z4pyMePOrl733ltTowbN565PxBw1oAr8IHmIXNDiDqd22nFpYltX9KhrNC/qBWAG1/Zx5MHX+cOYhWJQYCO/iw==", + "type": "package", + "path": "microsoft.extensions.primitives/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Primitives.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Primitives.targets", + "lib/net462/Microsoft.Extensions.Primitives.dll", + "lib/net462/Microsoft.Extensions.Primitives.xml", + "lib/net8.0/Microsoft.Extensions.Primitives.dll", + "lib/net8.0/Microsoft.Extensions.Primitives.xml", + "lib/net9.0/Microsoft.Extensions.Primitives.dll", + "lib/net9.0/Microsoft.Extensions.Primitives.xml", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.xml", + "microsoft.extensions.primitives.9.0.9.nupkg.sha512", + "microsoft.extensions.primitives.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.IdentityModel.Abstractions/8.17.0": { + "sha512": "6NrxQGcZg6IunkN8K2F0UVMavNpfCjbjjjON7PYcL8FwI8aULKUreiHsRX/yaA8j3XsTJnQKUYpoQk5gBjULZw==", + "type": "package", + "path": "microsoft.identitymodel.abstractions/8.17.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/net10.0/Microsoft.IdentityModel.Abstractions.dll", + "lib/net10.0/Microsoft.IdentityModel.Abstractions.xml", + "lib/net462/Microsoft.IdentityModel.Abstractions.dll", + "lib/net462/Microsoft.IdentityModel.Abstractions.xml", + "lib/net472/Microsoft.IdentityModel.Abstractions.dll", + "lib/net472/Microsoft.IdentityModel.Abstractions.xml", + "lib/net6.0/Microsoft.IdentityModel.Abstractions.dll", + "lib/net6.0/Microsoft.IdentityModel.Abstractions.xml", + "lib/net8.0/Microsoft.IdentityModel.Abstractions.dll", + "lib/net8.0/Microsoft.IdentityModel.Abstractions.xml", + "lib/net9.0/Microsoft.IdentityModel.Abstractions.dll", + "lib/net9.0/Microsoft.IdentityModel.Abstractions.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Abstractions.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Abstractions.xml", + "microsoft.identitymodel.abstractions.8.17.0.nupkg.sha512", + "microsoft.identitymodel.abstractions.nuspec" + ] + }, + "Microsoft.IdentityModel.JsonWebTokens/8.17.0": { + "sha512": "JbFZ3OVwtvqcqgBL0cIkhRYbIP7u9GIUYLOgbNqLWtBtZY8tGDpdGyXMzUVX0gVHq1ovuHsKZrkVv+ziHEnBHw==", + "type": "package", + "path": "microsoft.identitymodel.jsonwebtokens/8.17.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/net10.0/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net10.0/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/net462/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net462/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/net472/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net472/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/net6.0/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net6.0/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/net8.0/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net8.0/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/net9.0/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net9.0/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.JsonWebTokens.xml", + "microsoft.identitymodel.jsonwebtokens.8.17.0.nupkg.sha512", + "microsoft.identitymodel.jsonwebtokens.nuspec" + ] + }, + "Microsoft.IdentityModel.Logging/8.17.0": { + "sha512": "w1vjfri0BWqW7RkSZY3ZsqekNfIJJg5BQSFs2j+a+pCXOVrkezmJcn74pT3djwjXJh71577C6wJQgNc2UPz30w==", + "type": "package", + "path": "microsoft.identitymodel.logging/8.17.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/net10.0/Microsoft.IdentityModel.Logging.dll", + "lib/net10.0/Microsoft.IdentityModel.Logging.xml", + "lib/net462/Microsoft.IdentityModel.Logging.dll", + "lib/net462/Microsoft.IdentityModel.Logging.xml", + "lib/net472/Microsoft.IdentityModel.Logging.dll", + "lib/net472/Microsoft.IdentityModel.Logging.xml", + "lib/net6.0/Microsoft.IdentityModel.Logging.dll", + "lib/net6.0/Microsoft.IdentityModel.Logging.xml", + "lib/net8.0/Microsoft.IdentityModel.Logging.dll", + "lib/net8.0/Microsoft.IdentityModel.Logging.xml", + "lib/net9.0/Microsoft.IdentityModel.Logging.dll", + "lib/net9.0/Microsoft.IdentityModel.Logging.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Logging.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Logging.xml", + "microsoft.identitymodel.logging.8.17.0.nupkg.sha512", + "microsoft.identitymodel.logging.nuspec" + ] + }, + "Microsoft.IdentityModel.Tokens/8.17.0": { + "sha512": "teaW35URIV2x78Tzk+dVJiC4M62/9mQoSEoDjDGoEZmcQa3H2rE+XQpm9Tmdo9KK1Lcrnve4zoyLavl69kCFGg==", + "type": "package", + "path": "microsoft.identitymodel.tokens/8.17.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/net10.0/Microsoft.IdentityModel.Tokens.dll", + "lib/net10.0/Microsoft.IdentityModel.Tokens.xml", + "lib/net462/Microsoft.IdentityModel.Tokens.dll", + "lib/net462/Microsoft.IdentityModel.Tokens.xml", + "lib/net472/Microsoft.IdentityModel.Tokens.dll", + "lib/net472/Microsoft.IdentityModel.Tokens.xml", + "lib/net6.0/Microsoft.IdentityModel.Tokens.dll", + "lib/net6.0/Microsoft.IdentityModel.Tokens.xml", + "lib/net8.0/Microsoft.IdentityModel.Tokens.dll", + "lib/net8.0/Microsoft.IdentityModel.Tokens.xml", + "lib/net9.0/Microsoft.IdentityModel.Tokens.dll", + "lib/net9.0/Microsoft.IdentityModel.Tokens.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.xml", + "microsoft.identitymodel.tokens.8.17.0.nupkg.sha512", + "microsoft.identitymodel.tokens.nuspec" + ] + }, + "Microsoft.OpenApi/1.6.25": { + "sha512": "ZahSqNGtNV7N0JBYS/IYXPkLVexL/AZFxo6pqxv6A7Uli7Q7zfitNjkaqIcsV73Ukzxi4IlJdyDgcQiMXiH8cw==", + "type": "package", + "path": "microsoft.openapi/1.6.25", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/netstandard2.0/Microsoft.OpenApi.dll", + "lib/netstandard2.0/Microsoft.OpenApi.pdb", + "lib/netstandard2.0/Microsoft.OpenApi.xml", + "microsoft.openapi.1.6.25.nupkg.sha512", + "microsoft.openapi.nuspec" + ] + }, + "Mono.TextTemplating/3.0.0": { + "sha512": "YqueG52R/Xej4VVbKuRIodjiAhV0HR/XVbLbNrJhCZnzjnSjgMJ/dCdV0akQQxavX6hp/LC6rqLGLcXeQYU7XA==", + "type": "package", + "path": "mono.texttemplating/3.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.txt/LICENSE", + "buildTransitive/Mono.TextTemplating.targets", + "lib/net472/Mono.TextTemplating.dll", + "lib/net6.0/Mono.TextTemplating.dll", + "lib/netstandard2.0/Mono.TextTemplating.dll", + "mono.texttemplating.3.0.0.nupkg.sha512", + "mono.texttemplating.nuspec", + "readme.md" + ] + }, + "Newtonsoft.Json/13.0.4": { + "sha512": "pdgNNMai3zv51W5aq268sujXUyx7SNdE2bj1wZcWjAQrKMFZV260lbqYop1d2GM67JI1huLRwxo9ZqnfF/lC6A==", + "type": "package", + "path": "newtonsoft.json/13.0.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.md", + "README.md", + "lib/net20/Newtonsoft.Json.dll", + "lib/net20/Newtonsoft.Json.xml", + "lib/net35/Newtonsoft.Json.dll", + "lib/net35/Newtonsoft.Json.xml", + "lib/net40/Newtonsoft.Json.dll", + "lib/net40/Newtonsoft.Json.xml", + "lib/net45/Newtonsoft.Json.dll", + "lib/net45/Newtonsoft.Json.xml", + "lib/net6.0/Newtonsoft.Json.dll", + "lib/net6.0/Newtonsoft.Json.xml", + "lib/netstandard1.0/Newtonsoft.Json.dll", + "lib/netstandard1.0/Newtonsoft.Json.xml", + "lib/netstandard1.3/Newtonsoft.Json.dll", + "lib/netstandard1.3/Newtonsoft.Json.xml", + "lib/netstandard2.0/Newtonsoft.Json.dll", + "lib/netstandard2.0/Newtonsoft.Json.xml", + "newtonsoft.json.13.0.4.nupkg.sha512", + "newtonsoft.json.nuspec", + "packageIcon.png" + ] + }, + "Npgsql/9.0.3": { + "sha512": "tPvY61CxOAWxNsKLEBg+oR646X4Bc8UmyQ/tJszL/7mEmIXQnnBhVJZrZEEUv0Bstu0mEsHZD5At3EO8zQRAYw==", + "type": "package", + "path": "npgsql/9.0.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/net6.0/Npgsql.dll", + "lib/net6.0/Npgsql.xml", + "lib/net8.0/Npgsql.dll", + "lib/net8.0/Npgsql.xml", + "npgsql.9.0.3.nupkg.sha512", + "npgsql.nuspec", + "postgresql.png" + ] + }, + "Npgsql.EntityFrameworkCore.PostgreSQL/9.0.4": { + "sha512": "mw5vcY2IEc7L+IeGrxpp/J5OSnCcjkjAgJYCm/eD52wpZze8zsSifdqV7zXslSMmfJG2iIUGZyo3KuDtEFKwMQ==", + "type": "package", + "path": "npgsql.entityframeworkcore.postgresql/9.0.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/net8.0/Npgsql.EntityFrameworkCore.PostgreSQL.dll", + "lib/net8.0/Npgsql.EntityFrameworkCore.PostgreSQL.xml", + "npgsql.entityframeworkcore.postgresql.9.0.4.nupkg.sha512", + "npgsql.entityframeworkcore.postgresql.nuspec", + "postgresql.png" + ] + }, + "Polly/8.6.4": { + "sha512": "uuBsDoBw0oYrMe3uTWRjkT2sIkKh+ZZnnDrLb4Z+QANfeA4+7FJacx6E8CY5GAxXRoSgFrvUADEAQ7DPF6fGiw==", + "type": "package", + "path": "polly/8.6.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE", + "lib/net462/Polly.dll", + "lib/net462/Polly.pdb", + "lib/net462/Polly.xml", + "lib/net472/Polly.dll", + "lib/net472/Polly.pdb", + "lib/net472/Polly.xml", + "lib/net6.0/Polly.dll", + "lib/net6.0/Polly.pdb", + "lib/net6.0/Polly.xml", + "lib/netstandard2.0/Polly.dll", + "lib/netstandard2.0/Polly.pdb", + "lib/netstandard2.0/Polly.xml", + "package-icon.png", + "package-readme.md", + "polly.8.6.4.nupkg.sha512", + "polly.nuspec" + ] + }, + "Polly.Core/8.6.4": { + "sha512": "4AWqYnQ2TME0E+Mzovt1Uu+VyvpR84ymUldMcPw7Mbj799Phaag14CKrMtlJGx5jsvYP+S3oR1QmysgmXoD5cw==", + "type": "package", + "path": "polly.core/8.6.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE", + "lib/net462/Polly.Core.dll", + "lib/net462/Polly.Core.pdb", + "lib/net462/Polly.Core.xml", + "lib/net472/Polly.Core.dll", + "lib/net472/Polly.Core.pdb", + "lib/net472/Polly.Core.xml", + "lib/net6.0/Polly.Core.dll", + "lib/net6.0/Polly.Core.pdb", + "lib/net6.0/Polly.Core.xml", + "lib/net8.0/Polly.Core.dll", + "lib/net8.0/Polly.Core.pdb", + "lib/net8.0/Polly.Core.xml", + "lib/netstandard2.0/Polly.Core.dll", + "lib/netstandard2.0/Polly.Core.pdb", + "lib/netstandard2.0/Polly.Core.xml", + "package-icon.png", + "package-readme.md", + "polly.core.8.6.4.nupkg.sha512", + "polly.core.nuspec" + ] + }, + "Swashbuckle.AspNetCore.Swagger/9.0.5": { + "sha512": "mdjT7BRsB5T2SuG4UieFgTqTLPugg4RhnZ6m2K1uj8034tcXy6XDYjNPFCL66w2QfdWkKzhaHiJraMOcMRrHUw==", + "type": "package", + "path": "swashbuckle.aspnetcore.swagger/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net8.0/Swashbuckle.AspNetCore.Swagger.dll", + "lib/net8.0/Swashbuckle.AspNetCore.Swagger.pdb", + "lib/net8.0/Swashbuckle.AspNetCore.Swagger.xml", + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.dll", + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.pdb", + "lib/net9.0/Swashbuckle.AspNetCore.Swagger.xml", + "package-readme.md", + "swashbuckle.aspnetcore.swagger.9.0.5.nupkg.sha512", + "swashbuckle.aspnetcore.swagger.nuspec" + ] + }, + "Swashbuckle.AspNetCore.SwaggerGen/9.0.5": { + "sha512": "Fdeaanu9uYIQl8uDFLwfHFyiCh04NDZNJq55avdfc0DeeHB/krjW6JUZ0AMAnNRypgRrsF3Lwem511chAU0o+g==", + "type": "package", + "path": "swashbuckle.aspnetcore.swaggergen/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerGen.dll", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerGen.pdb", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerGen.xml", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.dll", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.pdb", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerGen.xml", + "package-readme.md", + "swashbuckle.aspnetcore.swaggergen.9.0.5.nupkg.sha512", + "swashbuckle.aspnetcore.swaggergen.nuspec" + ] + }, + "Swashbuckle.AspNetCore.SwaggerUI/9.0.5": { + "sha512": "Em1jGT2AX7/fP9LAU0ELUMVDtr6IPTgystcIg8AAEV59CfUtNkeNyirkX7fSxg0qX3R4NAQcsx9FwZIfHItiAQ==", + "type": "package", + "path": "swashbuckle.aspnetcore.swaggerui/9.0.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerUI.dll", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerUI.pdb", + "lib/net8.0/Swashbuckle.AspNetCore.SwaggerUI.xml", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.dll", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.pdb", + "lib/net9.0/Swashbuckle.AspNetCore.SwaggerUI.xml", + "package-readme.md", + "swashbuckle.aspnetcore.swaggerui.9.0.5.nupkg.sha512", + "swashbuckle.aspnetcore.swaggerui.nuspec" + ] + }, + "System.CodeDom/6.0.0": { + "sha512": "CPc6tWO1LAer3IzfZufDBRL+UZQcj5uS207NHALQzP84Vp/z6wF0Aa0YZImOQY8iStY0A2zI/e3ihKNPfUm8XA==", + "type": "package", + "path": "system.codedom/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.CodeDom.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.CodeDom.dll", + "lib/net461/System.CodeDom.xml", + "lib/net6.0/System.CodeDom.dll", + "lib/net6.0/System.CodeDom.xml", + "lib/netstandard2.0/System.CodeDom.dll", + "lib/netstandard2.0/System.CodeDom.xml", + "system.codedom.6.0.0.nupkg.sha512", + "system.codedom.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Collections.Immutable/7.0.0": { + "sha512": "dQPcs0U1IKnBdRDBkrCTi1FoajSTBzLcVTpjO4MBCMC7f4pDOIPzgBoX8JjG7X6uZRJ8EBxsi8+DR1JuwjnzOQ==", + "type": "package", + "path": "system.collections.immutable/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "README.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Collections.Immutable.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Collections.Immutable.targets", + "lib/net462/System.Collections.Immutable.dll", + "lib/net462/System.Collections.Immutable.xml", + "lib/net6.0/System.Collections.Immutable.dll", + "lib/net6.0/System.Collections.Immutable.xml", + "lib/net7.0/System.Collections.Immutable.dll", + "lib/net7.0/System.Collections.Immutable.xml", + "lib/netstandard2.0/System.Collections.Immutable.dll", + "lib/netstandard2.0/System.Collections.Immutable.xml", + "system.collections.immutable.7.0.0.nupkg.sha512", + "system.collections.immutable.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Composition/7.0.0": { + "sha512": "tRwgcAkDd85O8Aq6zHDANzQaq380cek9lbMg5Qma46u5BZXq/G+XvIYmu+UI+BIIZ9zssXLYrkTykEqxxvhcmg==", + "type": "package", + "path": "system.composition/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Composition.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Composition.targets", + "lib/net461/_._", + "lib/netcoreapp2.0/_._", + "lib/netstandard2.0/_._", + "system.composition.7.0.0.nupkg.sha512", + "system.composition.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Composition.AttributedModel/7.0.0": { + "sha512": "2QzClqjElKxgI1jK1Jztnq44/8DmSuTSGGahXqQ4TdEV0h9s2KikQZIgcEqVzR7OuWDFPGLHIprBJGQEPr8fAQ==", + "type": "package", + "path": "system.composition.attributedmodel/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Composition.AttributedModel.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Composition.AttributedModel.targets", + "lib/net462/System.Composition.AttributedModel.dll", + "lib/net462/System.Composition.AttributedModel.xml", + "lib/net6.0/System.Composition.AttributedModel.dll", + "lib/net6.0/System.Composition.AttributedModel.xml", + "lib/net7.0/System.Composition.AttributedModel.dll", + "lib/net7.0/System.Composition.AttributedModel.xml", + "lib/netstandard2.0/System.Composition.AttributedModel.dll", + "lib/netstandard2.0/System.Composition.AttributedModel.xml", + "system.composition.attributedmodel.7.0.0.nupkg.sha512", + "system.composition.attributedmodel.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Composition.Convention/7.0.0": { + "sha512": "IMhTlpCs4HmlD8B+J8/kWfwX7vrBBOs6xyjSTzBlYSs7W4OET4tlkR/Sg9NG8jkdJH9Mymq0qGdYS1VPqRTBnQ==", + "type": "package", + "path": "system.composition.convention/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Composition.Convention.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Composition.Convention.targets", + "lib/net462/System.Composition.Convention.dll", + "lib/net462/System.Composition.Convention.xml", + "lib/net6.0/System.Composition.Convention.dll", + "lib/net6.0/System.Composition.Convention.xml", + "lib/net7.0/System.Composition.Convention.dll", + "lib/net7.0/System.Composition.Convention.xml", + "lib/netstandard2.0/System.Composition.Convention.dll", + "lib/netstandard2.0/System.Composition.Convention.xml", + "system.composition.convention.7.0.0.nupkg.sha512", + "system.composition.convention.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Composition.Hosting/7.0.0": { + "sha512": "eB6gwN9S+54jCTBJ5bpwMOVerKeUfGGTYCzz3QgDr1P55Gg/Wb27ShfPIhLMjmZ3MoAKu8uUSv6fcCdYJTN7Bg==", + "type": "package", + "path": "system.composition.hosting/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Composition.Hosting.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Composition.Hosting.targets", + "lib/net462/System.Composition.Hosting.dll", + "lib/net462/System.Composition.Hosting.xml", + "lib/net6.0/System.Composition.Hosting.dll", + "lib/net6.0/System.Composition.Hosting.xml", + "lib/net7.0/System.Composition.Hosting.dll", + "lib/net7.0/System.Composition.Hosting.xml", + "lib/netstandard2.0/System.Composition.Hosting.dll", + "lib/netstandard2.0/System.Composition.Hosting.xml", + "system.composition.hosting.7.0.0.nupkg.sha512", + "system.composition.hosting.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Composition.Runtime/7.0.0": { + "sha512": "aZJ1Zr5Txe925rbo4742XifEyW0MIni1eiUebmcrP3HwLXZ3IbXUj4MFMUH/RmnJOAQiS401leg/2Sz1MkApDw==", + "type": "package", + "path": "system.composition.runtime/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Composition.Runtime.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Composition.Runtime.targets", + "lib/net462/System.Composition.Runtime.dll", + "lib/net462/System.Composition.Runtime.xml", + "lib/net6.0/System.Composition.Runtime.dll", + "lib/net6.0/System.Composition.Runtime.xml", + "lib/net7.0/System.Composition.Runtime.dll", + "lib/net7.0/System.Composition.Runtime.xml", + "lib/netstandard2.0/System.Composition.Runtime.dll", + "lib/netstandard2.0/System.Composition.Runtime.xml", + "system.composition.runtime.7.0.0.nupkg.sha512", + "system.composition.runtime.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Composition.TypedParts/7.0.0": { + "sha512": "ZK0KNPfbtxVceTwh+oHNGUOYV2WNOHReX2AXipuvkURC7s/jPwoWfsu3SnDBDgofqbiWr96geofdQ2erm/KTHg==", + "type": "package", + "path": "system.composition.typedparts/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Composition.TypedParts.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Composition.TypedParts.targets", + "lib/net462/System.Composition.TypedParts.dll", + "lib/net462/System.Composition.TypedParts.xml", + "lib/net6.0/System.Composition.TypedParts.dll", + "lib/net6.0/System.Composition.TypedParts.xml", + "lib/net7.0/System.Composition.TypedParts.dll", + "lib/net7.0/System.Composition.TypedParts.xml", + "lib/netstandard2.0/System.Composition.TypedParts.dll", + "lib/netstandard2.0/System.Composition.TypedParts.xml", + "system.composition.typedparts.7.0.0.nupkg.sha512", + "system.composition.typedparts.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.IdentityModel.Tokens.Jwt/8.17.0": { + "sha512": "nKikRYheDeSaXA3wGr2otwaiRFygBa25m+hc7MEomZVIEWZvKVqd8wgP9yn+8QpLRGgw//dUs4LErGx9gtVmAA==", + "type": "package", + "path": "system.identitymodel.tokens.jwt/8.17.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "README.md", + "lib/net10.0/System.IdentityModel.Tokens.Jwt.dll", + "lib/net10.0/System.IdentityModel.Tokens.Jwt.xml", + "lib/net462/System.IdentityModel.Tokens.Jwt.dll", + "lib/net462/System.IdentityModel.Tokens.Jwt.xml", + "lib/net472/System.IdentityModel.Tokens.Jwt.dll", + "lib/net472/System.IdentityModel.Tokens.Jwt.xml", + "lib/net6.0/System.IdentityModel.Tokens.Jwt.dll", + "lib/net6.0/System.IdentityModel.Tokens.Jwt.xml", + "lib/net8.0/System.IdentityModel.Tokens.Jwt.dll", + "lib/net8.0/System.IdentityModel.Tokens.Jwt.xml", + "lib/net9.0/System.IdentityModel.Tokens.Jwt.dll", + "lib/net9.0/System.IdentityModel.Tokens.Jwt.xml", + "lib/netstandard2.0/System.IdentityModel.Tokens.Jwt.dll", + "lib/netstandard2.0/System.IdentityModel.Tokens.Jwt.xml", + "system.identitymodel.tokens.jwt.8.17.0.nupkg.sha512", + "system.identitymodel.tokens.jwt.nuspec" + ] + }, + "System.IO.Pipelines/7.0.0": { + "sha512": "jRn6JYnNPW6xgQazROBLSfpdoczRw694vO5kKvMcNnpXuolEixUyw6IBuBs2Y2mlSX/LdLvyyWmfXhaI3ND1Yg==", + "type": "package", + "path": "system.io.pipelines/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.IO.Pipelines.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.IO.Pipelines.targets", + "lib/net462/System.IO.Pipelines.dll", + "lib/net462/System.IO.Pipelines.xml", + "lib/net6.0/System.IO.Pipelines.dll", + "lib/net6.0/System.IO.Pipelines.xml", + "lib/net7.0/System.IO.Pipelines.dll", + "lib/net7.0/System.IO.Pipelines.xml", + "lib/netstandard2.0/System.IO.Pipelines.dll", + "lib/netstandard2.0/System.IO.Pipelines.xml", + "system.io.pipelines.7.0.0.nupkg.sha512", + "system.io.pipelines.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Reflection.Metadata/7.0.0": { + "sha512": "MclTG61lsD9sYdpNz9xsKBzjsmsfCtcMZYXz/IUr2zlhaTaABonlr1ESeompTgM+Xk+IwtGYU7/voh3YWB/fWw==", + "type": "package", + "path": "system.reflection.metadata/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "README.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Reflection.Metadata.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Reflection.Metadata.targets", + "lib/net462/System.Reflection.Metadata.dll", + "lib/net462/System.Reflection.Metadata.xml", + "lib/net6.0/System.Reflection.Metadata.dll", + "lib/net6.0/System.Reflection.Metadata.xml", + "lib/net7.0/System.Reflection.Metadata.dll", + "lib/net7.0/System.Reflection.Metadata.xml", + "lib/netstandard2.0/System.Reflection.Metadata.dll", + "lib/netstandard2.0/System.Reflection.Metadata.xml", + "system.reflection.metadata.7.0.0.nupkg.sha512", + "system.reflection.metadata.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "sha512": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==", + "type": "package", + "path": "system.runtime.compilerservices.unsafe/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net461/System.Runtime.CompilerServices.Unsafe.xml", + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml", + "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512", + "system.runtime.compilerservices.unsafe.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Text.Json/9.0.9": { + "sha512": "NEnpppwq67fRz/OvQRxsEMgetDJsxlxpEsAFO/4PZYbAyAMd4Ol6KS7phc8uDoKPsnbdzRLKobpX303uQwCqdg==", + "type": "package", + "path": "system.text.json/9.0.9", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn3.11/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn3.11/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.0/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/System.Text.Json.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/System.Text.Json.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/System.Text.Json.SourceGeneration.resources.dll", + "buildTransitive/net461/System.Text.Json.targets", + "buildTransitive/net462/System.Text.Json.targets", + "buildTransitive/net8.0/System.Text.Json.targets", + "buildTransitive/netcoreapp2.0/System.Text.Json.targets", + "buildTransitive/netstandard2.0/System.Text.Json.targets", + "lib/net462/System.Text.Json.dll", + "lib/net462/System.Text.Json.xml", + "lib/net8.0/System.Text.Json.dll", + "lib/net8.0/System.Text.Json.xml", + "lib/net9.0/System.Text.Json.dll", + "lib/net9.0/System.Text.Json.xml", + "lib/netstandard2.0/System.Text.Json.dll", + "lib/netstandard2.0/System.Text.Json.xml", + "system.text.json.9.0.9.nupkg.sha512", + "system.text.json.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Threading.Channels/7.0.0": { + "sha512": "qmeeYNROMsONF6ndEZcIQ+VxR4Q/TX/7uIVLJqtwIWL7dDWeh0l1UIqgo4wYyjG//5lUNhwkLDSFl+pAWO6oiA==", + "type": "package", + "path": "system.threading.channels/7.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/System.Threading.Channels.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/System.Threading.Channels.targets", + "lib/net462/System.Threading.Channels.dll", + "lib/net462/System.Threading.Channels.xml", + "lib/net6.0/System.Threading.Channels.dll", + "lib/net6.0/System.Threading.Channels.xml", + "lib/net7.0/System.Threading.Channels.dll", + "lib/net7.0/System.Threading.Channels.xml", + "lib/netstandard2.0/System.Threading.Channels.dll", + "lib/netstandard2.0/System.Threading.Channels.xml", + "lib/netstandard2.1/System.Threading.Channels.dll", + "lib/netstandard2.1/System.Threading.Channels.xml", + "system.threading.channels.7.0.0.nupkg.sha512", + "system.threading.channels.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Core.Abstraction/1.0.0": { + "type": "project", + "path": "../Core/Abstraction/Core.Abstraction.csproj", + "msbuildProject": "../Core/Abstraction/Core.Abstraction.csproj" + }, + "Core.Domain/1.0.0": { + "type": "project", + "path": "../Core/Domain/Core.Domain.csproj", + "msbuildProject": "../Core/Domain/Core.Domain.csproj" + }, + "Core.Services/1.0.0": { + "type": "project", + "path": "../Core/Services/Core.Services.csproj", + "msbuildProject": "../Core/Services/Core.Services.csproj" + }, + "Infrastructure.Persistence/1.0.0": { + "type": "project", + "path": "../Infrastructure/Persistence/Infrastructure.Persistence.csproj", + "msbuildProject": "../Infrastructure/Persistence/Infrastructure.Persistence.csproj" + }, + "Infrastructure.Presentation/1.0.0": { + "type": "project", + "path": "../Infrastructure/Presentation/Infrastructure.Presentation.csproj", + "msbuildProject": "../Infrastructure/Presentation/Infrastructure.Presentation.csproj" + }, + "Share/1.0.0": { + "type": "project", + "path": "../Share/Share.csproj", + "msbuildProject": "../Share/Share.csproj" + } + }, + "projectFileDependencyGroups": { + "net9.0": [ + "Infrastructure.Persistence >= 1.0.0", + "Infrastructure.Presentation >= 1.0.0", + "Microsoft.AspNetCore.OpenApi >= 9.0.2", + "Microsoft.EntityFrameworkCore.Tools >= 9.0.9", + "Microsoft.Extensions.DependencyInjection >= 9.0.9", + "Swashbuckle.AspNetCore.SwaggerGen >= 9.0.5", + "Swashbuckle.AspNetCore.SwaggerUI >= 9.0.5", + "System.IdentityModel.Tokens.Jwt >= 8.17.0", + "dotenv.net >= 4.0.2" + ] + }, + "packageFolders": { + "/Users/rebuy/.nuget/packages/": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/Codience.API.csproj", + "projectName": "Codience.API", + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/Codience.API.csproj", + "packagesPath": "/Users/rebuy/.nuget/packages/", + "outputPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/rebuy/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "net9.0" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "projectReferences": { + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Persistence/Infrastructure.Persistence.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Persistence/Infrastructure.Persistence.csproj" + }, + "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Presentation/Infrastructure.Presentation.csproj": { + "projectPath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/Infrastructure/Presentation/Infrastructure.Presentation.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + }, + "SdkAnalysisLevel": "9.0.300" + }, + "frameworks": { + "net9.0": { + "targetAlias": "net9.0", + "dependencies": { + "Microsoft.AspNetCore.OpenApi": { + "target": "Package", + "version": "[9.0.2, )" + }, + "Microsoft.EntityFrameworkCore.Tools": { + "include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive", + "suppressParent": "All", + "target": "Package", + "version": "[9.0.9, )" + }, + "Microsoft.Extensions.DependencyInjection": { + "target": "Package", + "version": "[9.0.9, )" + }, + "Swashbuckle.AspNetCore.SwaggerGen": { + "target": "Package", + "version": "[9.0.5, )" + }, + "Swashbuckle.AspNetCore.SwaggerUI": { + "target": "Package", + "version": "[9.0.5, )" + }, + "System.IdentityModel.Tokens.Jwt": { + "target": "Package", + "version": "[8.17.0, )" + }, + "dotenv.net": { + "target": "Package", + "version": "[4.0.2, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "/Users/rebuy/.dotnet/sdk/9.0.312/PortableRuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/Backend/API/obj/project.nuget.cache b/Backend/API/obj/project.nuget.cache new file mode 100644 index 00000000..19d1de7c --- /dev/null +++ b/Backend/API/obj/project.nuget.cache @@ -0,0 +1,72 @@ +{ + "version": 2, + "dgSpecHash": "6jVF6uz8tKM=", + "success": true, + "projectFilePath": "/Users/rebuy/Desktop/FCAI/GP/CodienceProject/Backend/API/Codience.API.csproj", + "expectedPackageFiles": [ + "/Users/rebuy/.nuget/packages/csvhelper/33.1.0/csvhelper.33.1.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/dotenv.net/4.0.2/dotenv.net.4.0.2.nupkg.sha512", + "/Users/rebuy/.nuget/packages/humanizer.core/2.14.1/humanizer.core.2.14.1.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.aspnetcore.openapi/9.0.2/microsoft.aspnetcore.openapi.9.0.2.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.bcl.asyncinterfaces/7.0.0/microsoft.bcl.asyncinterfaces.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.build.framework/17.8.3/microsoft.build.framework.17.8.3.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.build.locator/1.7.8/microsoft.build.locator.1.7.8.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.codeanalysis.analyzers/3.3.4/microsoft.codeanalysis.analyzers.3.3.4.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.codeanalysis.common/4.8.0/microsoft.codeanalysis.common.4.8.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.codeanalysis.csharp/4.8.0/microsoft.codeanalysis.csharp.4.8.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.codeanalysis.csharp.workspaces/4.8.0/microsoft.codeanalysis.csharp.workspaces.4.8.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.codeanalysis.workspaces.common/4.8.0/microsoft.codeanalysis.workspaces.common.4.8.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.codeanalysis.workspaces.msbuild/4.8.0/microsoft.codeanalysis.workspaces.msbuild.4.8.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.entityframeworkcore/9.0.9/microsoft.entityframeworkcore.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.entityframeworkcore.abstractions/9.0.9/microsoft.entityframeworkcore.abstractions.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.entityframeworkcore.analyzers/9.0.9/microsoft.entityframeworkcore.analyzers.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.entityframeworkcore.design/9.0.9/microsoft.entityframeworkcore.design.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.entityframeworkcore.relational/9.0.9/microsoft.entityframeworkcore.relational.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.entityframeworkcore.tools/9.0.9/microsoft.entityframeworkcore.tools.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.caching.abstractions/9.0.9/microsoft.extensions.caching.abstractions.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.caching.memory/9.0.9/microsoft.extensions.caching.memory.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.configuration/9.0.5/microsoft.extensions.configuration.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.configuration.abstractions/9.0.9/microsoft.extensions.configuration.abstractions.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.configuration.binder/9.0.5/microsoft.extensions.configuration.binder.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.dependencyinjection/9.0.9/microsoft.extensions.dependencyinjection.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.dependencyinjection.abstractions/9.0.9/microsoft.extensions.dependencyinjection.abstractions.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.dependencymodel/9.0.9/microsoft.extensions.dependencymodel.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.diagnostics/9.0.5/microsoft.extensions.diagnostics.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.diagnostics.abstractions/9.0.5/microsoft.extensions.diagnostics.abstractions.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.http/9.0.5/microsoft.extensions.http.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.logging/9.0.9/microsoft.extensions.logging.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.logging.abstractions/9.0.9/microsoft.extensions.logging.abstractions.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.options/9.0.9/microsoft.extensions.options.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.options.configurationextensions/9.0.5/microsoft.extensions.options.configurationextensions.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.extensions.primitives/9.0.9/microsoft.extensions.primitives.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.identitymodel.abstractions/8.17.0/microsoft.identitymodel.abstractions.8.17.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.identitymodel.jsonwebtokens/8.17.0/microsoft.identitymodel.jsonwebtokens.8.17.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.identitymodel.logging/8.17.0/microsoft.identitymodel.logging.8.17.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.identitymodel.tokens/8.17.0/microsoft.identitymodel.tokens.8.17.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/microsoft.openapi/1.6.25/microsoft.openapi.1.6.25.nupkg.sha512", + "/Users/rebuy/.nuget/packages/mono.texttemplating/3.0.0/mono.texttemplating.3.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/newtonsoft.json/13.0.4/newtonsoft.json.13.0.4.nupkg.sha512", + "/Users/rebuy/.nuget/packages/npgsql/9.0.3/npgsql.9.0.3.nupkg.sha512", + "/Users/rebuy/.nuget/packages/npgsql.entityframeworkcore.postgresql/9.0.4/npgsql.entityframeworkcore.postgresql.9.0.4.nupkg.sha512", + "/Users/rebuy/.nuget/packages/polly/8.6.4/polly.8.6.4.nupkg.sha512", + "/Users/rebuy/.nuget/packages/polly.core/8.6.4/polly.core.8.6.4.nupkg.sha512", + "/Users/rebuy/.nuget/packages/swashbuckle.aspnetcore.swagger/9.0.5/swashbuckle.aspnetcore.swagger.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/swashbuckle.aspnetcore.swaggergen/9.0.5/swashbuckle.aspnetcore.swaggergen.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/swashbuckle.aspnetcore.swaggerui/9.0.5/swashbuckle.aspnetcore.swaggerui.9.0.5.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.codedom/6.0.0/system.codedom.6.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.collections.immutable/7.0.0/system.collections.immutable.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.composition/7.0.0/system.composition.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.composition.attributedmodel/7.0.0/system.composition.attributedmodel.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.composition.convention/7.0.0/system.composition.convention.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.composition.hosting/7.0.0/system.composition.hosting.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.composition.runtime/7.0.0/system.composition.runtime.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.composition.typedparts/7.0.0/system.composition.typedparts.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.identitymodel.tokens.jwt/8.17.0/system.identitymodel.tokens.jwt.8.17.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.io.pipelines/7.0.0/system.io.pipelines.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.reflection.metadata/7.0.0/system.reflection.metadata.7.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.runtime.compilerservices.unsafe/6.0.0/system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.text.json/9.0.9/system.text.json.9.0.9.nupkg.sha512", + "/Users/rebuy/.nuget/packages/system.threading.channels/7.0.0/system.threading.channels.7.0.0.nupkg.sha512" + ], + "logs": [] +} \ No newline at end of file diff --git a/Readme.md b/Readme.md index 8005e3af..4357b744 100644 --- a/Readme.md +++ b/Readme.md @@ -1,96 +1,149 @@ -# Codience --> Sudonators Team ^_^ +# Codience — *Sudonators Team* ^_^ -## Abstract -Codience is an intelligent VS Code extension that helps developers and tech leads decide what to work on next by analyzing technical complexity, business impact, dependencies, code health, risk of delay, and skill alignment. - ---- +> **AI-powered pull-request prioritization, risk analysis, and reviewer recommendation — right inside VS Code.** -## Main Idea -Codience prioritizes development tasks using AI, enabling teams to focus on the most important work first. It provides actionable, data-driven recommendations directly inside VS Code, reducing bottlenecks and improving delivery efficiency. +Codience helps developers and tech leads answer one question fast: **“Which pull request should we review and merge next?”** It analyzes every open PR for **business impact**, **bug risk**, **change complexity**, and **reviewer fit**, then surfaces ranked, data-driven recommendations in an in-editor dashboard. --- -## Objectives -- Reduce bottlenecks in development workflows. -- Improve delivery speed and efficiency. -- Ensure the highest-priority work gets completed first. -- Provide data-driven recommendations directly inside the code editor. +## Abstract +Codience is an intelligent VS Code extension that helps engineering teams decide what to work on next by combining machine learning, large language models, and software-engineering metrics. It connects to GitHub and Jira, scores each open pull request across multiple dimensions, recommends the best reviewers, and summarizes changes — all without leaving the editor. --- -## Scope -- Real-time task ranking based on multiple weighted factors. -- Seamless integration with Jira, GitHub, GitLab, and other project management/version control tools. -- Live in-editor dashboard with priority insights. -- Continuous analytics to refine prioritization accuracy over time. +## What Codience Does + +| Capability | How it works | +|---|---| +| **Business-impact ranking** | Scores each PR (blast radius, user exposure, deadline pressure, business impact) into **High / Medium / Low** tiers and flags merges that should be blocked. | +| **Bug-risk analysis** | An SVM model trained on commit-level metrics (ApacheJIT-style features) predicts a **bug probability** for each PR. | +| **Reviewer recommendation** | A RAG + multi-agent engine matches PR changes to the most qualified reviewers using commit history, skill extraction, Jira workload, and vector similarity. | +| **PR summarization** | An LLM produces a concise, human-readable summary of large diffs (with map-reduce for big PRs). | +| **Jira & GitHub integration** | OAuth into both; link PRs to tickets, read assignments, and enrich scoring with real project context. | +| **In-editor dashboard** | A React webview shows ranked PRs, risk/impact charts, recommended reviewers, and profile analytics inside the VS Code sidebar. | --- -## Key Highlights -- AI-powered prioritization of development tasks. -- Seamless integration with Jira, GitHub, and GitLab. -- Real-time task ranking based on business impact, complexity, and risk. -- Live dashboard inside VS Code for instant recommendations. -- Data-driven decision making to improve delivery speed. -- Continuous learning from past project patterns to improve accuracy. +## Architecture + +Codience is a **polyglot microservices system**. A VS Code extension hosts a React dashboard that talks to a .NET Core API and four Python FastAPI services. + +``` + ┌───────────────────────────────────────────┐ + │ VS Code Extension (React + Vite webview) │ + │ Dashboard · PR table · Reviewers · Jira │ + └───────────────┬─────────────────────────────┘ + │ HTTP + ┌────────────────────────┼─────────────────────────────────────┐ + ▼ ▼ ▼ +┌────────────────┐ ┌──────────────────────┐ ┌──────────────────────────────────┐ +│ .NET Core API │ │ Python AI services │ │ External APIs │ +│ ASP.NET 9 │ │ (FastAPI) │ │ │ +│ EF Core │ │ • Reviewer :8000 │ │ GitHub REST · Jira Cloud │ +│ :5051 / :8080 │ │ • Risk :8001 │ │ Ollama · Gemini · Groq/Mistral │ +│ │ │ • Summarizer:8002 │ │ Chroma vector DB │ +│ │ │ • Impact :8003 │ │ │ +└───────┬────────┘ └──────────────────────┘ └──────────────────────────────────┘ + │ + ▼ + PostgreSQL 16 +``` + +A detailed, as-built **UML class diagram** of the whole system lives in +`../Diagrams/Codience_AsBuilt_ClassDiagram.drawio` (5 pages: overview, backend, frontend, reviewer engine, AI services). + +### Components + +- **Frontend** — VS Code extension with a React + Vite webview (`SidebarProvider`). Pages: Dashboard, PRs, PR summary, reviewer settings, Jira login, profile. Calls every backend service via typed service modules. +- **.NET API** — ASP.NET Core 9 in clean architecture (Domain → Abstraction → Services → Infrastructure → API) with EF Core + PostgreSQL. Handles GitHub OAuth/App/webhooks, Jira OAuth, repositories & pull requests, and computes change/history/experience metrics. +- **Reviewer Recommender** (FastAPI, `:8000`) — RAG + multi-agent: PR skill extraction, Chroma vector search over commit diffs, Tversky profile matching, Jira-workload analysis, and a resilient multi-provider LLM router (Groq / Mistral / Cerebras / Gemini) with a two-layer profile cache. +- **Risk Service** (FastAPI, `:8001`) — SVM model (`svm_model_proba.pkl`) over 12 log-transformed commit metrics → bug probability. +- **PR Summarizer** (FastAPI, `:8002`) — Google Gemini, single-call or map-reduce summarization of PR diffs. +- **Business Impact / Priority** (FastAPI, `:8003`) — blends a rule-based formula with a local Qwen2.5-Coder model (via Ollama) to score blast radius, user exposure, and deadline pressure into an impact tier. --- -## Expected Outcomes and Deliverables +## Tech Stack -### Expected Outcomes -- Improved developer productivity by reducing time spent deciding what to work on. -- Faster delivery cycles with fewer bottlenecks. -- Better task alignment with business priorities and team skills. -- Higher code quality by prioritizing risky or untested code for review. -- Increased visibility of project health inside the code editor. -- Data-driven decisions replacing guesswork in task prioritization. - -### Deliverables -- VS Code Extension package (`.vsix`) ready to install. -- Integration modules for Jira, GitHub, GitLab APIs. -- Real-time prioritization engine with ranking algorithms. -- Dashboard UI inside VS Code showing ranked tasks. -- Analytics and reporting module (task completion rates, code risk stats). -- Technical documentation (architecture, API references, setup guides). -- User guide for developers and tech leads. -- Demo video showing how Codience works. -- Test cases & QA reports proving stability and accuracy. +| Layer | Technologies | +|---|---| +| **Frontend** | TypeScript, React, Vite, VS Code Extension API, Recharts | +| **Backend** | C#, ASP.NET Core 9, Entity Framework Core | +| **AI / ML** | Python, FastAPI, scikit-learn (SVM), Chroma, Sentence-Transformers (nomic / MiniLM), Ollama (Qwen2.5-Coder, Qwen2.5), Google Gemini, Groq / Mistral / Cerebras | +| **Database** | PostgreSQL 16 | +| **Integrations** | GitHub REST API & GitHub App, Jira Cloud API | +| **DevOps** | Docker, docker-compose, GitHub Actions | --- -## Technical Details +## Repository Layout (branches) -### Frontend -- Next.js, Tailwind CSS +This work spans several branches of the GitHub repository: -### Backend -- ASP.Net Core +| Branch | Contents | +|---|---| +| `Backend` | ASP.NET Core API (this checkout) | +| `frontend_v2` | React + Vite VS Code webview (latest UI) | +| `AI/DL` | Risk service, PR Summarizer, Reviewer Recommender engine | +| `Backend-AI` | Business Impact / Priority service | +| `DevOps` | Dockerfiles & `docker-compose` | +| `main` | Integration branch | -### DevOps -- Docker, GitHub CI/CD - -### AI/ML -- Scikit-learn, LightGBM, PyTorch +--- -### Integration Tools -- GitHub API / GitLab API, Jira +## Getting Started + +> Prerequisites: .NET 9 SDK, Node.js 18+, Python 3.10+, PostgreSQL 16, and (optionally) Ollama for the local LLM scoring. + +**1. Backend API** +```bash +cd Backend/API +dotnet restore +# set ConnectionStrings__DefaultConnection for PostgreSQL +dotnet run # serves on http://localhost:5051 +``` + +**2. Python AI services** (each in its own terminal / venv) +```bash +# Risk (:8001), Summarizer (:8002), Reviewer (:8000), Business Impact (:8003) +pip install -r requirements.txt +uvicorn app:app --port +``` + +**3. Frontend (VS Code extension)** +```bash +cd codience +npm install +npm run watch # then press F5 in VS Code to launch the extension host +``` + +**4. Or run the containerized stack** +```bash +docker compose up # db + api + frontend (see DevOps branch) +``` -### Storage -- PostgreSQL, MongoDB (optional / for logs) +--- -### Graph Dependency Tracking -- Neo4j, NetworkX (optional) +## Objectives +- Reduce bottlenecks in development workflows. +- Improve delivery speed and efficiency. +- Ensure the highest-priority work gets reviewed and merged first. +- Provide data-driven recommendations directly inside the code editor. -### Deployment -- GitHub Actions, AWS +## Expected Outcomes +- Less time spent deciding what to review next. +- Faster delivery cycles with fewer bottlenecks. +- Better alignment of work with business priorities and team skills. +- Higher code quality by surfacing risky changes early. +- Data-driven decisions replacing guesswork in prioritization. --- -## Mentorship Details -- **Academic Supervisors:** - - Dr. Mohamed El Ramly - - TA: Hager Mahmoud - +## Mentorship +- **Academic Supervisors:** + - Dr. Mohamed El Ramly + - TA: Hager Mahmoud +--- +*Faculty of Computers and Artificial Intelligence — Graduation Project.* diff --git a/Risk/API/riskAnalysis_logistic.py b/Risk/API/riskAnalysis_logistic.py new file mode 100644 index 00000000..b82e8dd2 --- /dev/null +++ b/Risk/API/riskAnalysis_logistic.py @@ -0,0 +1,1976 @@ +# %% [raw] +# { +# "cells": [ +# { +# "cell_type": "code", +# "id": "initial_id", +# "metadata": { +# "collapsed": true, +# "ExecuteTime": { +# "end_time": "2026-03-13T20:01:16.664221Z", +# "start_time": "2026-03-13T20:01:16.621103Z" +# } +# }, +# "source": [ +# "import pandas as pd\n", +# "import numpy as np\n", +# "from sklearn.linear_model import LogisticRegression\n" +# ], +# "outputs": [], +# "execution_count": 34 +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:01:16.750675Z", +# "start_time": "2026-03-13T20:01:16.667330Z" +# } +# }, +# "cell_type": "code", +# "source": [ +# "train = pd.read_csv('./Dataset/apacheJIT/apachejit_train.csv')\n", +# "\n", +# "train.head()" +# ], +# "id": "af4c47b66e371494", +# "outputs": [ +# { +# "data": { +# "text/plain": [ +# " commit_id project buggy fix \\\n", +# "0 06a456ec1670fb26a86f8a18f5b55017ac961f39 apache/groovy True False \n", +# "1 79f50a10e7688279664146bb3c18837dada370a4 apache/groovy False False \n", +# "2 42437917f185f8efa3d947fae3bb08b584504650 apache/groovy False False \n", +# "3 b6616e5fb6d537229d307cf8647ef483468175a6 apache/groovy True False \n", +# "4 5d0abaebf0bd4b5d98f9ef173f23b3be5e6fb37f apache/groovy True False \n", +# "\n", +# " year author_date la ld nf nd ns ent ndev age \\\n", +# "0 2003 1064916954 223 33 7 5 2 2.213687 0.142857 1.857143 \n", +# "1 2003 1071086882 138 10 9 3 1 1.692477 0.333333 32.333333 \n", +# "2 2003 1072801387 69 20 2 2 1 0.599911 1.500000 9.500000 \n", +# "3 2003 1072694298 52 2 2 2 1 0.380947 1.000000 6.000000 \n", +# "4 2003 1070542250 256 348 8 4 1 0.489213 0.375000 13.625000 \n", +# "\n", +# " nuc aexp arexp asexp \n", +# "0 12.142857 104 104.0 0.000606 \n", +# "1 11.777778 287 287.0 228.000000 \n", +# "2 16.500000 366 366.0 281.000000 \n", +# "3 14.000000 364 364.0 279.000000 \n", +# "4 20.000000 253 253.0 199.000000 " +# ], +# "text/html": [ +# "
\n", +# "\n", +# "\n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# "
commit_idprojectbuggyfixyearauthor_datelaldnfndnsentndevagenucaexparexpasexp
006a456ec1670fb26a86f8a18f5b55017ac961f39apache/groovyTrueFalse20031064916954223337522.2136870.1428571.85714312.142857104104.00.000606
179f50a10e7688279664146bb3c18837dada370a4apache/groovyFalseFalse20031071086882138109311.6924770.33333332.33333311.777778287287.0228.000000
242437917f185f8efa3d947fae3bb08b584504650apache/groovyFalseFalse2003107280138769202210.5999111.5000009.50000016.500000366366.0281.000000
3b6616e5fb6d537229d307cf8647ef483468175a6apache/groovyTrueFalse200310726942985222210.3809471.0000006.00000014.000000364364.0279.000000
45d0abaebf0bd4b5d98f9ef173f23b3be5e6fb37fapache/groovyTrueFalse200310705422502563488410.4892130.37500013.62500020.000000253253.0199.000000
\n", +# "
" +# ] +# }, +# "execution_count": 35, +# "metadata": {}, +# "output_type": "execute_result" +# } +# ], +# "execution_count": 35 +# }, +# { +# "metadata": {}, +# "cell_type": "markdown", +# "source": "# Pre Processing", +# "id": "263872ad978b3547" +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:01:16.903376Z", +# "start_time": "2026-03-13T20:01:16.792021Z" +# } +# }, +# "cell_type": "code", +# "source": [ +# "X_train= train.drop(['commit_id','project','fix','year','author_date',\"fix\"],axis=1)\n", +# "y_train= train['buggy']\n", +# "X_train" +# ], +# "id": "3b744e6cb523161f", +# "outputs": [ +# { +# "data": { +# "text/plain": [ +# " buggy la ld nf nd ns ent ndev age nuc \\\n", +# "0 True 223 33 7 5 2 2.213687 0.142857 1.857143 12.142857 \n", +# "1 False 138 10 9 3 1 1.692477 0.333333 32.333333 11.777778 \n", +# "2 False 69 20 2 2 1 0.599911 1.500000 9.500000 16.500000 \n", +# "3 True 52 2 2 2 1 0.380947 1.000000 6.000000 14.000000 \n", +# "4 True 256 348 8 4 1 0.489213 0.375000 13.625000 20.000000 \n", +# "... ... ... ... .. .. .. ... ... ... ... \n", +# "44829 False 1 0 1 1 1 0.000000 5.000000 1.000000 12.000000 \n", +# "44830 False 14 0 2 1 1 1.000000 1.500000 92.500000 2.000000 \n", +# "44831 False 50 0 2 2 1 0.855451 2.000000 3.500000 8.000000 \n", +# "44832 False 4 0 3 1 1 1.500000 3.000000 15.666667 19.000000 \n", +# "44833 False 8 29 9 3 1 2.533868 0.333333 100.000000 0.777778 \n", +# "\n", +# " aexp arexp asexp \n", +# "0 104 104.000000 0.000606 \n", +# "1 287 287.000000 228.000000 \n", +# "2 366 366.000000 281.000000 \n", +# "3 364 364.000000 279.000000 \n", +# "4 253 253.000000 199.000000 \n", +# "... ... ... ... \n", +# "44829 1 1.000000 0.000000 \n", +# "44830 2 2.000000 0.000000 \n", +# "44831 3 3.000000 1.000000 \n", +# "44832 4 4.000000 0.000000 \n", +# "44833 10388 4081.682143 5238.000000 \n", +# "\n", +# "[44834 rows x 13 columns]" +# ], +# "text/html": [ +# "
\n", +# "\n", +# "\n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# "
buggylaldnfndnsentndevagenucaexparexpasexp
0True223337522.2136870.1428571.85714312.142857104104.0000000.000606
1False138109311.6924770.33333332.33333311.777778287287.000000228.000000
2False69202210.5999111.5000009.50000016.500000366366.000000281.000000
3True5222210.3809471.0000006.00000014.000000364364.000000279.000000
4True2563488410.4892130.37500013.62500020.000000253253.000000199.000000
..........................................
44829False101110.0000005.0000001.00000012.00000011.0000000.000000
44830False1402111.0000001.50000092.5000002.00000022.0000000.000000
44831False5002210.8554512.0000003.5000008.00000033.0000001.000000
44832False403111.5000003.00000015.66666719.00000044.0000000.000000
44833False8299312.5338680.333333100.0000000.777778103884081.6821435238.000000
\n", +# "

44834 rows × 13 columns

\n", +# "
" +# ] +# }, +# "execution_count": 36, +# "metadata": {}, +# "output_type": "execute_result" +# } +# ], +# "execution_count": 36 +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:01:17.080255Z", +# "start_time": "2026-03-13T20:01:17.056304Z" +# } +# }, +# "cell_type": "code", +# "source": "y_train", +# "id": "2f8226b4a62fd720", +# "outputs": [ +# { +# "data": { +# "text/plain": [ +# "0 True\n", +# "1 False\n", +# "2 False\n", +# "3 True\n", +# "4 True\n", +# " ... \n", +# "44829 False\n", +# "44830 False\n", +# "44831 False\n", +# "44832 False\n", +# "44833 False\n", +# "Name: buggy, Length: 44834, dtype: bool" +# ] +# }, +# "execution_count": 37, +# "metadata": {}, +# "output_type": "execute_result" +# } +# ], +# "execution_count": 37 +# }, +# { +# "metadata": {}, +# "cell_type": "markdown", +# "source": "# Model Training", +# "id": "aa8def30d41778c3" +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:01:17.618958Z", +# "start_time": "2026-03-13T20:01:17.471043Z" +# } +# }, +# "cell_type": "code", +# "source": [ +# "from sklearn.linear_model import LogisticRegression\n", +# "\n", +# "# create the model\n", +# "model = LogisticRegression()\n", +# "\n", +# "# train the model\n", +# "model.fit(X_train, y_train)" +# ], +# "id": "eb2f4e505633d9ba", +# "outputs": [ +# { +# "name": "stderr", +# "output_type": "stream", +# "text": [ +# "/Users/rebuy/Desktop/FCAI/GP/MyCode/.venv/lib/python3.14/site-packages/sklearn/linear_model/_logistic.py:406: ConvergenceWarning: lbfgs failed to converge after 100 iteration(s) (status=1):\n", +# "STOP: TOTAL NO. OF ITERATIONS REACHED LIMIT\n", +# "\n", +# "Increase the number of iterations to improve the convergence (max_iter=100).\n", +# "You might also want to scale the data as shown in:\n", +# " https://scikit-learn.org/stable/modules/preprocessing.html\n", +# "Please also refer to the documentation for alternative solver options:\n", +# " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n", +# " n_iter_i = _check_optimize_result(\n" +# ] +# }, +# { +# "data": { +# "text/plain": [ +# "LogisticRegression()" +# ], +# "text/html": [ +# "
LogisticRegression()
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" +# ] +# }, +# "execution_count": 38, +# "metadata": {}, +# "output_type": "execute_result" +# } +# ], +# "execution_count": 38 +# }, +# { +# "metadata": {}, +# "cell_type": "markdown", +# "source": "# Testing", +# "id": "28dd5664cc88fac8" +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:01:17.668238Z", +# "start_time": "2026-03-13T20:01:17.637058Z" +# } +# }, +# "cell_type": "code", +# "source": [ +# "test = pd.read_csv('./Dataset/apacheJIT/aapachejit_test_large.csv')\n", +# "test" +# ], +# "id": "9c90c3d0fb22f6d8", +# "outputs": [ +# { +# "data": { +# "text/plain": [ +# " commit_id project buggy fix \\\n", +# "0 999baceff36165d950a61dd9cc4342f252e64837 apache/flink True False \n", +# "1 2c799fb70aa47f9109714dc410862af24b4a0321 apache/hbase False False \n", +# "2 22ac8c00db676ccc01d1a44ec206ee17790b46b0 apache/camel False False \n", +# "3 a9d3412b4ce40f5ab5a18756ede7e0606b653171 apache/hadoop False False \n", +# "4 6cf958c2fa7dab4a028039c7c6e8f23456a5d7e5 apache/groovy False False \n", +# "... ... ... ... ... \n", +# "7521 f89ffc3ae18d2ff25fe7250c63ee850372b35094 apache/camel False False \n", +# "7522 bc0cb5bb0571e0044c5958142c519e9d2b7b610f apache/camel False False \n", +# "7523 ee002068b75f5acaf909d7d82a6d212a879cdeb1 apache/camel False False \n", +# "7524 c3c48f30f7450c3a04950805bba7fb1536db7c9d apache/hbase False False \n", +# "7525 36b52fc525876c17f55faff87bed66e91c3cc1e2 apache/camel False False \n", +# "\n", +# " year author_date la ld nf nd ns ent ndev \\\n", +# "0 2017 1488367395 1439 87 80 4 1 5.746825 0.312500 \n", +# "1 2017 1486008708 983 4378 16 8 4 0.727304 5.250000 \n", +# "2 2017 1511424716 8 16 4 4 2 1.614005 3.500000 \n", +# "3 2017 1498508667 3 2 1 1 1 0.000000 15.000000 \n", +# "4 2017 1505541139 9 9 6 4 1 2.419382 5.000000 \n", +# "... ... ... ... ... .. .. .. ... ... \n", +# "7521 2019 1548057494 18 15 11 4 1 3.359253 2.181818 \n", +# "7522 2019 1554966471 2 2 1 1 1 0.000000 2.000000 \n", +# "7523 2019 1565342979 2 1 1 1 1 0.000000 4.000000 \n", +# "7524 2019 1555858691 73 17 9 2 4 2.791749 6.666667 \n", +# "7525 2019 1569053508 0 1 1 1 1 0.000000 20.000000 \n", +# "\n", +# " age nuc aexp arexp asexp \n", +# "0 50.625000 4.237500 223 178.833333 21.000000 \n", +# "1 0.000000 64.750000 105 60.833333 0.109456 \n", +# "2 7.000000 18.000000 13353 4421.309524 0.992185 \n", +# "3 19.000000 25.000000 44 20.750000 15.000000 \n", +# "4 335.166667 118.000000 364 258.166667 244.000000 \n", +# "... ... ... ... ... ... \n", +# "7521 67.363636 42.000000 4767 2909.000000 1681.000000 \n", +# "7522 0.000000 3.000000 5747 3610.583333 2275.000000 \n", +# "7523 115.000000 5.000000 73 36.916667 7.000000 \n", +# "7524 68.111111 36.777778 516 312.850000 0.145894 \n", +# "7525 0.000000 67.000000 15351 4099.212951 7591.000000 \n", +# "\n", +# "[7526 rows x 18 columns]" +# ], +# "text/html": [ +# "
\n", +# "\n", +# "\n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# " \n", +# "
commit_idprojectbuggyfixyearauthor_datelaldnfndnsentndevagenucaexparexpasexp
0999baceff36165d950a61dd9cc4342f252e64837apache/flinkTrueFalse2017148836739514398780415.7468250.31250050.6250004.237500223178.83333321.000000
12c799fb70aa47f9109714dc410862af24b4a0321apache/hbaseFalseFalse20171486008708983437816840.7273045.2500000.00000064.75000010560.8333330.109456
222ac8c00db676ccc01d1a44ec206ee17790b46b0apache/camelFalseFalse201715114247168164421.6140053.5000007.00000018.000000133534421.3095240.992185
3a9d3412b4ce40f5ab5a18756ede7e0606b653171apache/hadoopFalseFalse20171498508667321110.00000015.00000019.00000025.0000004420.75000015.000000
46cf958c2fa7dab4a028039c7c6e8f23456a5d7e5apache/groovyFalseFalse20171505541139996412.4193825.000000335.166667118.000000364258.166667244.000000
.........................................................
7521f89ffc3ae18d2ff25fe7250c63ee850372b35094apache/camelFalseFalse20191548057494181511413.3592532.18181867.36363642.00000047672909.0000001681.000000
7522bc0cb5bb0571e0044c5958142c519e9d2b7b610fapache/camelFalseFalse20191554966471221110.0000002.0000000.0000003.00000057473610.5833332275.000000
7523ee002068b75f5acaf909d7d82a6d212a879cdeb1apache/camelFalseFalse20191565342979211110.0000004.000000115.0000005.0000007336.9166677.000000
7524c3c48f30f7450c3a04950805bba7fb1536db7c9dapache/hbaseFalseFalse2019155585869173179242.7917496.66666768.11111136.777778516312.8500000.145894
752536b52fc525876c17f55faff87bed66e91c3cc1e2apache/camelFalseFalse20191569053508011110.00000020.0000000.00000067.000000153514099.2129517591.000000
\n", +# "

7526 rows × 18 columns

\n", +# "
" +# ] +# }, +# "execution_count": 39, +# "metadata": {}, +# "output_type": "execute_result" +# } +# ], +# "execution_count": 39 +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:01:17.772188Z", +# "start_time": "2026-03-13T20:01:17.694078Z" +# } +# }, +# "cell_type": "code", +# "source": [ +# "X_test= test.drop(['commit_id','project','fix','year','author_date',\"fix\"],axis=1)\n", +# "y_test= test['buggy']" +# ], +# "id": "1013dd4a33b8dea6", +# "outputs": [], +# "execution_count": 40 +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:01:17.992553Z", +# "start_time": "2026-03-13T20:01:17.969112Z" +# } +# }, +# "cell_type": "code", +# "source": "model.score(X_test, y_test)", +# "id": "50c43d26771a0a9d", +# "outputs": [ +# { +# "data": { +# "text/plain": [ +# "0.8227478076003188" +# ] +# }, +# "execution_count": 41, +# "metadata": {}, +# "output_type": "execute_result" +# } +# ], +# "execution_count": 41 +# }, +# { +# "metadata": {}, +# "cell_type": "markdown", +# "source": "# Saving the Model", +# "id": "474079755d7fa7ba" +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:02:19.359170Z", +# "start_time": "2026-03-13T20:02:19.329770Z" +# } +# }, +# "cell_type": "code", +# "outputs": [], +# "execution_count": 42, +# "source": [ +# "import pickle\n", +# "\n", +# "# save the trained model\n", +# "with open(\"risk_logistic_model.pkl\", \"wb\") as f:\n", +# " pickle.dump(model, f)" +# ], +# "id": "adfd566c188ce728" +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:03:02.533134Z", +# "start_time": "2026-03-13T20:03:02.507633Z" +# } +# }, +# "cell_type": "code", +# "source": [ +# "import pickle\n", +# "\n", +# "with open(\"risk_logistic_model.pkl\", \"rb\") as f:\n", +# " loaded_model = pickle.load(f)" +# ], +# "id": "642a0d29cbacd0da", +# "outputs": [], +# "execution_count": 43 +# }, +# { +# "metadata": { +# "ExecuteTime": { +# "end_time": "2026-03-13T20:03:13.140541Z", +# "start_time": "2026-03-13T20:03:13.108704Z" +# } +# }, +# "cell_type": "code", +# "source": "predictions = loaded_model.predict(X_test)", +# "id": "685093965681582b", +# "outputs": [], +# "execution_count": 44 +# } +# ], +# "metadata": { +# "kernelspec": { +# "display_name": "Python 3", +# "language": "python", +# "name": "python3" +# }, +# "language_info": { +# "codemirror_mode": { +# "name": "ipython", +# "version": 2 +# }, +# "file_extension": ".py", +# "mimetype": "text/x-python", +# "name": "python", +# "nbconvert_exporter": "python", +# "pygments_lexer": "ipython2", +# "version": "2.7.6" +# } +# }, +# "nbformat": 4, +# "nbformat_minor": 5 +# } +# +# %% [markdown] +# # Pre Processing +# %% +y_train +# %% +from sklearn.linear_model import LogisticRegression + +# create the model +model = LogisticRegression() + +# train the model +model.fit(X_train, y_train) +# %% +test = pd.read_csv('./Dataset/apacheJIT/aapachejit_test_large.csv') +test +# %% +model.score(X_test, y_test) +# %% +import pickle + +# save the trained model +with open("risk_logistic_model.pkl", "wb") as f: + pickle.dump(model, f) +# %% +predictions = loaded_model.predict(X_test) \ No newline at end of file diff --git a/Risk/API/risk_api.py b/Risk/API/risk_api.py index 08f5cfc6..092c3b23 100644 --- a/Risk/API/risk_api.py +++ b/Risk/API/risk_api.py @@ -2,6 +2,7 @@ import math from fastapi import FastAPI,HTTPException +from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import numpy as np import pickle @@ -64,6 +65,15 @@ def load_model(): # --- FastAPI App Setup --- app = FastAPI() +# Add CORS middleware +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # Adjust this to your needs + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + log("Attempting to load the model...") try: model = load_model() diff --git a/codience/.~lock.Reviewer_Recommender_Test_Report.csv# b/codience/.~lock.Reviewer_Recommender_Test_Report.csv# new file mode 100644 index 00000000..010eb0dc --- /dev/null +++ b/codience/.~lock.Reviewer_Recommender_Test_Report.csv# @@ -0,0 +1 @@ +,malak-hisham,malak-hisham,28.06.2026 23:19,file:///home/malak-hisham/.config/libreoffice/4; \ No newline at end of file diff --git a/codience/PR_Summarizer/.gitignore b/codience/PR_Summarizer/.gitignore new file mode 100644 index 00000000..5cb24285 --- /dev/null +++ b/codience/PR_Summarizer/.gitignore @@ -0,0 +1,7 @@ +# Secrets — never commit real keys +.env + +# Python +__pycache__/ +*.pyc +.venv/ diff --git a/codience/PR_Summarizer/app.py b/codience/PR_Summarizer/app.py new file mode 100644 index 00000000..b7453f11 --- /dev/null +++ b/codience/PR_Summarizer/app.py @@ -0,0 +1,93 @@ +import os +import sys + +import httpx +from fastapi import FastAPI, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from pydantic import BaseModel + +from summarize_pr import summarize_pr + + + +BACKEND_BASE_URL = "http://127.0.0.1:5051/api/GitHubAuth" + + + +def _log(message: str): + print(message, file=sys.stderr) + + +app = FastAPI(title="Codience PR Summarizer") + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_methods=["*"], + allow_headers=["*"], +) + + +class PRInput(BaseModel): + title: str + description: str = "" + diff: str = "" + + +class SummaryResponse(BaseModel): + summary: str + + +@app.get("/health") +def health(): + return {"status": "ok"} + + +@app.post("/summarize", response_model=SummaryResponse) +def summarize(data: PRInput): + """Summarize what happened in a pull request. Returns a markdown summary.""" + summary = summarize_pr(data.model_dump()) + return {"summary": summary} + + +@app.get("/summarize/{owner}/{repo}/pulls/{pull_number}", response_model=SummaryResponse) +async def summarize_from_backend(owner: str, repo: str, pull_number: int): + """Fetch a single PR from the .NET backend and return its summary. + + Calls GET {BACKEND_BASE_URL}/{owner}/{repo}/pulls/{pull_number} (which + returns just that PR, diff included) and feeds its title/body/diff into + the summarizer. + """ + url = f"{BACKEND_BASE_URL}/{owner}/{repo}/pulls/{pull_number}" + + async with httpx.AsyncClient(timeout=120.0, verify=False) as client: + try: + response = await client.get(url) + except httpx.RequestError as exc: + raise HTTPException( + status_code=502, + detail=f"Could not reach backend at {url}: {exc!r}", + ) + + if response.status_code != 200: + raise HTTPException( + status_code=response.status_code, + detail=f"Backend returned {response.status_code}: {response.text}", + ) + + pr = response.json() + + diff = pr.get("diffContent") or "" + # The backend stores fetch failures as the diff text itself ("ERROR: ..."). + if diff.startswith("ERROR:"): + _log(f"Backend could not provide a diff for PR #{pull_number}: {diff[:200]}") + diff = "" + + pr_data = { + "title": pr.get("title") or "", + "description": pr.get("body") or "", + "diff": diff, + } + + summary = summarize_pr(pr_data) + return {"summary": summary} diff --git a/codience/PR_Summarizer/llm.py b/codience/PR_Summarizer/llm.py new file mode 100644 index 00000000..a044444d --- /dev/null +++ b/codience/PR_Summarizer/llm.py @@ -0,0 +1,12 @@ +import os +from google import genai +from dotenv import load_dotenv + +load_dotenv() + + +def get_model(): + """Return a Gemini client. Mirrors the Reviewer Recommender so both + AI features share the same provider and GEMINI_API_KEY.""" + client = genai.Client(api_key=os.getenv("GEMINI_API_KEY")) + return client diff --git a/codience/PR_Summarizer/prompts.py b/codience/PR_Summarizer/prompts.py new file mode 100644 index 00000000..33474f23 --- /dev/null +++ b/codience/PR_Summarizer/prompts.py @@ -0,0 +1,70 @@ +PR_SUMMARY_PROMPT = """ +You are a Senior Software Engineer reviewing a pull request. Your task is to +explain, clearly and concisely, what happened in this pull request so a teammate +can understand it at a glance without reading the full diff. + +PR DATA: +Title: {title} +Description: {description} +Code Changes (Diff): +{diff} + +INSTRUCTIONS: +1. Focus on WHAT changed and WHY it matters, not a line-by-line readout of the diff. +2. Be factual and grounded in the data provided. Do not invent changes that are + not present in the title, description, or diff. +3. Keep it short and skimmable. + +OUTPUT FORMAT (Markdown only, no JSON, no code fences around the whole answer): +A single-sentence **Overview** of the change. + +**Key changes** +- bullet points of the most important changes (3-6 bullets) + +**Impact** (optional, one or two lines): notable effects, risks, or areas a +reviewer should pay attention to. Omit this section if there is nothing notable. +""" + + +# --- Map-reduce prompts (used only for very large diffs) --- + +# MAP step: summarize one section (usually one file) of a large diff into terse notes. +CHUNK_SUMMARY_PROMPT = """ +You are a Senior Software Engineer. Below is one portion of the code changes +(one or more files) from a pull request titled "{title}". Summarize what changed +in THIS portion only. + +CODE CHANGES: +{chunk} + +INSTRUCTIONS: +- Be factual and specific; do not invent changes that are not present. +- Output 1-5 short markdown bullet points. No preamble, no headings. +""" + +# REDUCE step: combine the per-section notes into the final PR summary. +REDUCE_SUMMARY_PROMPT = """ +You are a Senior Software Engineer. You are given a pull request's title and +description, plus per-section notes describing what changed across its files. +Write a single concise summary of what happened in the WHOLE pull request. + +Title: {title} +Description: {description} + +PER-SECTION NOTES: +{file_notes} + +INSTRUCTIONS: +1. Synthesize across all notes; group related changes. Do not just concatenate them. +2. Be factual and grounded in the notes. Do not invent changes. +3. Keep it short and skimmable. + +OUTPUT FORMAT (Markdown only, no JSON, no code fences around the whole answer): +A single-sentence **Overview** of the change. + +**Key changes** +- bullet points of the most important changes (3-6 bullets) + +**Impact** (optional, one or two lines): notable effects, risks, or areas a +reviewer should pay attention to. Omit this section if there is nothing notable. +""" diff --git a/codience/PR_Summarizer/requirements.txt b/codience/PR_Summarizer/requirements.txt new file mode 100644 index 00000000..931f7050 --- /dev/null +++ b/codience/PR_Summarizer/requirements.txt @@ -0,0 +1,5 @@ +fastapi +uvicorn[standard] +google-genai>=0.7.0 +python-dotenv +pydantic diff --git a/codience/PR_Summarizer/summarize_pr.py b/codience/PR_Summarizer/summarize_pr.py new file mode 100644 index 00000000..5fa86a07 --- /dev/null +++ b/codience/PR_Summarizer/summarize_pr.py @@ -0,0 +1,112 @@ +import re +import sys + +from llm import get_model +from prompts import ( + PR_SUMMARY_PROMPT, + CHUNK_SUMMARY_PROMPT, + REDUCE_SUMMARY_PROMPT, +) + +# Same Gemini model the Reviewer Recommender uses, so both features stay aligned. +MODEL = "gemini-3.1-flash-lite-preview" + +# Option A vs B routing: diffs at or below this size are sent whole in one call +# (best coherence). Larger diffs fall back to per-file map-reduce. ~200k chars is +# roughly ~50k tokens, comfortably inside the Gemini flash context window. +SINGLE_CALL_CHAR_LIMIT = 200_000 + +# In map-reduce mode, the maximum chars per chunk sent to the model. +CHUNK_CHAR_LIMIT = 60_000 + + +def _log(message: str): + print(message, file=sys.stderr) + + +def _generate(client, prompt: str) -> str: + response = client.models.generate_content(model=MODEL, contents=prompt) + return (response.text or "").strip() + + +def _split_diff_by_file(diff: str) -> list: + """Split a git diff into per-file sections, keeping each `diff --git` header. + Any section larger than CHUNK_CHAR_LIMIT is hard-split by size. Non-git diffs + fall back to fixed-size chunks.""" + sections = re.split(r"(?=^diff --git )", diff, flags=re.MULTILINE) + sections = [s for s in sections if s.strip()] + if not sections: # not a git-style diff + sections = [diff] + + chunks = [] + for section in sections: + if len(section) <= CHUNK_CHAR_LIMIT: + chunks.append(section) + else: + for i in range(0, len(section), CHUNK_CHAR_LIMIT): + chunks.append(section[i:i + CHUNK_CHAR_LIMIT]) + return chunks + + +def _summarize_single(client, pr_data: dict, diff: str) -> str: + """Option A: send the entire diff in one call.""" + prompt = PR_SUMMARY_PROMPT.format( + title=pr_data.get("title", "N/A"), + description=pr_data.get("description", "N/A"), + diff=diff, + ) + return _generate(client, prompt) + + +def _summarize_mapreduce(client, pr_data: dict, diff: str) -> str: + """Option B: summarize each file section, then combine into one summary.""" + chunks = _split_diff_by_file(diff) + _log(f"Large diff ({len(diff)} chars): map-reduce over {len(chunks)} chunks.") + + notes = [] + for chunk in chunks: + note = _generate(client, CHUNK_SUMMARY_PROMPT.format( + title=pr_data.get("title", "N/A"), + chunk=chunk, + )) + if note: + notes.append(note) + + if not notes: + return "" + + return _generate(client, REDUCE_SUMMARY_PROMPT.format( + title=pr_data.get("title", "N/A"), + description=pr_data.get("description", "N/A"), + file_notes="\n\n".join(notes), + )) + + +def summarize_pr(pr_data: dict) -> str: + """Produce a concise markdown summary of what happened in a pull request. + + pr_data is shaped like the data the .NET backend provides: + {"title": str, "description": str, "diff": str} + + The full diff is sent in a single call when it fits (Option A); very large + diffs fall back to per-file map-reduce (Option B). On failure, returns a safe + fallback message. + """ + diff = pr_data.get("diff", "") or "" + + try: + # Inside the try so a missing/invalid GEMINI_API_KEY (which raises at + # client construction) returns a safe fallback instead of a 500. + client = get_model() + if len(diff) <= SINGLE_CALL_CHAR_LIMIT: + summary = _summarize_single(client, pr_data, diff) + else: + summary = _summarize_mapreduce(client, pr_data, diff) + + if not summary: + _log("Warning: LLM returned an empty summary.") + return "Summary unavailable: the model returned no content." + return summary + except Exception as e: + _log(f"Error generating PR summary: {e}") + return "Summary unavailable due to an internal error." diff --git a/codience/PR_Summarizer/test_summarize.py b/codience/PR_Summarizer/test_summarize.py new file mode 100644 index 00000000..11bf9666 --- /dev/null +++ b/codience/PR_Summarizer/test_summarize.py @@ -0,0 +1,35 @@ +from summarize_pr import summarize_pr + +# Mock data shaped like what the .NET backend provides. +mock_pr_data = { + "title": "Fix: Optimized SQL Query for User Dashboard", + "description": ( + "I added an index to the User table and refactored the Entity Framework " + "query to avoid N+1 issues." + ), + "diff": """ + --- a/Data/UserRepository.cs + +++ b/Data/UserRepository.cs + @@ -10,5 +10,5 @@ + - var users = context.Users.ToList(); + + var users = context.Users.Include(u => u.Posts).AsNoTracking().ToList(); + """, +} + + +def test_summary(): + print("🚀 Starting Test: Summarizing PR...") + try: + summary = summarize_pr(mock_pr_data) + print("\n--- AI SUMMARY ---") + print(summary) + if summary and "unavailable" not in summary.lower(): + print("\n✅ SUCCESS: A summary was generated.") + else: + print("\n❌ FAILED: No usable summary was produced.") + except Exception as e: + print(f"\n❌ CRITICAL ERROR: {e}") + + +if __name__ == "__main__": + test_summary() diff --git a/codience/Reviewer Testing report .xlsx b/codience/Reviewer Testing report .xlsx new file mode 100644 index 00000000..611377d8 Binary files /dev/null and b/codience/Reviewer Testing report .xlsx differ diff --git a/codience/ReviewerRecommender.md b/codience/ReviewerRecommender.md index 10c6266c..8b8f8379 100644 --- a/codience/ReviewerRecommender.md +++ b/codience/ReviewerRecommender.md @@ -4,19 +4,32 @@ This system automates the selection of pull request reviewers by bridging the ga --- -## 🔄 System Architecture +## 🔄 System Architecture (Smart Caching Architecture) -The system follows a decoupled pipeline to ensure that technical requirements are mapped to organizational roles before assigning specific individuals. +The evolved system leverages a multi-agent, caching-aware workflow designed to maximize accuracy, eliminate local LLM bottlenecks, and drastically reduce redundant LLM calls. ```mermaid graph TD - A[Pull Request Diff] --> B{LLM Skill Extractor} - B -->|Atomic Skills| C[RAG Layer: Role Knowledge Base] - C -->|Required Roles| D{Reviewer Matcher} - E[Dynamic Team Roster] --> D - D -->|Scoring & Logic| F[Recommended Reviewers] - F -->|Justification| G[Final Output] - + A[Pull Request Diff] --> B{PR Agent: Skill Extractor} + B -->|Atomic Skills| C[RAG Layer: Vector DB Role KB] + B -->|Required Languages| D[Developer Pre-Filtering] + + %% Cache & LLM Flow %% + D -->|Candidate Pool| E{ProfileCache Check} + E -->|Cache Hit: Load Skills| F[Merged Developer Profiles] + E -->|Cache Miss| G[GitHub Commit Fetcher] + G -->|Recent Diffs| H[Ollama phi3:mini Skill Analyzer] + H -->|Extracted Skills| I[Save to ProfileCache] + I --> F + + %% Jira & Scorer %% + F --> J{Jira Agent: Workload Focus} + K[.NET Jira Backend: Port 5051] -->|Recent Assigned Tickets| J + J -->|Jira Context| L{Matchmaker Scorer Agent} + C -->|Required Roles| L + + L -->|Tversky Heuristic + AI Scoring| M[Recommended Reviewers] + M --> G1[Final Output with Justification] ``` --- @@ -24,232 +37,157 @@ graph TD ## 📋 Process Flow ### 1. Skill Extraction (The "What") - The system ingests the raw `git diff` and PR metadata. An LLM analyzes the code changes to identify specific technical competencies required to safely review the code. - * **Input:** PR Title, Description, and File Diffs. * **Output:** A weighted list of technical skills (e.g., `React Hooks`, `PostgreSQL Migrations`, `JWT Auth`). ### 2. Role Mapping via RAG (The "Who Type") - To ensure architectural alignment, the system uses **Retrieval-Augmented Generation (RAG)** to map extracted skills to defined organizational roles. - * **Knowledge Base:** A vector database containing "Role Personas" (e.g., Database Administrator, Security Engineer, Frontend Lead). * **Mechanism:** The system queries the Vector DB using the extracted skills to find the most relevant roles. -* **Benefit:** Decouples technical tasks from individual people, making the system adaptable to changing team structures. - -### 3. Candidate Matching (The "Who Specifically") - -Once the required roles are identified, the system cross-references them against the **Dynamic Team Roster** (the current project members). -* **Filtering:** Narrow down the team to individuals currently assigned to the identified roles. -* **Ranking:** Candidates are ranked based on a composite score: -* **Skill Match:** Proficiency in the atomic skills identified in Step 1. -* **Contextual Recency:** Historical activity in the specific files or modules being changed. -* **Workload:** Current number of open PRs assigned to prevent bottlenecks. +### 3. Smart Skill Caching & Commit Fetching (The Optimization) +To avoid evaluating every developer's massive git commit history using the LLM directly (which causes token/memory bottlenecks and API cost issues): +1. **GitHub Commit Fetcher:** Fetches actual commit history dynamically for candidate developers. +2. **Profile Cache (`ProfileCache`):** The system checks if the candidate's skills are already profiled in a local JSON cache. + - **Cache Hit:** Directly loads the developer's historical skills from the cache (0 LLM calls made!). + - **Cache Miss:** Runs the local Ollama LLM (`phi3:mini`) only on the newly fetched commits to deduce skills, then saves them to the cache for future requests. +### 4. Jira Context Analysis (The "Workload Focus") +To avoid assigning reviews to developers focused on completely different tasks, the **Jira Agent** reaches out to the configured `.NET` REST API (`localhost:5051` or custom base URL) to fetch the candidate's recently assigned Jira tickets. It uses the LLM to summarize their active domains of focus *right now*. - -### 4. Recommendation & Justification - -The final output provides a list of suggested reviewers accompanied by a "Reasoning" string generated by the LLM. - -* **Example:** *"Suggested @user123 (Senior Backend) because they have 90% skill overlap with the new Redis implementation and recently modified the Auth module."* +### 5. Matchmaker & Scoring (The "Who Specifically") +The **Matchmaker / Scorer Agent** acts as the "Tech Lead." It blends the following metrics into a **0-100 Confidence Score**: +* **Tversky Similarity Index:** A high-speed file path overlap match comparing files changed in the PR to candidate commit history. +* **Skill Alignment:** Matching cache/LLM skills and active Jira contexts against Vector DB roles. +* **Fallback Mode:** If LLM scoring experiences an error, a robust pure mathematical fallback is triggered to prevent the service from failing. --- -## API Contract (v2) +## 🔌 API Contracts -The system exposes a versioned endpoint for frontend and .NET integration: +The system exposes two versioned endpoints for frontend and .NET orchestrator integration. -- **Method:** `POST` -- **Path:** `/api/recommend/v2` -- **Purpose:** Return reviewer recommendations with required-reviewer handling and configurable ranking weights. +### 1. `/api/recommend/v2` -### Request Parameters +* **Method:** `POST` +* **Purpose:** Returns customized reviewer recommendations with support for explicit candidate profiles. +#### Request Shape ```json { - "owner": "huggingface", - "repo": "transformers", - "pr_number": 44935, - "required_reviewers": ["lvliang-intel", "someone-new"], + "owner": "MalakHisham121", + "repo": "codience-test", + "pr_number": 1, + "required_reviewers": [ + { + "username": "MalakHisham121", + "jira_username": "Malak Hesham", + "raw_skills": ["python", "react", "fastapi"] + } + ], "options": { "top_k": 5, "prioritize_recent_activity": true, "commits_per_reviewer": 50 - } + }, + "jira_token": "YOUR_JIRA_ACCESS_TOKEN", + "jira_cloud_id": "7cb11454-7b11-4eed-a345-54b06f4ce1f7", + "jira_project_key": "SCRUM" } ``` -- `owner`: GitHub organization/user that owns the repository. -- `repo`: Repository name under `owner`. -- `pr_number`: Pull request number in that repository. -- `required_reviewers`: Optional. Frontend-provided usernames that must be evaluated explicitly. -- `options`: Optional object. If omitted, server defaults are used. -- `options.top_k`: Optional override. Default is `5`. -- `options.prioritize_recent_activity`: Optional override. Default is `true` (favor recent commit activity). -- `options.commits_per_reviewer`: Optional override. Default is `50` recent commits per reviewer. - -### Ranking Behavior - -- The ranking always considers skill match. -- When `prioritize_recent_activity=true`, recent activity is blended into preliminary ranking to favor currently active contributors. -- Commit recency is computed from the most recent `commits_per_reviewer` commits per candidate. -- By default, all detected candidate contributors are analyzed; options only customize behavior when provided. -- Required reviewers receive explicit evaluation output even when they are not included in final recommendations. - -### Contributor-Only Policy - -- Recommended reviewers must be contributors of the target repository. -- A required reviewer who is not a repository contributor is returned as: - - `included: false` - - `reasons: ["required_reviewer_not_repo_contributor"]` - -### Response Shape +* `required_reviewers`: List of strings or dicts. Dict entities can provide a custom `jira_username` and `raw_skills` override. +* `options.top_k`: Number of recommendations to return (Default: 5). +* `options.prioritize_recent_activity`: Favor recent commit activity (Default: `true`). +#### Response Shape ```json { - "required_reviewers_result": [ - { - "name": "lvliang-intel", - "included": true, - "confidence_score": 65, - "justification": "...", - "reasons": ["required_reviewer", "recent_activity_priority"] - }, - { - "name": "someone-new", - "included": false, - "confidence_score": 0, - "justification": "Reviewer was required by frontend but is not a contributor of this repository.", - "reasons": ["required_reviewer_not_repo_contributor"] - } - ], "recommended_reviewers": [ { - "name": "candidate-a", - "confidence_score": 72, - "justification": "...", - "reasons": ["strong_skill_match"], - "required_reviewer": false, - "score_breakdown": { - "skill_score": 0.8, - "recency_score": 0.4, - "preliminary_score": 0.67, - "ai_score": 0.71, - "prioritize_recent_activity": true, - "commits_considered_per_reviewer": 50 - } + "name": "MalakHisham121", + "confidence_score": 92, + "justification": "Has explicit Python skills and high file-path similarity, but lacks specific commit history or Jira context for advanced Python idioms..." } - ], - "diagnostics": { - "candidate_pool_size": 42, - "required_reviewers_requested": 2, - "prioritize_recent_activity": true, - "commits_per_reviewer": 50, - "indexed_commit_window": 1000 - } + ] } ``` --- -## 📂 Knowledge Base Structure (RAG) +### 2. `/api/orchestrator` -The Role Knowledge Base consists of structured personas used for vector similarity search. Example entry: +* **Method:** `POST` +* **Purpose:** Orchestrates profiling and scoring across a specified list of fully detailed user entities (highly useful when developers are managed dynamically outside of local VCS indexing). +#### Request Shape ```json { - "Role: Machine Learning Engineer | Details: Python Programming Language SQL Machine Learning Deep Learning Natural Language Processing NLP Data Analytics Machine Learning Algorithms TensorFlow Keras github Bachelor of Technology (B.Tech.), Computer Science GITAM Deemed University ML Engineer Tata Consultancy Services" - + "owner": "MalakHisham121", + "repo": "codience-test", + "pr_number": 1, + "users": [ + { + "github_username": "MalakHisham121", + "jira_username": "Malak Hesham", + "jira_token": "YOUR_JIRA_ACCESS_TOKEN", + "jira_cloud_id": "7cb11454-7b11-4eed-a345-54b06f4ce1f7", + "jira_project_key": "SCRUM", + "raw_skills": ["python", "react", "fastapi"] + } + ], + "commits_per_user": 50, + "options": { + "top_k": 5, + "prioritize_recent_activity": true + } } - ``` ---- - -## 🛠 Tech Stack - -* **LLM:** Groq (primary) with Gemini fallback support -* **Vector DB:** ChromaDB (for Role Knowledge Base) -* **Framework:** LangChain / LlamaIndex / Pre-defined AI Clean Code Frameworks -* **API:** GitHub GraphQL API, .NET Jira Backend - -### LLM Provider Configuration - -The system now supports provider routing through the centralized LLM wrapper. - -Recommended default mode: - -```env -LLM_PROVIDER=groq_primary_gemini_fallback -GROQ_API_KEY=your_groq_key -GROQ_MODEL_PRIMARY=llama-3.3-70b-versatile -GROQ_MODEL_FALLBACKS=llama-3.1-8b-instant - -GEMINI_API_KEY=your_gemini_key -LLM_MODEL_PRIMARY=gemini-3.1-flash-lite-preview -LLM_MODEL_FALLBACKS=gemini-1.5-flash +#### Response Shape +```json +{ + "recommended_reviewers": [ + { + "name": "MalakHisham121", + "confidence_score": 92, + "justification": "Matched based on raw_skills override and dynamic profiling..." + } + ] +} ``` -Supported provider modes: - -- `groq_primary_gemini_fallback` (recommended) -- `gemini_primary_groq_fallback` -- `groq_only` -- `gemini_only` - -Purpose-specific model overrides are supported with either generic keys or provider-specific keys: - -- Generic: `LLM_MODELS_PR_SKILL_EXTRACTION=model-a,model-b` -- Provider-specific: `LLM_MODELS_GROQ_PR_SKILL_EXTRACTION=model-a,model-b` - -All existing agents continue to call the same `generate_with_resilience` wrapper, so no endpoint contract or business-logic changes are required. - --- -## 🚀 Multi-Agent Evolution (v2) & Jira Integration +## 📂 Active Module Structure (`/PRNew/`) -To address input-size limitations and enhance tracking accuracy, the recommendation pipeline has been evolved into a **Stateful Multi-Agent Workflow**, adhering to AI Clean Code standards. +The core engine is structured into clean, modular, and decoupled Python services under the `codience/src/Reviewer_Recommender/PRNew/` package: -### The "Story" of the New Changes (How to Explain It) +### 1. `Reviewer_Engine.py` (The Orchestrator) +The central workflow coordinator. It orchestrates the indexing of repository contributors, checks the local profile cache, calls the GitHub and Jira services, and delegates scoring. It enforces an intelligent **Top 10 Preliminary Pre-Filter** to ensure that local LLM tokens are conserved. -The core challenge was that evaluating every developer's massive git commit history using an LLM directly would result in excessive context limits. -Therefore, we separated the capabilities into isolated "Automated Agents" orchestrating together: +### 2. `profile_cache.py` (The Caching Layer) +Implements a filesystem-based JSON caching architecture for developer skill profiles. It manages loading, updating, and saving developer capabilities to eliminate redundant LLM executions entirely. -1. **The PR Agent** (`extract_pr_skills`): Extracts the required languages and atomic skills from the incoming PR. -2. **The Jira Analyzer Agent** (`jira_agent.py`): Reaches out to the configured `.NET` REST API to fetch a developer's recently assigned Jira tickets. It uses the LLM to deduce what domain (e.g., UI, Database, Auth) the developer is focusing on *right now*. -3. **The Matchmaker / Scorer Agent** (`scorer_agent.py`): Acts as the "Tech Lead". It intakes the PR constraints, the Vector DB recommendations (RAG), and the summarized Jira/commit history, generating a scaled **0-100 Confidence Score** with human-readable rationale. +### 3. `commit_history_utils.py` ( Vcs Client) +Handles GitHub API calls to fetch commit logs. It extracts file paths, changes, and commits, and maps commits to raw developer activities to supply data to the Tversky formula. -### Component Code Explanations (Line-by-Line Concepts) +### 4. `jira_agent.py` (.NET Workload Bridge) +Interfaces with the custom `.NET` JiraController API (`/api/Jira/assigned-tickets`) to pull live assigned Jira tickets for developers, utilizing isolated LLM prompts to summarize what they are actively working on. -#### 1. `Engine_test.py` (The Orchestrator) -**What it does:** It's the central pipeline that ties everything together. -**Line-by-line Breakdown:** -- It calls the PR Agent (`extract_pr_skills`) to find out the requirements. -- It calls `search_vector_db` to get historical role guidance from RAG. -- **The Filter (Crucial Optimization):** Instead of hitting the Jira API and LLM for all 100 historical contributors computationally, it uses a fast mathematical formula `len(matched_skills) / max(req_languages)` to filter the pool down to the **Top 10 Preliminary Candidates**. -- For those 10, it launches `analyze_jira_context` to fetch Jira domains. -- Finally, it aggregates all parameters and triggers the Scorer Agent (`calculate_match_scores`) to assign the final `confidence_score`. +### 5. `scorer_agent.py` (The Matchmaker) +Intakes PR requirements, developer skills, commit metrics, and Jira contexts. It formats them into a strict AI prompt to evaluate confidence scores and output human-readable justifications, backed by a robust math-scoring fallback system. -#### 2. `jira_agent.py` (The Context Gatherer) -**What it does:** Maps a username to their current workload focus. -**Line-by-line Breakdown:** -- Uses the `requests` library to fetch JSON payloads from the `JIRA_API_BASE_URL` (the internal .NET backend). -- Loops through up to 10 recent tickets, merging their titles and descriptions into a singular text block. -- Invokes the LLM by formatting variables into the isolated `JIRA_ANALYSIS_PROMPT`. -- **Clean Code Mechanics:** To enforce structural integrity, it uses `Pydantic (BaseModel)` so the JSON response structurally maps strictly to `{"domain", "recent_skills", "summary"}`. It implements a deterministic `3-max-retries` loop (`json.JSONDecodeError` and `ValidationError` capture) for resilience against hallucinated JSON architectures. +### 6. `prompts.py` (System Prompts) +Isolates hardcoded LLM prompts from business logic, making it easy to tune LLM behavior without editing Python code files. -#### 3. `scorer_agent.py` (The Final Matchmaker) -**What it does:** Eliminates naive language matching by adding smart, contextual semantic AI evaluation. -**Line-by-line Breakdown:** -- Combines the `pr_skills`, the vector database `rag_context`, and loops through mapping out each candidate's raw `commits` + current `Jira Domain`. -- Invokes the LLM using the externalized `SCORER_PROMPT`. -- Parses the string into a JSON array, structurally validating it into `[CandidateScore]` (which enforces the `{name, confidence_score, justification}` structure). -- Sorts the Array descending by score. **Graceful Degradation:** If the LLM throws an exception 3 times in a row, a pure mathematical fallback score logic is immediately executed, guaranteeing the system never crashes. +--- -#### 4. `prompts.py` (AI Clean Code Configurations) -**What it does:** Extracts hardcoded AI instructions away from pure business logic. -**The Concept:** By placing `JIRA_ANALYSIS_PROMPT` and `SCORER_PROMPT` here as top-level variables, they become 'first-class configuration items'. This prevents Python execution logic from being visually polluted by massive strings, allows the team to tweak the LLM constraints easily without introducing python bugs, and strictly enforces **Separation of Concerns**. +## 🛠 Tech Stack & Environment Settings +* **VCS Client:** GitHub REST API v3 +* **Primary LLMs:** Groq (`llama-3.3-70b-versatile`) with Gemini fallback support. +* **Local LLM:** Ollama (`phi3:mini`) for developer skill profiling. +* **Vector DB:** ChromaDB (stores organizational role personas). +* **Jira Integration Backend:** REST API hosted on custom `.NET` server (`port 5051`). diff --git a/codience/src/Reviewer_Recommender/Data/__pycache__/searching_into_vectordb.cpython-312.pyc b/codience/src/Reviewer_Recommender/Data/__pycache__/searching_into_vectordb.cpython-312.pyc index f6ddd7a6..5c128f97 100644 Binary files a/codience/src/Reviewer_Recommender/Data/__pycache__/searching_into_vectordb.cpython-312.pyc and b/codience/src/Reviewer_Recommender/Data/__pycache__/searching_into_vectordb.cpython-312.pyc differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_diff_vectordb.py b/codience/src/Reviewer_Recommender/Data/commit_diff_vectordb.py new file mode 100644 index 00000000..9a3de6f8 --- /dev/null +++ b/codience/src/Reviewer_Recommender/Data/commit_diff_vectordb.py @@ -0,0 +1,63 @@ +import os +import warnings +from langchain_community.vectorstores import Chroma +from langchain_huggingface import HuggingFaceEmbeddings +from langchain_text_splitters import RecursiveCharacterTextSplitter + +import logging +logging.getLogger("transformers").setLevel(logging.ERROR) +logging.getLogger("sentence_transformers").setLevel(logging.ERROR) + +warnings.filterwarnings("ignore", category=UserWarning, module="chromadb") +warnings.filterwarnings("ignore", category=DeprecationWarning) + +CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) +DB_DIR = os.path.join(CURRENT_DIR, "commit_vector_db_minilm") + +# Use MiniLM's modern, lightweight embedding model for faster semantic search +embeddings = HuggingFaceEmbeddings( + model_name="all-MiniLM-L6-v2" +) + +def get_commit_vector_db(): + return Chroma(persist_directory=DB_DIR, embedding_function=embeddings) + +def index_commits_to_db(commits_data: list): + """ + Expects a list of dicts: + [{"author": "username", "sha": "commit_sha", "filename": "file.py", "patch": "diff code..."}] + """ + if not commits_data: + return + + db = get_commit_vector_db() + + # Split large diffs into sensible chunks so the vector search is accurate + text_splitter = RecursiveCharacterTextSplitter(chunk_size=1500, chunk_overlap=200) + + texts = [] + metadatas = [] + + for item in commits_data: + if not item.get("patch"): + continue + + chunks = text_splitter.split_text(item["patch"]) + for chunk in chunks: + texts.append(chunk) + metadatas.append({ + "author": item.get("author", "unknown"), + "sha": item.get("sha", "unknown"), + "filename": item.get("filename", "unknown") + }) + + if texts: + db.add_texts(texts=texts, metadatas=metadatas) + +def search_similar_commits(pr_patch: str, k=20): + if not pr_patch: + return [] + + db = get_commit_vector_db() + results = db.similarity_search(pr_patch, k=k) + return results diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/data_level0.bin b/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/data_level0.bin new file mode 100644 index 00000000..5efb1b9f Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/data_level0.bin differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/header.bin b/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/header.bin new file mode 100644 index 00000000..bb547926 Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/header.bin differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/length.bin b/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/length.bin new file mode 100644 index 00000000..4c4dd366 Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/length.bin differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/link_lists.bin b/codience/src/Reviewer_Recommender/Data/commit_vector_db/7424a9e0-535b-4082-8e0a-654a558a01d6/link_lists.bin new file mode 100644 index 00000000..e69de29b diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db/chroma.sqlite3 b/codience/src/Reviewer_Recommender/Data/commit_vector_db/chroma.sqlite3 new file mode 100644 index 00000000..d7522bf0 Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db/chroma.sqlite3 differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/data_level0.bin b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/data_level0.bin new file mode 100644 index 00000000..f34737f9 Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/data_level0.bin differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/header.bin b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/header.bin new file mode 100644 index 00000000..5387a4fa Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/header.bin differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/index_metadata.pickle b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/index_metadata.pickle new file mode 100644 index 00000000..96d842c4 Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/index_metadata.pickle differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/length.bin b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/length.bin new file mode 100644 index 00000000..b9d451f5 Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/length.bin differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/link_lists.bin b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/link_lists.bin new file mode 100644 index 00000000..6bc6ef48 Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/3abc2e2d-6500-4ccb-97d7-36c1fb468a77/link_lists.bin differ diff --git a/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/chroma.sqlite3 b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/chroma.sqlite3 new file mode 100644 index 00000000..c5b5d39e Binary files /dev/null and b/codience/src/Reviewer_Recommender/Data/commit_vector_db_nomic/chroma.sqlite3 differ diff --git a/codience/src/Reviewer_Recommender/PRNew/Reviewer_Engine.py b/codience/src/Reviewer_Recommender/PRNew/Reviewer_Engine.py index 1d9f2b40..d17cf073 100644 --- a/codience/src/Reviewer_Recommender/PRNew/Reviewer_Engine.py +++ b/codience/src/Reviewer_Recommender/PRNew/Reviewer_Engine.py @@ -2,19 +2,21 @@ import requests from datetime import datetime, timezone from collections import defaultdict -from typing import Any, Dict, List, Optional, Set +from typing import Any, Optional +# pyrefly: ignore [missing-import] from dotenv import load_dotenv -import sys -sys.path.insert(0, '/home/shahd/Desktop/Grduation/codience/src/Reviewer_Recommender/PRNew') from .analysis_PR import extract_pr_skills # Import your history logic - UPDATED IMPORT -from .commit_history_utils import fetch_commits, map_commits_to_skills, load_from_cache, get_cached_author_count, load_multiple_from_cache, fetch_commit_history_for_author +from .commit_history_utils import session, fetch_commits, map_commits_to_skills, load_from_cache, get_cached_author_count, load_multiple_from_cache, fetch_commit_history_for_author # Import AI Agents from .scorer_agent import calculate_match_scores +from .jira_agent import analyze_jira_context +from .evaluator_agent import evaluate_recommendations from ..Data.searching_into_vectordb import search_vector_db +from ..Data.commit_diff_vectordb import search_similar_commits from .profile_cache import ProfileCache load_dotenv() @@ -33,19 +35,19 @@ def fetch_real_pr_data(owner, repo, pr_number): "Accept": "application/vnd.github.v3+json" } - pr_resp = requests.get(pr_url, headers=headers) + pr_resp = session.get(pr_url, headers=headers, timeout=15) if pr_resp.status_code != 200: print(f"❌ Failed to fetch PR info: {pr_resp.status_code}") try: print(f"GitHub Error: {pr_resp.json().get('message')}") - except: + except Exception: print(f"Raw Response: {pr_resp.text}") return None pr_json = pr_resp.json() files_url = f"{pr_url}/files" - files_resp = requests.get(files_url, headers=headers) + files_resp = session.get(files_url, headers=headers, timeout=15) files_data = [] if files_resp.status_code == 200: files_json = files_resp.json() @@ -75,7 +77,7 @@ def fetch_repo_contributors(owner, repo, max_pages=5, per_page=100): for page in range(1, max_pages + 1): url = f"https://api.github.com/repos/{owner}/{repo}/contributors" - resp = requests.get(url, headers=headers, params={"per_page": per_page, "page": page}, timeout=20) + resp = session.get(url, headers=headers, params={"per_page": per_page, "page": page}, timeout=20) if resp.status_code != 200: if page == 1: print(f"⚠️ Could not fetch contributors list: {resp.status_code}") @@ -112,7 +114,7 @@ def __init__(self, owner, repo): self.repo_contributors = set() self._profile_cache = ProfileCache() - def initialize_with_cache_check(self, required_developers: Optional[List[str]] = None, + def initialize_with_cache_check(self, required_developers: Optional[list[str]] = None, max_developers: int = 50, max_commits: int = 500, commits_per_reviewer: int = 50, @@ -136,11 +138,20 @@ def initialize_with_cache_check(self, required_developers: Optional[List[str]] = else: return self._initialize_top_developers(max_developers, max_commits, commits_per_reviewer) - def _initialize_specific_developers(self, required_developers: List[str], + def _initialize_specific_developers(self, required_developers: list[Any], commits_per_reviewer: int, max_commits: int) -> bool: """Initialize for specific developers - skills from cache, commits from GitHub""" - needed_set = set(required_developers) + needed_names = [] + for dev in required_developers: + if isinstance(dev, str): + needed_names.append(dev.strip()) + elif isinstance(dev, dict): + username = dev.get("username") or dev.get("login") + if username: + needed_names.append(username.strip()) + + needed_set = set(needed_names) print(f"🎯 Need {len(needed_set)} specific developers: {', '.join(list(needed_set)[:5])}...") # Step 1: Load skills from cache (NO LLM) @@ -274,7 +285,7 @@ def _initialize_top_developers(self, max_developers: int, max_commits: int, comm print(f"📊 Total commits for Tversky: {len(self.indexed_commits)}") return False - def _fetch_commits_bulk(self, authors: List[str], limit: int = 50) -> Dict[str, List[dict]]: + def _fetch_commits_bulk(self, authors: list[str], limit: int = 50) -> dict[str, list[dict]]: """Fetch commit history for multiple authors in parallel""" from concurrent.futures import ThreadPoolExecutor, as_completed @@ -298,7 +309,7 @@ def _fetch_commits_bulk(self, authors: List[str], limit: int = 50) -> Dict[str, return results - def _fetch_commits_for_author_with_files(self, author_name: str, limit: int = 50) -> List[dict]: + def _fetch_commits_for_author_with_files(self, author_name: str, limit: int = 50) -> list[dict]: """Fetch commits for an author with file details included""" target = max(0, int(limit)) if target <= 0: @@ -315,7 +326,7 @@ def _fetch_commits_for_author_with_files(self, author_name: str, limit: int = 50 while len(collected) < target: batch_size = min(100, target - len(collected)) - resp = requests.get( + resp = session.get( url, headers=headers, params={"author": author_name, "per_page": batch_size, "page": page}, @@ -333,13 +344,13 @@ def _fetch_commits_for_author_with_files(self, author_name: str, limit: int = 50 try: detail_url = commit.get("url") if detail_url: - detail_resp = requests.get(detail_url, headers=headers, timeout=15) + detail_resp = session.get(detail_url, headers=headers, timeout=15) if detail_resp.status_code == 200: detail = detail_resp.json() commit["files"] = detail.get("files", []) else: commit["files"] = [] - except: + except Exception: commit["files"] = [] collected.append(commit) @@ -349,79 +360,7 @@ def _fetch_commits_for_author_with_files(self, author_name: str, limit: int = 50 return collected[:target] - def _process_specific_developers(self, developers: Set[str], commits_per_reviewer: int, max_commits: int): - """Process only specific developers (legacy - kept for compatibility)""" - print(f"🚀 Processing {len(developers)} specific developers...") - - all_commits = [] - seen_shas = set() - - for username in developers: - fetched = self._fetch_commits_for_author(username, commits_per_reviewer) - for commit in fetched: - sha = commit.get("sha") - if sha and sha in seen_shas: - continue - if sha: - seen_shas.add(sha) - all_commits.append(commit) - - self.indexed_commits = all_commits - self.contributor_stats.update(self._build_contributor_stats(all_commits)) - - # Only map skills for these specific developers - repo_key = f"{self.owner}/{self.repo}" - new_profiles = map_commits_to_skills(all_commits, repo=repo_key, specific_authors=list(developers)) - - # Update existing profiles - for author, skills in new_profiles.items(): - self.history_profiles[author] = skills - - print(f"✅ Processed {len(new_profiles)} new developers") - - def _process_top_developers(self, max_developers: int, max_commits: int, need_to_process: int): - """Process only the top N developers we need (legacy - kept for compatibility)""" - print(f"🚀 Fetching top {max_developers} developers (need {need_to_process} new ones)...") - - # Fetch commits and get top developers - commits = fetch_commits(self.owner, self.repo, limit=max_commits) - - # Group commits by author - commits_by_author = defaultdict(list) - for commit in commits: - author = commit.get("author", {}).get("login") or commit.get("commit", {}).get("author", {}).get("name") - if author: - commits_by_author[author].append(commit) - - # Sort by commit count - sorted_authors = sorted(commits_by_author.keys(), - key=lambda a: len(commits_by_author[a]), - reverse=True) - - # Take top N developers - top_authors = sorted_authors[:max_developers] - - # Filter out already cached developers - repo_key = f"{self.owner}/{self.repo}" - - # Filter commits to only top authors - filtered_commits = [] - for commit in commits: - author = commit.get("author", {}).get("login") or commit.get("commit", {}).get("author", {}).get("name") - if author in top_authors: - filtered_commits.append(commit) - - # Process these commits (will auto-skip already cached) - self.indexed_commits = filtered_commits - self.contributor_stats.update(self._build_contributor_stats(filtered_commits)) - - new_profiles = map_commits_to_skills(filtered_commits, repo=repo_key, max_authors=need_to_process) - - # Update existing profiles - for author, skills in new_profiles.items(): - self.history_profiles[author] = skills - - print(f"✅ Added {len(new_profiles)} new developers to cache") + def _initialize_fresh(self, max_developers: int, max_commits: int): """Fresh initialization (ignore cache)""" @@ -464,15 +403,7 @@ def _initialize_fresh(self, max_developers: int, max_commits: int): print(f"✅ Indexed {len(self.history_profiles)} developers.") return False - def initialize_system(self, max_commits=500, max_llm_calls=None, max_developers=50): - """DEPRECATED: Use initialize_with_cache_check instead""" - print("⚠️ initialize_system is deprecated. Use initialize_with_cache_check for smart caching.") - return self._initialize_fresh(max_developers, max_commits) - - def initialize_for_required_only(self, required_reviewers, commits_per_reviewer=50, max_llm_calls=20): - """DEPRECATED: Use initialize_with_cache_check instead""" - print("⚠️ initialize_for_required_only is deprecated. Use initialize_with_cache_check for smart caching.") - return self._initialize_specific_developers(required_reviewers, commits_per_reviewer, 500) + def _parse_commit_datetime(self, date_value): if not date_value: @@ -553,7 +484,8 @@ def _normalize_required_reviewers(self, required_reviewers): key = clean_name.lower() required_map[key] = { "username": clean_name, - "raw_skills": [] + "raw_skills": [], + "jira_username": None } elif isinstance(reviewer, dict): username = reviewer.get("username") or reviewer.get("login") @@ -561,7 +493,8 @@ def _normalize_required_reviewers(self, required_reviewers): key = username.strip().lower() required_map[key] = { "username": username.strip(), - "raw_skills": reviewer.get("raw_skills", []) + "raw_skills": reviewer.get("raw_skills", []), + "jira_username": reviewer.get("jira_username") } return required_map @@ -593,7 +526,7 @@ def _fetch_commits_for_author(self, author_name, limit): page = 1 while len(collected) < target: batch_size = min(100, target - len(collected)) - resp = requests.get( + resp = session.get( url, headers=headers, params={"author": author_name, "per_page": batch_size, "page": page}, @@ -658,7 +591,7 @@ def recommend(self, pr_data): v2_result = self.recommend_v2(pr_data, required_reviewers=[], options={}) return v2_result.get("recommended_reviewers", []) - def recommend_v2(self, pr_data, required_reviewers=None, options=None): + def recommend_v2(self, pr_data, required_reviewers=None, options=None, jira_token=None, jira_cloud_id=None, jira_project_key=None): options = options or {} raw_top_k = options.get("top_k") top_k = self.DEFAULT_TOP_K if raw_top_k is None else max(1, min(20, int(raw_top_k))) @@ -695,13 +628,23 @@ def recommend_v2(self, pr_data, required_reviewers=None, options=None): required_languages.remove("C#") required_languages.add(".NET") - # 2. Vector DB RAG Search - rag_query = analysis.get('rag_query', '') or ', '.join(required_languages) - try: - rag_roles = search_vector_db(rag_query, k=10) if rag_query else [] - except Exception as e: - print(f"⚠️ Vector DB Search Failed: {e}") - rag_roles = [] + # 2. Vector DB RAG Search (Semantic Candidate Retrieval) + pr_patches = [f.get("patch", "") for f in pr_data.get("files", []) if f.get("patch")] + combined_patch = "\n".join(pr_patches)[:3000] # Limit size for embedding + + vector_db_candidates = {} + rag_roles = [] + if combined_patch: + try: + # Get top 20 matching commit chunks + similar_commits = search_similar_commits(combined_patch, k=20) + for doc in similar_commits: + author = doc.metadata.get("author") + if author: + vector_db_candidates.setdefault(author, []).append(doc.page_content) + print(f"🔍 Vector DB found historically matched authors: {list(vector_db_candidates.keys())}") + except Exception as e: + print(f"⚠️ Vector DB Commit Search Failed: {e}") # 3. Preliminary candidate scoring if required_only_mode: @@ -714,6 +657,10 @@ def recommend_v2(self, pr_data, required_reviewers=None, options=None): candidate_names = set(observed_contributors) if repo_contributors: candidate_names = {name for name in candidate_names if name in repo_contributors} + # Add Vector DB authors to the pool + for author in vector_db_candidates: + if author not in candidate_names and (not repo_contributors or author in repo_contributors): + candidate_names.add(author) preliminary_candidates = [] @@ -762,6 +709,12 @@ def recommend_v2(self, pr_data, required_reviewers=None, options=None): if required_flag: base_composite = min(1.0, base_composite + 0.10) + # Boost if found in Vector DB + rag_code_matches = vector_db_candidates.get(name, []) + if rag_code_matches: + boost = min(0.20, len(rag_code_matches) * 0.05) # +0.05 per chunk match, max 0.20 + base_composite = min(1.0, base_composite + boost) + # Get commit history for this candidate candidate_commit_history = commits_by_author.get(name, []) @@ -774,12 +727,39 @@ def recommend_v2(self, pr_data, required_reviewers=None, options=None): "recency_score": recency_score, "required_reviewer": required_flag, "raw_skills": raw_skills, + "rag_code_matches": rag_code_matches, "prelim_score": round(base_composite, 4), "commit_count": stat.get("commit_count", 0), "tenure_days": stat.get("tenure_days", 365), }) preliminary_candidates = sorted(preliminary_candidates, key=lambda x: x['prelim_score'], reverse=True) + + # === TOP 10 PRE-FILTERING (LLM BOTTLENECK FIX) === + if not required_only_mode and len(preliminary_candidates) > 10: + print(f"🔪 Truncating candidates from {len(preliminary_candidates)} to Top 10 to save LLM tokens.") + preliminary_candidates = preliminary_candidates[:10] + # Update candidate_names so debug output below matches what is sent to LLM + candidate_names = {c["name"] for c in preliminary_candidates} + + # === JIRA ANALYSIS (For Top Candidates Only) === + if jira_token and jira_cloud_id and jira_project_key: + print(f"\n🎫 Fetching Jira Context for Top {len(preliminary_candidates)} Candidates...") + for c in preliminary_candidates: + # Find Jira username if provided in required_reviewers, else fallback to github name + meta = required_map.get(c["name"].lower(), {}) + j_user = meta.get("jira_username") or meta.get("username", c["name"]) + + jira_result = analyze_jira_context( + username=c["name"], + jira_username=j_user, + token=jira_token, + cloud_id=jira_cloud_id, + project_key=jira_project_key + ) + c["jira_context"] = jira_result + else: + print(f"\n⚠️ Skipping Jira Analysis: Missing Jira credentials (token, cloud_id, project_key).") # 5. Get PR file paths for Tversky scoring pr_file_paths = [f.get("filename") for f in pr_data.get("files", []) if f.get("filename")] @@ -802,55 +782,80 @@ def recommend_v2(self, pr_data, required_reviewers=None, options=None): print(f"\n🔍 DEBUG: PR files being compared:") for f in pr_file_paths[:10]: print(f" - {f}") - ai_rankings = calculate_match_scores( - pr_analysis=analysis, - rag_roles=rag_roles, - candidates=preliminary_candidates, - pr_file_paths=pr_file_paths, - repo=f"{self.owner}/{self.repo}", - cache=self._profile_cache, - prioritize_recent=prioritize_recent_activity - ) - ai_by_name = {r.get("name", "").lower(): r for r in ai_rankings} - - final_candidates = [] - for c in preliminary_candidates: - ai_result = ai_by_name.get(c["name"].lower(), {}) - ai_score = float(ai_result.get("confidence_score", 0)) / 100.0 - final_score = ai_result.get("confidence_score", 0) - reasons = c.get("reasons", []) - if not reasons: - if c.get("required_reviewer"): - reasons.append("required_reviewer") - if c.get("skill_score", 0) >= 0.5: - reasons.append("strong_skill_match") - if prioritize_recent_activity and c.get("recency_score", 0) >= 0.5: - reasons.append("recent_activity_priority") - - final_candidates.append({ - "name": c["name"], - "confidence_score": final_score, - "justification": ai_result.get("justification", "Tversky-based scoring with AI enhancement."), - "reasons": reasons, - "required_reviewer": c.get("required_reviewer", False), - "score_breakdown": ai_result.get("score_breakdown", { - "skill_score": c.get("skill_score", 0), - "recency_score": c.get("recency_score", 0), - "preliminary_score": c.get("prelim_score", 0), - "ai_score": round(ai_score, 4), - }), - }) + max_retries = 1 + current_retry = 0 + judge_feedback = None + recommended = [] + + while current_retry <= max_retries: + if current_retry > 0: + print(f"🔄 Re-evaluating with judge feedback (Attempt {current_retry + 1}/{max_retries + 1})...") + + ai_rankings = calculate_match_scores( + pr_analysis=analysis, + rag_roles=rag_roles, + candidates=preliminary_candidates, + pr_file_paths=pr_file_paths, + repo=f"{self.owner}/{self.repo}", + cache=self._profile_cache, + prioritize_recent=prioritize_recent_activity, + judge_feedback=judge_feedback + ) + ai_by_name = {r.get("name", "").lower(): r for r in ai_rankings} + + final_candidates = [] + for c in preliminary_candidates: + ai_result = ai_by_name.get(c["name"].lower(), {}) + ai_score = float(ai_result.get("confidence_score", 0)) / 100.0 + final_score = ai_result.get("confidence_score", 0) + + reasons = c.get("reasons", []) + if not reasons: + if c.get("required_reviewer"): + reasons.append("required_reviewer") + if c.get("skill_score", 0) >= 0.5: + reasons.append("strong_skill_match") + if prioritize_recent_activity and c.get("recency_score", 0) >= 0.5: + reasons.append("recent_activity_priority") + + final_candidates.append({ + "name": c["name"], + "confidence_score": final_score, + "justification": ai_result.get("justification", "Tversky-based scoring with AI enhancement."), + "reasons": reasons, + "required_reviewer": c.get("required_reviewer", False), + "score_breakdown": ai_result.get("score_breakdown", { + "skill_score": c.get("skill_score", 0), + "recency_score": c.get("recency_score", 0), + "preliminary_score": c.get("prelim_score", 0), + "ai_score": round(ai_score, 4), + }), + }) - final_candidates.sort(key=lambda x: x["confidence_score"], reverse=True) + final_candidates.sort(key=lambda x: x["confidence_score"], reverse=True) - if required_only_mode: - recommended = final_candidates[:top_k] - else: - recommended = [ - c for c in final_candidates - if c["name"].lower() not in required_set - ][:top_k] + if required_only_mode: + recommended = final_candidates[:top_k] + else: + recommended = [ + c for c in final_candidates + if c["name"].lower() not in required_set + ][:top_k] + + print(f"\n⚖️ Passing top {len(recommended)} recommendations to LLM Judge...") + judge_result = evaluate_recommendations(pr_data, recommended) + + if judge_result.get("accepted"): + print("✅ Judge accepted the recommendations.") + break + else: + judge_feedback = judge_result.get("feedback") + print(f"❌ Judge rejected the recommendations. Feedback: {judge_feedback}") + current_retry += 1 + + if current_retry > max_retries: + print("⚠️ Max retries reached. Returning best available recommendations despite judge's rejection.") return { "recommended_reviewers": recommended, diff --git a/codience/src/Reviewer_Recommender/PRNew/batch_skill_extractor.py b/codience/src/Reviewer_Recommender/PRNew/batch_skill_extractor.py new file mode 100644 index 00000000..1572b105 --- /dev/null +++ b/codience/src/Reviewer_Recommender/PRNew/batch_skill_extractor.py @@ -0,0 +1,125 @@ +import os +import sys +import json +import requests +from pathlib import Path + +# Add project root to python path to import internal modules +PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent.parent.parent +sys.path.insert(0, str(PROJECT_ROOT)) +sys.path.insert(0, str(Path(__file__).resolve().parent)) + +# pyrefly: ignore [missing-import] +from dotenv import load_dotenv + +from codience.src.Reviewer_Recommender.PRNew.commit_history_utils import fetch_commit_history_for_author, save_checkpoint + +load_dotenv() + +# --- CONFIGURATION --- +TARGET_OWNER = "huggingface" +TARGET_REPO = "transformers" +COMMITS_TO_ANALYZE = 3 # Reduced for low-RAM speed +OLLAMA_URL = "http://localhost:11434/api/generate" +OLLAMA_MODEL = "qwen2.5:0.5b" + +# List of developers you want to extract skills for +DEVELOPERS_TO_PROFILE = [ + "ArthurZucker", + "younesbelkada", + # Add more usernames here... +] + +def extract_skills_with_ollama(commit_history) -> set: + """ + Takes a developer's commit history and sends it to local Llama3 + to extract rich architectural skills. + """ + if not commit_history: + return set() + + print(f" 🧠 Compiling diffs for {len(commit_history)} commits...") + + # Combine commit messages and diffs into a prompt + combined_text = "" + for commit in commit_history: + msg = commit.get("commit", {}).get("message", "") + files = commit.get("files", []) + + diff_summaries = [] + for f in files: + filename = f.get("filename", "") + patch = f.get("patch", "")[:300] # Take first 300 chars of diff to save context + if patch: + diff_summaries.append(f"File: {filename}\nDiff: {patch}") + + combined_text += f"\nCommit Message: {msg}\nChanges:\n" + "\n".join(diff_summaries) + "\n---\n" + + prompt = f""" +You are an expert Senior Software Architect analyzing a developer's commit history. +Based on the following commit messages and code diffs, extract the high-level technical skills, +frameworks, and architectural patterns this developer is proficient in. + +Focus on rich skills like "Dependency Injection", "State Management", "Concurrency", "React Hooks", "PyTorch Optimization", "CI/CD", etc. +DO NOT return generic terms like "bug fixing" or "coding". + +Commit History: +{combined_text[:6000]} # Limit to 6000 chars + +Return ONLY a valid JSON list of strings representing the skills. Example: ["React", "State Management", "Authentication"] +""" + + print(f" 🤖 Sending to Local Ollama ({OLLAMA_MODEL})...") + try: + response = requests.post(OLLAMA_URL, json={ + "model": OLLAMA_MODEL, + "prompt": prompt, + "stream": False, + "format": "json" # Forces Ollama to return JSON + }, timeout=300) # Increased timeout to 5 minutes for slow hardware + + if response.status_code == 200: + result_json = response.json() + raw_text = result_json.get("response", "[]") + skills = set(json.loads(raw_text)) + return skills + else: + print(f" ❌ Ollama Error: {response.status_code} - {response.text}") + return set() + except requests.exceptions.ConnectionError: + print(f" ❌ Failed to connect to Ollama at {OLLAMA_URL}. Is it running?") + return set() + except json.JSONDecodeError: + print(f" ❌ Failed to parse Ollama output as JSON.") + return set() + except Exception as e: + print(f" ❌ Error calling Local LLM: {e}") + return set() + +def run_batch_extraction(): + print("🚀 Starting Batch Skill Extraction via Local LLM...") + + for author in DEVELOPERS_TO_PROFILE: + print(f"\n👨‍💻 Processing developer: {author}") + + # 1. Fetch their commit history from GitHub + print(" 📡 Fetching commits from GitHub API...") + commits = fetch_commit_history_for_author(author, TARGET_OWNER, TARGET_REPO, limit=COMMITS_TO_ANALYZE) + + if not commits: + print(f" ⚠️ No commits found for {author}.") + continue + + # 2. Extract deep skills using local LLM + skills = extract_skills_with_ollama(commits) + + if skills: + print(f" ✅ Extracted {len(skills)} skills: {', '.join(skills)}") + # 3. Save directly to your existing cache + repo_key = f"{TARGET_OWNER}/{TARGET_REPO}" + save_checkpoint(author, skills, repo_key) + else: + print(f" ⚠️ No skills extracted for {author}.") + +if __name__ == "__main__": + run_batch_extraction() diff --git a/codience/src/Reviewer_Recommender/PRNew/commit_history_utils.py b/codience/src/Reviewer_Recommender/PRNew/commit_history_utils.py index a2bdf93c..f7075a79 100644 --- a/codience/src/Reviewer_Recommender/PRNew/commit_history_utils.py +++ b/codience/src/Reviewer_Recommender/PRNew/commit_history_utils.py @@ -3,7 +3,7 @@ import requests import json import re -import concurrent.futures +import re from collections import defaultdict from dotenv import load_dotenv from requests.adapters import HTTPAdapter @@ -11,16 +11,13 @@ import sys import pickle from pathlib import Path -from typing import List, Dict, Optional, Set, Any - -# Add paths to Python path -sys.path.insert(0, '/home/shahd/Desktop/Grduation') -sys.path.insert(0, '/home/shahd/Desktop/Grduation/codience/src/Reviewer_Recommender/PRNew') +from typing import Optional, Any # Imports -from llm import generate_with_resilience, print_rate_limiter_stats -from prompts import FILE_DIFF_SUMMARY_PROMPT, COMMIT_CHUNK_SUMMARY_PROMPT, DEVELOPER_PROFILE_REDUCE_PROMPT -from profile_cache import ProfileCache +from .llm import generate_with_resilience, print_rate_limiter_stats +from .prompts import FILE_DIFF_SUMMARY_PROMPT, COMMIT_CHUNK_SUMMARY_PROMPT, DEVELOPER_PROFILE_REDUCE_PROMPT, MEANINGFUL_COMMIT_FILTER_PROMPT +from .profile_cache import ProfileCache +from codience.src.Reviewer_Recommender.Data.commit_diff_vectordb import index_commits_to_db load_dotenv() GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") @@ -33,7 +30,8 @@ # Initialize persistent cache _profile_cache = ProfileCache() -CHECKPOINT_FILE = "/tmp/commit_skills_checkpoint.json" +import tempfile +CHECKPOINT_FILE = os.path.join(tempfile.gettempdir(), "commit_skills_checkpoint.json") def fetch_commits(owner, repo, limit=300): url = f"{BASE_URL}/repos/{owner}/{repo}/commits" @@ -63,69 +61,106 @@ def fetch_commits(owner, repo, limit=300): page += 1 return collected[:target] - except: + except Exception as e: + print(f"⚠️ Failed to fetch commits: {e}") return [] -# REMOVED: LLM_BUDGET limit - let it run until complete -# No artificial budget - just let rate limiting handle it -llm_calls_made = 0 # Just for tracking, not limiting -SUMMARY_WORKERS = int(os.getenv("SUMMARY_WORKERS", "2")) +EXT_TO_SKILL = { + ".py": "Python", ".js": "JavaScript", ".ts": "TypeScript", ".tsx": "React/TypeScript", + ".jsx": "React", ".cs": "C#/.NET", ".java": "Java", ".go": "Go", ".rb": "Ruby", + ".php": "PHP", ".html": "HTML", ".css": "CSS", ".sql": "SQL", ".sh": "Shell", + ".rs": "Rust", ".cpp": "C++", ".c": "C", ".yml": "CI/CD", ".yaml": "CI/CD", + "Dockerfile": "Docker", "docker-compose": "Docker" +} -def call_llm(prompt, retries=3): - """Call LLM without artificial budget limit""" - global llm_calls_made - llm_calls_made += 1 - - result = generate_with_resilience(prompt, purpose="history_summary", max_retries=retries) - if result.get("ok"): - return result.get("text", "") - - # If LLM fails, return empty string (will retry via rate limiter) - print(f"⚠️ LLM call failed after {result.get('attempts', 0)} attempts") - return "" +KEYWORD_TO_SKILL = { + "auth": "Authentication", "security": "Security", "db": "Database", "sql": "SQL", + "api": "API Development", "performance": "Performance Optimization", "docker": "Docker", + "k8s": "Kubernetes", "test": "Testing/QA", "react": "React", "vue": "Vue", + "aws": "AWS", "azure": "Azure", "gcp": "GCP", "pipeline": "CI/CD", "refactor": "Refactoring" +} -def summarize_file_patch(file_data): - if not file_data.get("patch"): return "" - prompt = FILE_DIFF_SUMMARY_PROMPT.format( - filename=file_data['filename'], - patch=file_data['patch'] +def is_meaningful_commit_ai(commit_message: str, files: list) -> bool: + """Use local LLM to evaluate if a commit contains meaningful skill signals.""" + filenames = [f.get("filename") for f in files if f.get("filename")] + if not filenames or not commit_message: + return False + + filenames_str = ", ".join(filenames[:20]) # Limit to 20 files for token efficiency + + prompt = MEANINGFUL_COMMIT_FILTER_PROMPT.format( + commit_message=commit_message, + filenames_str=filenames_str ) - res = call_llm(prompt) - if not res: - return "" - return f"File: {file_data['filename']}\nSummary: {res}" + + # Call the LLM with a very low max_tokens since we only need YES/NO + response = generate_with_resilience(prompt, max_tokens=5) + + if not response: + # Fallback to true if LLM fails so we don't accidentally drop good data + return True + + return "YES" in response.upper() -def summarize_commit(commit_message, files): - valid_files = [f for f in files if "patch" in f and not f["filename"].endswith(".csv") and not f["filename"].endswith("lock.json") and not f["filename"].endswith("poetry.lock")] +def filter_commit_files(files: list) -> list: + """Remove lockfiles, assets, and docs to save LLM tokens.""" + ignored_extensions = {".md", ".txt", ".png", ".jpg", ".svg", ".csv", ".json"} + ignored_files = {"package-lock.json", "yarn.lock", "poetry.lock", "Pipfile.lock"} - file_summaries = [] - with concurrent.futures.ThreadPoolExecutor(max_workers=SUMMARY_WORKERS) as executor: - results = executor.map(summarize_file_patch, valid_files) - for r in results: - if r: file_summaries.append(r) + filtered = [] + for f in files: + filename = f.get("filename", "").lower() + if not filename: continue + + basename = os.path.basename(filename) + _, ext = os.path.splitext(filename) + + if basename in ignored_files or ext in ignored_extensions: + continue + + # Also skip massive files if patch is too long (over 1000 lines) + patch = f.get("patch", "") + if len(patch) > 50000: # ~1000 lines + continue + + filtered.append(f) + return filtered + +def extract_skills_heuristically(commit_message, files): + skills = set() + msg_lower = commit_message.lower() + for kw, skill in KEYWORD_TO_SKILL.items(): + if re.search(r'\b' + kw + r'\b', msg_lower): + skills.add(skill) - if not file_summaries: - return "" + for f in files: + filename = f.get("filename", "").lower() + if not filename: + continue - prompt = COMMIT_CHUNK_SUMMARY_PROMPT.format( - commit_message=commit_message, - file_summaries="\n\n".join(file_summaries) - ) - return call_llm(prompt) + # Check extensions + _, ext = os.path.splitext(filename) + if ext in EXT_TO_SKILL: + skills.add(EXT_TO_SKILL[ext]) + + # Check specific filenames/paths + if "dockerfile" in filename: + skills.add("Docker") + if "workflows" in filename and (ext == ".yml" or ext == ".yaml"): + skills.add("GitHub Actions") + + return skills def save_checkpoint(author: str, skills: set, repo: str = "huggingface/transformers"): - """Save progress to both cache and checkpoint file""" try: - # Don't save empty profiles if not skills: - print(f"⚠️ Skipping cache for {author} - no skills extracted") return False from collections import Counter skill_profile = Counter({skill.lower(): 1.0 for skill in skills}) - decay_tag = _profile_cache.decay_tag(2.0, 180) + # FIX: Append "_skills" to the tag to prevent collision with multiset_engine + decay_tag = _profile_cache.decay_tag(2.0, 180) + "_skills" _profile_cache.set_profile(repo, author, skill_profile, decay_tag) - # Save to checkpoint file checkpoint = load_checkpoint() checkpoint[author] = list(skills) @@ -144,20 +179,20 @@ def load_checkpoint(): try: with open(CHECKPOINT_FILE, 'r') as f: return json.load(f) - except: + except Exception: return {} return {} def load_from_cache(author: str, repo: str = "huggingface/transformers"): """Try to load skills from cache first""" try: - decay_tag = _profile_cache.decay_tag(2.0, 180) + decay_tag = _profile_cache.decay_tag(2.0, 180) + "_skills" profile = _profile_cache.get_profile(repo, author, decay_tag) if profile and len(profile) > 0: # Only return non-empty profiles skills = [skill for skill in profile.keys()] print(f"✅ Loaded {author} from cache ({len(skills)} skills)") return set(skills) - except: + except Exception: pass return None @@ -175,7 +210,7 @@ def get_cached_author_count(repo: str = "huggingface/transformers") -> int: try: checkpoint = load_checkpoint() return len([k for k, v in checkpoint.items() if v]) - except: + except Exception: return 0 def map_commits_to_skills(commits, max_llm_calls=None, repo="huggingface/transformers", @@ -184,8 +219,6 @@ def map_commits_to_skills(commits, max_llm_calls=None, repo="huggingface/transfo Map commits to skills with crash-safe checkpointing. Can filter to specific authors or limit to max_authors. """ - global llm_calls_made - llm_calls_made = 0 # Load existing checkpoint checkpoint = load_checkpoint() @@ -261,39 +294,64 @@ def map_commits_to_skills(commits, max_llm_calls=None, repo="huggingface/transfo author_commits = commits_by_author[author] print(f"\n🔄 [{idx}/{len(authors_to_process)}] Analyzing {author} ({len(author_commits)} commits)...") - commit_summaries = [] + author_skills = set() + for commit_idx, commit in enumerate(author_commits): try: - if commit_idx > 0: - time.sleep(0.5) # Small delay between commits + commit_message = commit.get("commit", {}).get("message", "") + + # FIX: Use existing files if available, otherwise fetch + if "files" in commit and commit["files"]: + files = commit["files"] + else: + if commit_idx > 0: + time.sleep(0.5) + commit_detail = session.get(commit["url"], headers=HEADERS, timeout=15).json() + files = commit_detail.get("files", []) + commit["files"] = files - commit_detail = session.get(commit["url"], headers=HEADERS, timeout=15).json() - commit_message = commit["commit"]["message"] - files = commit_detail.get("files", []) - summary = summarize_commit(commit_message, files) - if summary: - commit_summaries.append(f"Commit: {commit_message[:80].replace('\n',' ')}...\nSummary: {summary}") + # Skip trivial commits using AI filter + if not is_meaningful_commit_ai(commit_message, files): + print(f" 🤖 AI Filtered out trivial commit: {commit_message[:30]}...") + continue + + # Filter out noise (lockfiles, docs, images, giant files) + filtered_files = filter_commit_files(files) + if not filtered_files: + continue # Skip commit if no meaningful files are left + + # Update commit files so LLM only sees filtered files + commit["files"] = filtered_files + files = filtered_files + + + # Prepare data for Vector DB RAG Indexing + to_index = [] + for f in files: + if f.get("patch"): + to_index.append({ + "author": author, + "sha": commit.get("sha", "unknown"), + "filename": f.get("filename", "unknown"), + "patch": f.get("patch") + }) + if to_index: + index_commits_to_db(to_index) + + # Heuristic extraction - NO LLM calls! + skills = extract_skills_heuristically(commit_message, files) + author_skills.update(skills) except Exception as e: print(f" ⚠️ Error on commit {commit_idx + 1}: {e}") continue - # Extract skills from summaries - author_skills = set() - if commit_summaries: - prompt = DEVELOPER_PROFILE_REDUCE_PROMPT.format( - author=author, - commit_summaries="\n\n".join(commit_summaries) - ) - raw_result = call_llm(prompt) - if raw_result: - try: - json_match = re.search(r'\[.*\]', raw_result, re.DOTALL) - skills = json.loads(json_match.group()) if json_match else json.loads(raw_result) - if isinstance(skills, list): - author_skills = set(skills) - except Exception as e: - print(f" ⚠️ Failed to parse skills: {e}") + # Local LLM Extraction! + from .batch_skill_extractor import extract_skills_with_ollama + llm_skills = extract_skills_with_ollama(author_commits) + if llm_skills: + print(f" 🧠 Added LLM skills for {author}: {', '.join(llm_skills)}") + author_skills.update(llm_skills) # Save to dev_skills (even if empty, but we'll skip saving empty) dev_skills[author] = author_skills @@ -304,18 +362,14 @@ def map_commits_to_skills(commits, max_llm_calls=None, repo="huggingface/transfo else: print(f" ⚠️ No skills extracted for {author} - not saving to cache") - print(f" ✅ Completed {author}: {len(author_skills)} skills extracted") + print(f" ✅ Completed {author}: {len(author_skills)} skills extracted (RAG indexed)") print(f" 📊 Progress: {idx}/{len(authors_to_process)} authors processed") - print(f" 📞 LLM calls made so far: {llm_calls_made}") print(f"\n✅ Complete! Processed {len(dev_skills)} total developers") - # Print rate limiter stats - print_rate_limiter_stats() - return dev_skills # Add this helper function to get commit history without LLM -def fetch_commit_history_for_author(author: str, owner: str, repo: str, limit: int = 50) -> List[dict]: +def fetch_commit_history_for_author(author: str, owner: str, repo: str, limit: int = 50) -> list[dict]: """Fetch commit history for a specific author from GitHub API.""" url = f"{BASE_URL}/repos/{owner}/{repo}/commits" headers = {"Authorization": f"token {GITHUB_TOKEN}", "Accept": "application/vnd.github+json"} @@ -341,7 +395,7 @@ def fetch_commit_history_for_author(author: str, owner: str, repo: str, limit: i try: detail = session.get(commit["url"], headers=headers, timeout=15).json() commit["files"] = detail.get("files", []) - except: + except Exception: commit["files"] = [] collected.append(commit) @@ -351,7 +405,7 @@ def fetch_commit_history_for_author(author: str, owner: str, repo: str, limit: i return collected[:limit] -def fetch_commit_history_bulk(authors: List[str], owner: str, repo: str, limit: int = 50) -> Dict[str, List[dict]]: +def fetch_commit_history_bulk(authors: list[str], owner: str, repo: str, limit: int = 50) -> dict[str, list[dict]]: """ Fetch commit history for multiple authors in parallel. NO LLM calls - pure GitHub API. diff --git a/codience/src/Reviewer_Recommender/PRNew/evaluator_agent.py b/codience/src/Reviewer_Recommender/PRNew/evaluator_agent.py new file mode 100644 index 00000000..4359e8c5 --- /dev/null +++ b/codience/src/Reviewer_Recommender/PRNew/evaluator_agent.py @@ -0,0 +1,74 @@ +import json +import re +from typing import Dict, Any, List + +import sys +import os + +# Add to sys.path if needed based on structure +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + +from .llm import generate_with_resilience +from .prompts import JUDGE_EVALUATION_PROMPT + +def evaluate_recommendations(pr_data: Dict[str, Any], recommendations: List[Dict[str, Any]]) -> Dict[str, Any]: + """ + Evaluates the proposed recommendations using an LLM-as-a-judge. + Returns a dict with 'accepted' (bool) and 'feedback' (str). + """ + if not recommendations: + return {"accepted": True, "feedback": "No recommendations provided to evaluate."} + + # Format PR Data + title = pr_data.get("title", "No Title") + description = pr_data.get("description", "No Description") + + # Format Reviewers + reviewers_lines = [] + for i, rec in enumerate(recommendations, 1): + name = rec.get("name", f"Reviewer_{i}") + score = rec.get("confidence_score", 0) + justification = rec.get("justification", "No justification") + reasons = ", ".join(rec.get("reasons", [])) + reviewers_lines.append( + f"{i}. Name: {name}\n" + f" Score: {score}/100\n" + f" Justification: {justification}\n" + f" Reasons: {reasons}" + ) + reviewers_text = "\n\n".join(reviewers_lines) + + prompt = JUDGE_EVALUATION_PROMPT.format( + title=title, + description=description, + reviewers_text=reviewers_text + ) + + result = generate_with_resilience(prompt, purpose="evaluator_judge") + if not result.get("ok"): + print(f"⚠️ Evaluator LLM failed: {result.get('reason')}") + # Default to accepted if the judge fails, to avoid breaking the pipeline + return {"accepted": True, "feedback": f"Judge unavailable: {result.get('reason')}"} + + try: + cleaned = re.sub(r"```(?:json)?|```", "", result.get("text", "")).strip() + match = re.search(r"\{.*\}", cleaned, re.DOTALL) + parsed = json.loads(match.group() if match else cleaned) + + # Depending on the model, boolean might come back as string 'true'/'false' + raw_accepted = parsed.get("accepted", True) + if isinstance(raw_accepted, str): + accepted = raw_accepted.lower() == 'true' + else: + accepted = bool(raw_accepted) + + feedback = str(parsed.get("feedback", "")) + + return { + "accepted": accepted, + "feedback": feedback + } + except Exception as exc: + print(f"⚠️ Evaluator parse error: {exc}") + # Default to accepted if parsing fails + return {"accepted": True, "feedback": f"Parse error: {exc}"} diff --git a/codience/src/Reviewer_Recommender/PRNew/jira_agent.py b/codience/src/Reviewer_Recommender/PRNew/jira_agent.py index ef0342ef..c0f09010 100644 --- a/codience/src/Reviewer_Recommender/PRNew/jira_agent.py +++ b/codience/src/Reviewer_Recommender/PRNew/jira_agent.py @@ -3,8 +3,6 @@ import json import re from dotenv import load_dotenv -import sys -sys.path.insert(0, '/home/shahd/Desktop/Grduation/codience/src/Reviewer_Recommender/PRNew') from .llm import generate_with_resilience from .prompts import JIRA_ANALYSIS_PROMPT diff --git a/codience/src/Reviewer_Recommender/PRNew/llm.py b/codience/src/Reviewer_Recommender/PRNew/llm.py index b1641f37..165f729d 100644 --- a/codience/src/Reviewer_Recommender/PRNew/llm.py +++ b/codience/src/Reviewer_Recommender/PRNew/llm.py @@ -23,7 +23,7 @@ from dotenv import load_dotenv # Import rate limiter -from llm_rate_limiter import rate_limiter +from .llm_rate_limiter import rate_limiter # Use only openai package for all providers from openai import OpenAI diff --git a/codience/src/Reviewer_Recommender/PRNew/prompts.py b/codience/src/Reviewer_Recommender/PRNew/prompts.py index cef0855d..8d3b1cb1 100644 --- a/codience/src/Reviewer_Recommender/PRNew/prompts.py +++ b/codience/src/Reviewer_Recommender/PRNew/prompts.py @@ -118,4 +118,38 @@ {pr_text} Return JSON only: {{"seniority_signals": ["signal1", "signal2"]}} +""" + +MEANINGFUL_COMMIT_FILTER_PROMPT = """ +You are an expert engineering manager. Analyze the following commit to determine if it provides meaningful evidence of a developer's technical skills (e.g., writing logic, designing architecture, fixing complex bugs). + +Commit Message: {commit_message} +Files Modified: {filenames_str} + +Is this a meaningful commit for skill profiling? +Ignore trivial commits like "merge branch", typo fixes, or automated dependency updates. + +Reply with EXACTLY ONE WORD: "YES" or "NO". +""" + +JUDGE_EVALUATION_PROMPT = """ +You are an expert Engineering Manager evaluating the proposed reviewers for a Pull Request. + +PULL REQUEST DATA: +Title: {title} +Description: {description} + +PROPOSED REVIEWERS: +{reviewers_text} + +Task: +Evaluate whether this list of reviewers is acceptable and appropriate for the given PR. +Consider their technical skills, historical relevance, and score justifications. +Are there obvious mismatches? Are the top reviewers actually qualified based on their skills and the PR's languages/skills? + +Return your evaluation as a valid JSON object strictly matching this schema: +{{ + "accepted": true/false, + "feedback": "string (If accepted, say 'Looks good'. If rejected, provide specific, actionable feedback to the recommendation agent on what to improve, e.g., 'Candidate X lacks Java skills but the PR is in Java. Please prioritize Java developers.')" +}} """ \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/PRNew/scorer_agent.py b/codience/src/Reviewer_Recommender/PRNew/scorer_agent.py index b6ea85d5..623bbc73 100644 --- a/codience/src/Reviewer_Recommender/PRNew/scorer_agent.py +++ b/codience/src/Reviewer_Recommender/PRNew/scorer_agent.py @@ -65,7 +65,10 @@ def _tversky_bulk( """Bulk Tversky scoring with caching and debugging.""" m_c = commit_multiset(pr_file_paths) pr_hash = ProfileCache.hash_pr(pr_file_paths) - dtag = ProfileCache.decay_tag(DECAY_FACTOR, DECAY_HALFLIFE) + + date_str = ref.strftime("%Y-%m-%d") + base_dtag = ProfileCache.decay_tag(DECAY_FACTOR, DECAY_HALFLIFE) + dtag = f"{base_dtag}_{date_str}" out = {} # DEBUG: Print PR files @@ -142,6 +145,7 @@ def _call_llm_scorer( rag_roles: list, candidates: List[dict], tv_by_name: Dict[str, float], + judge_feedback: Optional[str] = None, ) -> List[dict]: """Call LLM for AI scoring with Tversky as context.""" if not candidates: @@ -151,11 +155,23 @@ def _call_llm_scorer( for i, c in enumerate(candidates, 1): name = c.get("name", f"Candidate_{i}") tv = tv_by_name.get(name, 0.0) + + rag_matches = c.get("rag_code_matches", []) + rag_text = f"\n Historically Matched Code Diffs: {' | '.join(rag_matches)[:500]}..." if rag_matches else "" + + jira_ctx = c.get("jira_context", {}) + jira_text = "" + if jira_ctx: + j_domain = jira_ctx.get("domain", "Unknown") + j_skills = ", ".join(jira_ctx.get("recent_skills", [])) + j_summary = jira_ctx.get("summary", "") + jira_text = f"\n Jira Context: Domain={j_domain}, Skills={j_skills}, Summary={j_summary}" + lines.append( f"Candidate {i}: {name}\n" f" Tversky file-path similarity: {tv:.3f}\n" f" Commit skills: {', '.join(c.get('commit_skills', [])) or 'none'}\n" - f" Explicit skills: {', '.join(c.get('raw_skills', [])) or 'none'}" + f" Explicit skills: {', '.join(c.get('raw_skills', [])) or 'none'}{rag_text}{jira_text}" ) rag_ctx = "\n".join(f"- {r.page_content}" for r in rag_roles) if rag_roles else "No vector DB match." @@ -172,6 +188,9 @@ def _call_llm_scorer( candidates_text="\n\n".join(lines), ) + if judge_feedback: + prompt += f"\n\nJUDGE FEEDBACK FROM PREVIOUS RUN:\n{judge_feedback}\nPlease address this feedback in your scoring by adjusting the scores or ranking accordingly." + result = generate_with_resilience(prompt, purpose="candidate_scoring") if not result.get("ok"): print(f"⚠️ Scorer LLM failed: {result.get('reason')}") @@ -195,6 +214,7 @@ def calculate_match_scores( cache: Optional[ProfileCache] = None, prioritize_recent: bool = True, ref_date: Optional[datetime] = None, + judge_feedback: Optional[str] = None, ) -> List[Dict[str, Any]]: """ Score all candidates using Tversky + AI + supporting signals. @@ -225,7 +245,7 @@ def calculate_match_scores( print(f" 📊 Tversky: scored {len(tv_scores)} candidates.") # 2. AI scores - ai_results = _call_llm_scorer(pr_analysis, rag_roles, candidates, tv_scores) + ai_results = _call_llm_scorer(pr_analysis, rag_roles, candidates, tv_scores, judge_feedback=judge_feedback) ai_by_name = {r["name"].lower(): r for r in ai_results} # 3. Apply formula diff --git a/codience/src/Reviewer_Recommender/Process/Engine_test.py b/codience/src/Reviewer_Recommender/Process/Engine_test.py deleted file mode 100644 index db716369..00000000 --- a/codience/src/Reviewer_Recommender/Process/Engine_test.py +++ /dev/null @@ -1,566 +0,0 @@ -import os -import requests -from datetime import datetime, timezone -from typing import Any, Dict, List -from dotenv import load_dotenv -from codience.src.Reviewer_Recommender.Process.analysis_PR import extract_pr_skills - -# Import your history logic -from codience.src.Reviewer_Recommender.Process.Reviewer_Engine_Helper import fetch_commits, map_commits_to_skills - -# Import AI Agents -from codience.src.Reviewer_Recommender.Process.jira_agent import analyze_jira_context -from codience.src.Reviewer_Recommender.Process.scorer_agent import calculate_match_scores -from codience.src.Reviewer_Recommender.Data.searching_into_vectordb import search_vector_db - -load_dotenv() - -# --- 1. FETCH REAL DATA --- -def fetch_real_pr_data(owner, repo, pr_number): - print(f"📡 Fetching Real PR #{pr_number} from {owner}/{repo}...") - pr_url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{pr_number}" - headers = { - "Authorization": f"token {os.getenv('GITHUB_TOKEN')}", - "Accept": "application/vnd.github.v3+json" - } - - pr_resp = requests.get(pr_url, headers=headers) - if pr_resp.status_code != 200: - print(f"❌ Failed to fetch PR info: {pr_resp.status_code}") - try: - print(f"GitHub Error: {pr_resp.json().get('message')}") - except: - print(f"Raw Response: {pr_resp.text}") - return None - - pr_json = pr_resp.json() - - files_url = f"{pr_url}/files" - files_resp = requests.get(files_url, headers=headers) - files_data = [] - if files_resp.status_code == 200: - files_json = files_resp.json() - for f in files_json: - if "patch" in f and not f["filename"].endswith("lock.json") and not f["filename"].endswith("poetry.lock"): - files_data.append({ - "filename": f["filename"], - "patch": f["patch"] - }) - # Cap at 30 files to avoid excessive API calls - files_data = files_data[:30] - else: - print(f"⚠️ Failed to fetch PR files: {files_resp.status_code}") - - return { - "title": pr_json.get("title"), - "description": pr_json.get("body") or "No description provided.", - "files": files_data - } - - -def fetch_repo_contributors(owner, repo, max_pages=5, per_page=100): - contributors = set() - headers = { - "Authorization": f"token {os.getenv('GITHUB_TOKEN')}", - "Accept": "application/vnd.github.v3+json", - } - - for page in range(1, max_pages + 1): - url = f"https://api.github.com/repos/{owner}/{repo}/contributors" - resp = requests.get(url, headers=headers, params={"per_page": per_page, "page": page}, timeout=20) - if resp.status_code != 200: - if page == 1: - print(f"⚠️ Could not fetch contributors list: {resp.status_code}") - break - - items = resp.json() or [] - if not items: - break - - for item in items: - login = (item or {}).get("login") - if login: - contributors.add(login) - - if len(items) < per_page: - break - - return contributors - - - -# --- THE ENGINE --- -class ReviewerRecommender: - DEFAULT_TOP_K = 5 - DEFAULT_PRIORITIZE_RECENT_ACTIVITY = True - DEFAULT_COMMITS_PER_REVIEWER = 50 - - def __init__(self, owner, repo): - self.owner = owner - self.repo = repo - self.indexed_commits = [] - self.history_profiles = {} - self.contributor_stats = {} - self.repo_contributors = set() - - def initialize_system(self, max_commits=1000, max_llm_calls=40): - print(f"🚀 Building Knowledge Base from last {max_commits} commits...") - self.repo_contributors = fetch_repo_contributors(self.owner, self.repo) - commits = fetch_commits(self.owner, self.repo, limit=max_commits) - self.indexed_commits = commits - self.contributor_stats = self._build_contributor_stats(commits) - self.history_profiles = map_commits_to_skills(commits, max_llm_calls=max_llm_calls) - - # Keep contributors visible in the candidate pool even if skill extraction failed. - for author in self.contributor_stats: - self.history_profiles.setdefault(author, set()) - - print(f"✅ Indexed {len(self.history_profiles)} developers.") - - def initialize_for_required_only(self, required_reviewers, commits_per_reviewer=50, max_llm_calls=20): - """ - Lean initialization path used when required_reviewers are explicitly provided. - Skips full repo indexing — fetches commit history ONLY for the listed reviewers. - This is much faster and cheaper than initialize_system. - """ - # Normalize to extract usernames only - usernames = [] - for r in required_reviewers or []: - if isinstance(r, str): - name = r.strip() - elif isinstance(r, dict): - name = (r.get("username") or r.get("login") or "").strip() - else: - continue - if name: - usernames.append(name) - - if not usernames: - return - - print(f"🚀 Targeted init: fetching up to {commits_per_reviewer} commits for {len(usernames)} reviewer(s)...") - all_commits = [] - seen_shas = set() - for username in usernames: - fetched = self._fetch_commits_for_author(username, commits_per_reviewer) - for commit in fetched: - sha = commit.get("sha") - if sha and sha in seen_shas: - continue - if sha: - seen_shas.add(sha) - all_commits.append(commit) - - self.indexed_commits = all_commits - self.contributor_stats = self._build_contributor_stats(all_commits) - self.history_profiles = map_commits_to_skills(all_commits, max_llm_calls=max_llm_calls) - - for author in self.contributor_stats: - self.history_profiles.setdefault(author, set()) - - print(f"✅ Targeted init complete: {len(self.history_profiles)} reviewer(s) profiled.") - - def _parse_commit_datetime(self, date_value): - if not date_value: - return None - try: - normalized = date_value.replace("Z", "+00:00") if isinstance(date_value, str) else date_value - return datetime.fromisoformat(normalized) - except Exception: - return None - - def _build_contributor_stats(self, commits): - now = datetime.now(timezone.utc) - by_author = {} - - for commit in commits: - author = commit.get("author", {}).get("login") or commit.get("commit", {}).get("author", {}).get("name") - if not author: - continue - - date_value = commit.get("commit", {}).get("author", {}).get("date") - parsed_date = self._parse_commit_datetime(date_value) - by_author.setdefault(author, {"count": 0, "dates": []}) - by_author[author]["count"] += 1 - if parsed_date: - by_author[author]["dates"].append(parsed_date) - - stats = {} - for author, data in by_author.items(): - dates = data["dates"] - commits_count = data["count"] - - if dates: - first_seen = min(dates) - last_seen = max(dates) - tenure_days = max((now - first_seen).days, 0) - recency_days = max((now - last_seen).days, 0) - else: - tenure_days = 365 - recency_days = 365 - - recency_score = max(0.0, 1.0 - (min(recency_days, 90) / 90.0)) - - stats[author] = { - "commit_count": commits_count, - "tenure_days": tenure_days, - "recency_days": recency_days, - "recency_score": round(recency_score, 4), - } - - return stats - - def _limit_commits_per_reviewer(self, commits, commits_per_reviewer): - if commits_per_reviewer <= 0: - return commits - - limited = [] - author_counts = {} - for commit in commits or []: - author = commit.get("author", {}).get("login") or commit.get("commit", {}).get("author", {}).get("name") - if not author: - continue - - current_count = author_counts.get(author, 0) - if current_count >= commits_per_reviewer: - continue - - author_counts[author] = current_count + 1 - limited.append(commit) - - return limited - - def _normalize_required_reviewers(self, required_reviewers): - """ - Normalizes required reviewers into a consistent dict mapping. - Supports: - - String (username) - - Dict {"username": "...", "jira_username": "...", "raw_skills": [...]} - """ - required_map = {} - for reviewer in required_reviewers or []: - if isinstance(reviewer, str): - clean_name = reviewer.strip() - if not clean_name: continue - key = clean_name.lower() - required_map[key] = { - "username": clean_name, - "jira_username": None, - "raw_skills": [] - } - elif isinstance(reviewer, dict): - username = reviewer.get("username") or reviewer.get("login") - if not username: continue - key = username.strip().lower() - required_map[key] = { - "username": username.strip(), - "jira_username": reviewer.get("jira_username"), - "raw_skills": reviewer.get("raw_skills", []) - } - return required_map - - def _count_commits_for_author(self, commits, author_name): - target = (author_name or "").lower() - if not target: - return 0 - - count = 0 - for commit in commits or []: - author = commit.get("author", {}).get("login") or commit.get("commit", {}).get("author", {}).get("name") - if author and author.lower() == target: - count += 1 - return count - - def _fetch_commits_for_author(self, author_name, limit): - target = max(0, int(limit or 0)) - if target <= 0: - return [] - - url = f"https://api.github.com/repos/{self.owner}/{self.repo}/commits" - headers = { - "Authorization": f"token {os.getenv('GITHUB_TOKEN')}", - "Accept": "application/vnd.github.v3+json", - } - - collected = [] - page = 1 - while len(collected) < target: - batch_size = min(100, target - len(collected)) - resp = requests.get( - url, - headers=headers, - params={"author": author_name, "per_page": batch_size, "page": page}, - timeout=20, - ) - if resp.status_code != 200: - print(f"⚠️ Could not fetch commits for required reviewer {author_name}: {resp.status_code}") - break - - batch = resp.json() or [] - if not isinstance(batch, list) or not batch: - break - - collected.extend(batch) - if len(batch) < batch_size: - break - page += 1 - - return collected[:target] - - def _ensure_required_reviewers_history(self, required_names, commits_per_reviewer): - if commits_per_reviewer <= 0: - return - - extra_commits = [] - seen_shas = {c.get("sha") for c in self.indexed_commits if c.get("sha")} - - for required_name in required_names: - existing_count = self._count_commits_for_author(self.indexed_commits, required_name) - missing = commits_per_reviewer - existing_count - if missing <= 0: - continue - - fetched = self._fetch_commits_for_author(required_name, missing) - for commit in fetched: - sha = commit.get("sha") - if sha and sha in seen_shas: - continue - if sha: - seen_shas.add(sha) - extra_commits.append(commit) - - if not extra_commits: - return - - self.indexed_commits.extend(extra_commits) - - updated_stats = self._build_contributor_stats(self.indexed_commits) - self.contributor_stats.update(updated_stats) - - extra_profiles = map_commits_to_skills(extra_commits, max_llm_calls=10) - for author, skills in extra_profiles.items(): - self.history_profiles.setdefault(author, set()) - self.history_profiles[author].update(skills) - - def _resolve_valid_required_contributors(self, required_map): - if not required_map: - return [] - - # Return all usernames from required_map. - # We will try to fetch their GitHub history if it exists, but we won't exclude them yet. - return [r["username"] for r in required_map.values()] - - def recommend(self, pr_data): - v2_result = self.recommend_v2(pr_data, required_reviewers=[], options={}) - return v2_result.get("recommended_reviewers", []) - - def recommend_v2(self, pr_data, required_reviewers=None, options=None): - options = options or {} - # top_k controls how many non-required reviewers are returned in the final recommendation list. - raw_top_k = options.get("top_k") - top_k = self.DEFAULT_TOP_K if raw_top_k is None else max(1, min(20, int(raw_top_k))) - # When false, recency is treated equally for all contributors. - raw_prioritize = options.get("prioritize_recent_activity") - if raw_prioritize is None: - prioritize_recent_activity = self.DEFAULT_PRIORITIZE_RECENT_ACTIVITY - else: - prioritize_recent_activity = bool(raw_prioritize) - # Number of most recent commits considered per reviewer for activity signals. - raw_commits_per_reviewer = options.get("commits_per_reviewer") - commits_per_reviewer = ( - self.DEFAULT_COMMITS_PER_REVIEWER - if raw_commits_per_reviewer is None - else max(1, min(100, int(raw_commits_per_reviewer))) - ) - - limited_commits = self._limit_commits_per_reviewer(self.indexed_commits, commits_per_reviewer) - dynamic_stats = self._build_contributor_stats(limited_commits) - - required_map = self._normalize_required_reviewers(required_reviewers) - required_set = set(required_map.keys()) - required_only_mode = bool(required_map) - - valid_required_contributors = self._resolve_valid_required_contributors(required_map) - - # Backfill history only for valid required contributors. - self._ensure_required_reviewers_history(valid_required_contributors, commits_per_reviewer) - - # Recompute dynamic stats after adding required-reviewer history. - limited_commits = self._limit_commits_per_reviewer(self.indexed_commits, commits_per_reviewer) - dynamic_stats = self._build_contributor_stats(limited_commits) - - # 1. PR Analyzer Agent - analysis = extract_pr_skills(pr_data) - required_languages = {lang.strip().title() for lang in analysis.get('detected_languages', [])} - - if "C#" in required_languages: - required_languages.remove("C#") - required_languages.add(".NET") - - # 2. Vector DB RAG Search - rag_query = analysis.get('rag_query', '') or ', '.join(required_languages) - try: - rag_roles = search_vector_db(rag_query, k=10) if rag_query else [] - except Exception as e: - print(f"⚠️ Vector DB Search Failed: {e}") - rag_roles = [] - - # 3. Preliminary candidate scoring - if required_only_mode: - # Strict required mode: evaluate ONLY required reviewers provided in the input. - candidate_names = set() - for key, meta in required_map.items(): - candidate_names.add(meta["username"]) - else: - # No required list provided: analyze all observed repo contributors. - observed_contributors = set(self.history_profiles.keys()) | set(dynamic_stats.keys()) - repo_contributors = set(self.repo_contributors) - candidate_names = set(observed_contributors) - if repo_contributors: - candidate_names = {name for name in candidate_names if name in repo_contributors} - - preliminary_candidates = [] - for name in candidate_names: - dev_skills = set(self.history_profiles.get(name, set())) - matched_skills = required_languages.intersection(dev_skills) if required_languages else set() - skill_score = len(matched_skills) / max(len(required_languages), 1) if required_languages else (1.0 if dev_skills else 0.0) - - stat = dynamic_stats.get(name, self.contributor_stats.get(name, {})) - recency_score = stat.get("recency_score", 0.0) - - # Fetch metadata from required_map if it exists - meta = required_map.get(name.lower(), {}) - required_flag = bool(meta) - raw_skills = meta.get("raw_skills", []) - jira_username = meta.get("jira_username") - - base_composite = skill_score - if prioritize_recent_activity: - base_composite = (0.55 * skill_score) + (0.45 * recency_score) - if required_flag: - base_composite = min(1.0, base_composite + 0.10) - - preliminary_candidates.append({ - "name": name, - "commit_skills": sorted(list(dev_skills)), - "matched_skills": list(matched_skills), - "skill_score": round(skill_score, 4), - "recency_score": recency_score, - "required_reviewer": required_flag, - "raw_skills": raw_skills, - "jira_username": jira_username, - "prelim_score": round(base_composite, 4), - "commit_count": stat.get("commit_count", 0), - "tenure_days": stat.get("tenure_days", 365), - }) - - preliminary_candidates = sorted(preliminary_candidates, key=lambda x: x['prelim_score'], reverse=True) - - # 4. Jira Analyzer Agent (Enrich candidates) - for c in preliminary_candidates: - print(f"🔄 Analyzing Jira Context for {c['name']} (Jira user: {c.get('jira_username') or c['name']})...") - c["jira_context"] = analyze_jira_context(c["name"], jira_username=c.get("jira_username")) - - # 5. Scorer Matchmaker Agent (AI explanation + confidence) - print("🧠 Calculating AI Confidence Scores...") - ai_rankings = calculate_match_scores(analysis, rag_roles, preliminary_candidates) - ai_by_name = {r.get("name", "").lower(): r for r in ai_rankings} - - final_candidates = [] - for c in preliminary_candidates: - ai_result = ai_by_name.get(c["name"].lower(), {}) - ai_score = float(ai_result.get("confidence_score", 0)) / 100.0 - final_score = int(round(100 * ((0.65 * c["prelim_score"]) + (0.35 * ai_score)))) - - reasons = [] - if c.get("required_reviewer"): - reasons.append("required_reviewer") - if c.get("skill_score", 0) >= 0.5: - reasons.append("strong_skill_match") - if prioritize_recent_activity and c.get("recency_score", 0) >= 0.5: - reasons.append("recent_activity_priority") - - final_candidates.append({ - "name": c["name"], - "confidence_score": max(0, min(100, final_score)), - "justification": ai_result.get("justification", "Composite scoring based on skills and recent contributor activity."), - "reasons": reasons, - "required_reviewer": c.get("required_reviewer", False), - "score_breakdown": { - "skill_score": c.get("skill_score", 0), - "recency_score": c.get("recency_score", 0), - "preliminary_score": c.get("prelim_score", 0), - "ai_score": round(ai_score, 4), - "prioritize_recent_activity": prioritize_recent_activity, - "commits_considered_per_reviewer": commits_per_reviewer, - }, - }) - - final_candidates.sort(key=lambda x: x["confidence_score"], reverse=True) - - if required_only_mode: - # In required-only mode, return ranked required reviewers directly. - recommended = final_candidates[:top_k] - else: - recommended = [ - c for c in final_candidates - if c["name"].lower() not in required_set - ][:top_k] - - return { - "recommended_reviewers": recommended, - } - -if __name__ == "__main__": - # Test on a repo that uses your skills (Java/SQL/Web) - # https://api.github.com/repos/huggingface/transformers # 44935 - # https://api.github.com/repos/spring-petclinic/spring-framework-petclinic # 249 - TARGET_OWNER = "huggingface" - TARGET_REPO = "transformers" - PR_NUMBER = 44935 # Example PR number - MAX_COMMITS = int(os.getenv("ENGINE_MAX_COMMITS", "1000")) - MAX_LLM_CALLS = int(os.getenv("ENGINE_MAX_LLM_CALLS", "30")) - - engine = ReviewerRecommender(TARGET_OWNER, TARGET_REPO) - engine.initialize_system(max_commits=MAX_COMMITS, max_llm_calls=MAX_LLM_CALLS) - - real_pr = fetch_real_pr_data(TARGET_OWNER, TARGET_REPO, PR_NUMBER) - - if real_pr: - required_reviewers = [ - {"username": "lvliang-intel", "jira_username": "lvliang_jira", "raw_skills": ["Intel optimizations", "C++", "Performance"]}, - {"username": "jackcook", "jira_username": "jack_jira", "raw_skills": ["Frontend", "React", "Typescript"]}, - {"username": "harshaljanjani", "jira_username": "harshal_jira", "raw_skills": ["Transformers", "NLP", "Python"]}, - {"username": "someone-new", "jira_username": "someone_new_jira", "raw_skills": ["Rust", "PyO3", "Core Optimization"]} - ] - - options = { - "top_k": 5, - "prioritize_recent_activity": True, - "commits_per_reviewer": 5 - } - - print(f"\n🚀 Running restricted analysis for {len(required_reviewers)} reviewers...") - run_output = engine.recommend_v2(real_pr, required_reviewers=required_reviewers, options=options) - results = run_output.get("recommended_reviewers", []) - - print("\n" + "═"*90) - print(f" ACCURACY-MATCH REPORT: {TARGET_REPO}") - print("═"*90) - print(f"{'RANK':<5} | {'DEVELOPER':<18} | {'CONF SCORE':<10} | {'JUSTIFICATION'}") - print("─"*90) - - for i, r in enumerate(results): - icon = "⭐" if i == 0 else " " - conf_score = f"{r.get('confidence_score', 0)}/100" - justif = r.get('justification', '')[:40] + "..." if len(r.get('justification', '')) > 40 else r.get('justification', '') - - print(f"{icon} #{i+1:<2} | {r['name']:<18} | {conf_score:<10} | {justif}") - - print("═"*90) - if results and results[0].get('confidence_score', 0) > 0: - print(f"🏆 BEST MATCH: {results[0]['name']}") - print(f" Reason: {results[0].get('justification', 'N/A')}") - else: - print("⚠️ No strong matches found in recent history.") - print("═"*90) \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/Process/Reviewer_Engine_Helper.py b/codience/src/Reviewer_Recommender/Process/Reviewer_Engine_Helper.py deleted file mode 100644 index d71c35d8..00000000 --- a/codience/src/Reviewer_Recommender/Process/Reviewer_Engine_Helper.py +++ /dev/null @@ -1,185 +0,0 @@ -import os -import time -import requests -import json -import re -import concurrent.futures -from collections import defaultdict -from dotenv import load_dotenv -from requests.adapters import HTTPAdapter -from urllib3.util.retry import Retry -from codience.src.Reviewer_Recommender.Process.llm import generate_with_resilience -from codience.src.Reviewer_Recommender.Process.prompts import FILE_DIFF_SUMMARY_PROMPT, COMMIT_CHUNK_SUMMARY_PROMPT, DEVELOPER_PROFILE_REDUCE_PROMPT - -load_dotenv() -GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") -HEADERS = {"Authorization": f"token {GITHUB_TOKEN}", "Accept": "application/vnd.github+json"} -BASE_URL = "https://api.github.com" - -session = requests.Session() -retries = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504]) -session.mount("https://", HTTPAdapter(max_retries=retries)) - -def fetch_commits(owner, repo, limit=300): - url = f"{BASE_URL}/repos/{owner}/{repo}/commits" - try: - target = max(1, int(limit)) - collected = [] - page = 1 - - while len(collected) < target: - batch_size = min(100, target - len(collected)) - r = session.get( - url, - headers=HEADERS, - params={"per_page": batch_size, "page": page}, - timeout=15, - ) - if r.status_code != 200: - break - - batch = r.json() or [] - if not isinstance(batch, list) or not batch: - break - - collected.extend(batch) - if len(batch) < batch_size: - break - page += 1 - - return collected[:target] - except: - return [] - -# Global counter to avoid burning through API budget -LLM_BUDGET = 100 -llm_calls_made = 0 -SUMMARY_WORKERS = int(os.getenv("SUMMARY_WORKERS", "2")) - -def call_llm(prompt, retries=3): - global llm_calls_made - if llm_calls_made >= LLM_BUDGET: - return "Budget exceeded" - - llm_calls_made += 1 - result = generate_with_resilience(prompt, purpose="history_summary", max_retries=retries) - if result.get("ok"): - return result.get("text", "") - return "" - -def summarize_file_patch(file_data): - if not file_data.get("patch"): return "" - prompt = FILE_DIFF_SUMMARY_PROMPT.format( - filename=file_data['filename'], - patch=file_data['patch'] - ) - res = call_llm(prompt) - if not res or res == "Budget exceeded": return "" - return f"File: {file_data['filename']}\nSummary: {res}" - -def summarize_commit(commit_message, files): - # 1. Map step: Summarize each file - valid_files = [f for f in files if "patch" in f and not f["filename"].endswith(".csv") and not f["filename"].endswith("lock.json") and not f["filename"].endswith("poetry.lock")] - - file_summaries = [] - with concurrent.futures.ThreadPoolExecutor(max_workers=SUMMARY_WORKERS) as executor: - results = executor.map(summarize_file_patch, valid_files) - for r in results: - if r: file_summaries.append(r) - - if not file_summaries: - return "" - - # 2. Reduce step: Summarize the whole commit - prompt = COMMIT_CHUNK_SUMMARY_PROMPT.format( - commit_message=commit_message, - file_summaries="\n\n".join(file_summaries) - ) - return call_llm(prompt) - -def analyze_user_commit_history(author: str, author_commits: list[dict], max_llm_calls=100) -> list[str]: - global llm_calls_made - llm_calls_made = 0 - global LLM_BUDGET - LLM_BUDGET = max_llm_calls - - print(f"🔄 Analyzing history for {author} ({len(author_commits)} commits)...") - commit_summaries = [] - for commit in author_commits: - try: - commit_detail = session.get(commit["url"], headers=HEADERS, timeout=15).json() - commit_message = commit["commit"]["message"] - files = commit_detail.get("files", []) - summary = summarize_commit(commit_message, files) - if summary and summary != "Budget exceeded": - commit_summaries.append(f"Commit: {commit_message[:80].replace('\n',' ')}...\nSummary: {summary}") - time.sleep(0.5) - except Exception as e: - print(f"⚠️ Error processing commit {commit.get('sha','')}: {e}") - continue - - dev_skills = set() - if commit_summaries: - prompt = DEVELOPER_PROFILE_REDUCE_PROMPT.format( - author=author, - commit_summaries="\n\n".join(commit_summaries) - ) - raw_result = call_llm(prompt) - try: - json_match = re.search(r'\[.*\]', raw_result, re.DOTALL) - skills = json.loads(json_match.group()) if json_match else json.loads(raw_result) - if isinstance(skills, list): - for skill in skills: - dev_skills.add(skill) - except Exception as e: - print(f"⚠️ Failed to parse skill JSON for {author}: {e}") - return list(dev_skills) - - -def map_commits_to_skills(commits, max_llm_calls=100): - global llm_calls_made - llm_calls_made = 0 # reset budget for this run - # Optionally limit total LLM calls - global LLM_BUDGET - LLM_BUDGET = max_llm_calls - - commits_by_author = defaultdict(list) - for commit in commits: - author = commit.get("author", {}).get("login") or commit["commit"]["author"]["name"] - commits_by_author[author].append(commit) - - dev_skills = defaultdict(set) - - for author, author_commits in commits_by_author.items(): - print(f"🔄 Analyzing history for {author} ({len(author_commits)} commits)...") - commit_summaries = [] - for commit in author_commits: - try: - # Fetch detailed commit data (including file patches) - commit_detail = session.get(commit["url"], headers=HEADERS, timeout=15).json() - commit_message = commit["commit"]["message"] - files = commit_detail.get("files", []) - # Summarize this single commit (Map step) - summary = summarize_commit(commit_message, files) - if summary and summary != "Budget exceeded": - commit_summaries.append(f"Commit: {commit_message[:80].replace('\n',' ')}...\nSummary: {summary}") - time.sleep(0.5) # basic rate‑limit protection for GitHub - except Exception as e: - print(f"⚠️ Error processing commit {commit.get('sha','')}: {e}") - continue - # Reduce step: build a developer skill profile from the commit summaries - if commit_summaries: - prompt = DEVELOPER_PROFILE_REDUCE_PROMPT.format( - author=author, - commit_summaries="\n\n".join(commit_summaries) - ) - raw_result = call_llm(prompt) - try: - json_match = re.search(r'\[.*\]', raw_result, re.DOTALL) - skills = json.loads(json_match.group()) if json_match else json.loads(raw_result) - if isinstance(skills, list): - for skill in skills: - dev_skills[author].add(skill) - except Exception as e: - print(f"⚠️ Failed to parse skill JSON for {author}: {e}") - return dev_skills \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/Process/__pycache__/Reviewer_Engine_Helper.cpython-312.pyc b/codience/src/Reviewer_Recommender/Process/__pycache__/Reviewer_Engine_Helper.cpython-312.pyc deleted file mode 100644 index c2c7249c..00000000 Binary files a/codience/src/Reviewer_Recommender/Process/__pycache__/Reviewer_Engine_Helper.cpython-312.pyc and /dev/null differ diff --git a/codience/src/Reviewer_Recommender/Process/__pycache__/analysis_PR.cpython-312.pyc b/codience/src/Reviewer_Recommender/Process/__pycache__/analysis_PR.cpython-312.pyc deleted file mode 100644 index 4a790136..00000000 Binary files a/codience/src/Reviewer_Recommender/Process/__pycache__/analysis_PR.cpython-312.pyc and /dev/null differ diff --git a/codience/src/Reviewer_Recommender/Process/__pycache__/llm.cpython-312.pyc b/codience/src/Reviewer_Recommender/Process/__pycache__/llm.cpython-312.pyc deleted file mode 100644 index db2cc7d1..00000000 Binary files a/codience/src/Reviewer_Recommender/Process/__pycache__/llm.cpython-312.pyc and /dev/null differ diff --git a/codience/src/Reviewer_Recommender/Process/__pycache__/main.cpython-312.pyc b/codience/src/Reviewer_Recommender/Process/__pycache__/main.cpython-312.pyc deleted file mode 100644 index 7684efd5..00000000 Binary files a/codience/src/Reviewer_Recommender/Process/__pycache__/main.cpython-312.pyc and /dev/null differ diff --git a/codience/src/Reviewer_Recommender/Process/__pycache__/prompts.cpython-312.pyc b/codience/src/Reviewer_Recommender/Process/__pycache__/prompts.cpython-312.pyc deleted file mode 100644 index 36ca2e7f..00000000 Binary files a/codience/src/Reviewer_Recommender/Process/__pycache__/prompts.cpython-312.pyc and /dev/null differ diff --git a/codience/src/Reviewer_Recommender/Process/__pycache__/tests_prs.cpython-312.pyc b/codience/src/Reviewer_Recommender/Process/__pycache__/tests_prs.cpython-312.pyc deleted file mode 100644 index 4b2885ba..00000000 Binary files a/codience/src/Reviewer_Recommender/Process/__pycache__/tests_prs.cpython-312.pyc and /dev/null differ diff --git a/codience/src/Reviewer_Recommender/Process/analysis_PR.py b/codience/src/Reviewer_Recommender/Process/analysis_PR.py deleted file mode 100644 index 1c0924cd..00000000 --- a/codience/src/Reviewer_Recommender/Process/analysis_PR.py +++ /dev/null @@ -1,55 +0,0 @@ -import json -import os -import re -import concurrent.futures -from codience.src.Reviewer_Recommender.Process.llm import generate_with_resilience -from codience.src.Reviewer_Recommender.Process.prompts import SKILL_EXTRACTION_PROMPT, FILE_DIFF_SUMMARY_PROMPT - -PR_SUMMARY_WORKERS = int(os.getenv("PR_SUMMARY_WORKERS", "3")) - -def summarize_file_diff(file_data): - try: - prompt = FILE_DIFF_SUMMARY_PROMPT.format( - filename=file_data['filename'], - patch=file_data['patch'] - ) - result = generate_with_resilience(prompt, purpose="pr_file_summary") - if not result.get("ok"): - return "" - return f"File: {file_data['filename']}\nSummary: {result.get('text', '').strip()}\n" - except Exception as e: - print(f"⚠️ Failed to summarize file {file_data.get('filename')}: {e}") - return "" - -def extract_pr_skills(pr_data): - files = pr_data.get('files', []) - aggregated_summaries = "" - - if files: - print(f"🚀 Summarizing {len(files)} files in parallel...") - with concurrent.futures.ThreadPoolExecutor(max_workers=PR_SUMMARY_WORKERS) as executor: - summaries = list(executor.map(summarize_file_diff, files)) - aggregated_summaries = "\n".join(summaries) - else: - aggregated_summaries = "No code files changed or diffs available." - - full_prompt = SKILL_EXTRACTION_PROMPT.format( - title=pr_data.get('title', 'N/A'), - description=pr_data.get('description', 'N/A'), - diff=aggregated_summaries - ) - - result = generate_with_resilience(full_prompt, purpose="pr_skill_extraction") - if not result.get("ok"): - return {"required_skills": [], "summary": "Extraction failed", "detected_languages": []} - raw_text = result.get("text", "") - - # Robust JSON extraction - try: - json_match = re.search(r'\{.*\}', raw_text, re.DOTALL) - if json_match: - return json.loads(json_match.group()) - return json.loads(raw_text) - except Exception as e: - print(f"Error: Could not parse LLM output as JSON. Raw text: {raw_text}") - return {"required_skills": [], "summary": "Extraction failed", "detected_languages": []} \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/Process/jira_agent.py b/codience/src/Reviewer_Recommender/Process/jira_agent.py deleted file mode 100644 index 89a71fcb..00000000 --- a/codience/src/Reviewer_Recommender/Process/jira_agent.py +++ /dev/null @@ -1,251 +0,0 @@ -import os -import requests -import json -import re -from dotenv import load_dotenv -from codience.src.Reviewer_Recommender.Process.llm import generate_with_resilience -from codience.src.Reviewer_Recommender.Process.prompts import JIRA_ANALYSIS_PROMPT -from pydantic import BaseModel, ValidationError - -load_dotenv() - -# ─── Configuration ──────────────────────────────────────────────────────────── - -JIRA_API_BASE_URL = os.getenv("JIRA_API_BASE_URL", "http://localhost:5051/api") - - -class JiraAnalysisOutput(BaseModel): - domain: str - recent_skills: list[str] - summary: str - - -# ─── Jira API Client ────────────────────────────────────────────────────────── - -class JiraClient: - """ - Thin HTTP client for the .NET JiraController endpoints. - - Endpoints consumed: - GET /api/Jira/login → Redirects to Atlassian OAuth flow - GET /api/Jira/callback?code=... → Exchanges code for token + cloud info - GET /api/Jira/me?token=... → Returns the current authenticated user - POST /api/Jira/assigned-tickets → Returns issues assigned to a user - """ - - def __init__(self, base_url: str = JIRA_API_BASE_URL, timeout: int = 15): - self.base_url = base_url.rstrip("/") - self.timeout = timeout - - # ── Auth ────────────────────────────────────────────────────────────────── - - def get_login_url(self) -> str: - """ - Returns the Atlassian OAuth authorisation URL that the .NET backend - would redirect to. Useful when you need to show the URL to a user - rather than following the redirect automatically. - """ - return f"{self.base_url}/Jira/login" - - def exchange_code_for_token(self, code: str) -> dict: - """ - Calls GET /api/Jira/callback?code= and returns the full JSON - response which includes { accessToken, cloudId, Projects }. - """ - url = f"{self.base_url}/Jira/callback" - response = requests.get(url, params={"code": code}, timeout=self.timeout) - response.raise_for_status() - return response.json() - - def get_current_user(self, token: str) -> dict: - """ - Calls GET /api/Jira/me?token= and returns the user object. - """ - url = f"{self.base_url}/Jira/me" - response = requests.get(url, params={"token": token}, timeout=self.timeout) - response.raise_for_status() - return response.json() - - # ── Issues ──────────────────────────────────────────────────────────────── - - def get_assigned_tickets( - self, - token: str, - cloud_id: str, - project_key: str, - assignee_name: str, - ) -> list[dict]: - """ - Calls POST /api/Jira/assigned-tickets and returns the list of issues. - - Matches the JiraRequestDto expected by the controller: - { Token, CloudId, ProjectKey, AssigneeName } - """ - url = f"{self.base_url}/Jira/assigned-tickets" - payload = { - "token": token, - "cloudId": cloud_id, - "projectKey": project_key, - "assigneeName": assignee_name, - } - response = requests.post(url, json=payload, timeout=self.timeout) - if not response.ok: - print(f"⚠️ Jira API Error Response Body: {response.text}") - response.raise_for_status() - return response.json() - - -# ─── Default client (uses env config) ──────────────────────────────────────── - -_client = JiraClient() - - -# ─── Public helpers ─────────────────────────────────────────────────────────── - -# Use this to map GitHub usernames to Jira display names/Account IDs if they differ. -GITHUB_TO_JIRA_MAPPING = { - # "github_username": "Jira Display Name", - "your_github_username": "Your Jira Name", -} - -def _resolve_jira_name(github_username: str) -> str: - """Resolves a GitHub username to a Jira username using the local mapping.""" - # If the user is in the mapping, use the mapped name. Otherwise, fallback to github username. - return GITHUB_TO_JIRA_MAPPING.get(github_username, github_username) - -# This API should recieve data from frontend and then return the tickets -def fetch_jira_tickets( - username: str, - jira_username: str = None, - token: str = None, - cloud_id: str = None, - project_key: str = None, -) -> list[dict]: - # ─── DEBUG SECTION ─── - print(f"🔍 DEBUG: Resolving Jira identity for {username}") - - # This data should be passed from frontend or backend - target_user = jira_username or os.getenv("JIRA_USERNAME", username) - resolved_token = token or os.getenv("JIRA_API_TOKEN") - resolved_cloud_id = cloud_id or os.getenv("JIRA_CLOUD_ID") - resolved_project_key = project_key or os.getenv("JIRA_PROJECT_KEY") - - print(f" -> Target User: {target_user}") - print(f" -> Token exists: {bool(resolved_token)}") - print(f" -> Cloud ID exists: {bool(resolved_cloud_id)}") - print(f" -> Project Key exists: {bool(resolved_project_key)}") - - # Check for None values - C# will reject these with a 400 error! - if not all([resolved_token, resolved_cloud_id, resolved_project_key]): - print("❌ ERROR: Missing required Jira credentials in .env or API request.") - return [] - - try: - tickets = _client.get_assigned_tickets( - token=resolved_token, - cloud_id=resolved_cloud_id, - project_key=resolved_project_key, - assignee_name=target_user, - ) - return tickets - except Exception as exc: - print(f"⚠️ Error: {exc}") - return [] - - -def get_current_user(token: str = None) -> dict: - """ - Returns the Jira user profile for the supplied (or env-based) token - by calling GET /api/Jira/me. - """ - resolved_token = token or os.getenv("JIRA_API_TOKEN", "") - try: - user = _client.get_current_user(resolved_token) - return user - except requests.HTTPError as http_err: - print(f"⚠️ HTTP error fetching current Jira user: {http_err}") - except requests.RequestException as req_err: - print(f"⚠️ Network error fetching current Jira user: {req_err}") - except Exception as exc: - print(f"⚠️ Unexpected error fetching current Jira user: {exc}") - return {} - - -# ─── LLM Analysis ───────────────────────────────────────────────────────────── - -def analyze_jira_context( - username: str, - jira_username: str = None, - token: str = None, - cloud_id: str = None, - project_key: str = None, -) -> dict: - """ - Fetches Jira tickets for *username* and uses the configured LLM to - determine the developer's current domain and skills. - - Returns a dict with keys: domain, recent_skills, summary. - """ - tickets = fetch_jira_tickets( - username, - jira_username=jira_username, - token=token, - cloud_id=cloud_id, - project_key=project_key, - ) - return analyze_jira_tickets(username, tickets) - - -def analyze_jira_tickets(username: str, tickets: list[dict]) -> dict: - """ - Uses the configured LLM to determine the developer's current domain and skills - from the provided list of tickets. - """ - - - if not tickets: - return {"domain": "Unknown", "recent_skills": [], "summary": "No Jira tickets found."} - - # Build a text representation for the LLM (cap at 10 tickets) - ticket_texts: list[str] = [] - for i, ticket in enumerate(tickets[:10]): - title = ticket.get("title") or ticket.get("summary", "") - description = ticket.get("description", "") - if not title and not description: - continue - ticket_texts.append(f"Ticket {i + 1}: TITLE: {title}\nDESCRIPTION: {description}") - - if not ticket_texts: - return {"domain": "Unknown", "recent_skills": [], "summary": "No valid Jira ticket content found."} - - combined_tickets = "\n\n".join(ticket_texts) - prompt = JIRA_ANALYSIS_PROMPT.format(username=username, combined_tickets=combined_tickets) - - result = generate_with_resilience(prompt, purpose="jira_analysis") - if not result.get("ok"): - print(f"⚠️ Jira analysis fallback for '{username}'. reason={result.get('reason')}") - return {"domain": "Unknown", "recent_skills": [], "summary": "Analysis failed after retries."} - - raw_text = result.get("text", "") - try: - json_match = re.search(r"\{.*\}", raw_text, re.DOTALL) - json_str = json_match.group() if json_match else raw_text - parsed_data = json.loads(json_str) - validated_output = JiraAnalysisOutput(**parsed_data) - return validated_output.model_dump() - except json.JSONDecodeError as decode_error: - print(f"⚠️ Jira JSON decode error: {decode_error}") - except ValidationError as validation_error: - print(f"⚠️ Jira validation failed: {validation_error}") - except Exception as exc: - print(f"⚠️ Jira analysis parse error: {exc}") - - return {"domain": "Unknown", "recent_skills": [], "summary": "Analysis failed after retries."} - - -# ─── Smoke test ─────────────────────────────────────────────────────────────── - -if __name__ == "__main__": - result = analyze_jira_context("test_user") - print("\n--- Jira Analysis Output ---") - print(json.dumps(result, indent=2)) \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/Process/llm.py b/codience/src/Reviewer_Recommender/Process/llm.py deleted file mode 100644 index 259dc37d..00000000 --- a/codience/src/Reviewer_Recommender/Process/llm.py +++ /dev/null @@ -1,269 +0,0 @@ -import os -import random -import re -import time -import importlib -from threading import Lock -from google import genai -from dotenv import load_dotenv - -load_dotenv() - -LLM_PROVIDER = os.getenv("LLM_PROVIDER", "groq_primary_gemini_fallback").strip().lower() - -GEMINI_MODEL_PRIMARY = os.getenv("LLM_MODEL_PRIMARY", "gemini-3.1-flash-lite-preview") -GEMINI_MODEL_FALLBACKS = [m.strip() for m in os.getenv("LLM_MODEL_FALLBACKS", "").split(",") if m.strip()] - -GROQ_MODEL_PRIMARY = os.getenv("GROQ_MODEL_PRIMARY", "llama-3.3-70b-versatile") -GROQ_MODEL_FALLBACKS = [m.strip() for m in os.getenv("GROQ_MODEL_FALLBACKS", "").split(",") if m.strip()] - -LLM_MAX_RETRIES = int(os.getenv("LLM_MAX_RETRIES", "2")) -LLM_BACKOFF_BASE_SEC = float(os.getenv("LLM_BACKOFF_BASE_SEC", "1.5")) -LLM_BACKOFF_MAX_SEC = float(os.getenv("LLM_BACKOFF_MAX_SEC", "8")) -LLM_MAX_TOTAL_WAIT_SEC = float(os.getenv("LLM_MAX_TOTAL_WAIT_SEC", "20")) -LLM_CIRCUIT_FAIL_THRESHOLD = int(os.getenv("LLM_CIRCUIT_FAIL_THRESHOLD", "4")) -LLM_CIRCUIT_COOLDOWN_SEC = float(os.getenv("LLM_CIRCUIT_COOLDOWN_SEC", "30")) - -_clients = {} -_lock = Lock() -_circuit_failures = 0 -_circuit_open_until = 0.0 - - -class ProviderConfigurationError(Exception): - pass - - -class ProviderUnavailableError(Exception): - pass - - -def _parse_model_list(value): - return [m.strip() for m in value.split(",") if m.strip()] - - -def _purpose_env_key(purpose): - suffix = re.sub(r"[^a-zA-Z0-9]+", "_", (purpose or "general")).upper().strip("_") - if not suffix: - suffix = "GENERAL" - return suffix - - -def _provider_sequence(): - if LLM_PROVIDER in ("groq", "groq_only"): - return ["groq"] - if LLM_PROVIDER in ("gemini", "gemini_only"): - return ["gemini"] - if LLM_PROVIDER == "gemini_primary_groq_fallback": - return ["gemini", "groq"] - if LLM_PROVIDER == "groq_primary_gemini_fallback": - return ["groq", "gemini"] - - parsed = [p.strip().lower() for p in LLM_PROVIDER.split(",") if p.strip()] - valid = [p for p in parsed if p in ("groq", "gemini")] - return valid or ["groq", "gemini"] - - -def _provider_api_key(provider): - if provider == "groq": - return os.getenv("GROQ_API_KEY", "").strip() - if provider == "gemini": - return os.getenv("GEMINI_API_KEY", "").strip() - return "" - - -def _models_for_provider(purpose, provider, allow_fallback=True): - suffix = _purpose_env_key(purpose) - provider_key = f"LLM_MODELS_{provider.upper()}_{suffix}" - generic_key = f"LLM_MODELS_{suffix}" - - provider_models = _parse_model_list(os.getenv(provider_key, "")) - if provider_models: - return list(dict.fromkeys(provider_models)) - - generic_models = _parse_model_list(os.getenv(generic_key, "")) - if generic_models: - return list(dict.fromkeys(generic_models)) - - if provider == "groq": - models = [GROQ_MODEL_PRIMARY] - if allow_fallback: - models.extend(GROQ_MODEL_FALLBACKS) - return list(dict.fromkeys([m for m in models if m])) - - if provider == "gemini": - models = [GEMINI_MODEL_PRIMARY] - if allow_fallback: - models.extend(GEMINI_MODEL_FALLBACKS) - return list(dict.fromkeys([m for m in models if m])) - - return [] - - -def _get_provider_client(provider): - global _clients - if provider in _clients: - return _clients[provider] - - api_key = _provider_api_key(provider) - if not api_key: - raise ProviderConfigurationError(f"Missing API key for provider={provider}") - - if provider == "gemini": - _clients[provider] = genai.Client(api_key=api_key) - return _clients[provider] - - if provider == "groq": - try: - groq_module = importlib.import_module("groq") - Groq = getattr(groq_module, "Groq") - except Exception as exc: - raise ProviderUnavailableError(f"Groq SDK unavailable: {exc}") - _clients[provider] = Groq(api_key=api_key) - return _clients[provider] - - raise ProviderConfigurationError(f"Unsupported provider={provider}") - - -def _invoke_model(provider, model_name, prompt): - client = _get_provider_client(provider) - - if provider == "gemini": - response = client.models.generate_content(model=model_name, contents=prompt) - return (response.text or "").strip() - - if provider == "groq": - response = client.chat.completions.create( - model=model_name, - messages=[{"role": "user", "content": prompt}], - temperature=0, - ) - try: - content = response.choices[0].message.content - return (content or "").strip() - except Exception: - return "" - - raise ProviderConfigurationError(f"Unsupported provider={provider}") - - -def _is_retryable_error(exc): - msg = str(exc) - retry_markers = [ - "429", - "503", - "500", - "RESOURCE_EXHAUSTED", - "UNAVAILABLE", - "DEADLINE_EXCEEDED", - "rate limit", - "too many requests", - "internal server error", - "overloaded", - "timeout", - "temporarily unavailable", - ] - lowered = msg.lower() - return any(marker.lower() in lowered for marker in retry_markers) - - -def _mark_failure_and_maybe_open_circuit(): - global _circuit_failures, _circuit_open_until - with _lock: - _circuit_failures += 1 - if _circuit_failures >= LLM_CIRCUIT_FAIL_THRESHOLD: - _circuit_open_until = time.time() + LLM_CIRCUIT_COOLDOWN_SEC - - -def _reset_circuit_on_success(): - global _circuit_failures, _circuit_open_until - with _lock: - _circuit_failures = 0 - _circuit_open_until = 0.0 - - -def _is_circuit_open(): - return time.time() < _circuit_open_until - - -def generate_with_resilience(prompt, purpose="general", allow_fallback=True, max_retries=None, model_candidates=None): - if _is_circuit_open(): - return { - "ok": False, - "text": "", - "reason": "CIRCUIT_OPEN", - "attempts": 0, - "model": "", - } - - retries = LLM_MAX_RETRIES if max_retries is None else max(0, max_retries) - forced_models = list(dict.fromkeys([m.strip() for m in (model_candidates or []) if str(m).strip()])) - providers = _provider_sequence() - start_time = time.time() - attempts = 0 - last_error = "" - - for attempt_index in range(retries + 1): - for provider in providers: - if not _provider_api_key(provider): - last_error = f"Missing API key for provider={provider}" - continue - - models = forced_models or _models_for_provider(purpose, provider, allow_fallback=allow_fallback) - if not models: - last_error = f"No models configured for provider={provider}, purpose={purpose}" - continue - - provider_blocked = False - for model_name in models: - attempts += 1 - try: - text = _invoke_model(provider, model_name, prompt) - _reset_circuit_on_success() - return { - "ok": bool(text), - "text": text, - "reason": "OK" if text else "EMPTY_RESPONSE", - "attempts": attempts, - "model": model_name, - "provider": provider, - } - except (ProviderConfigurationError, ProviderUnavailableError) as exc: - last_error = str(exc) - provider_blocked = True - continue - except Exception as exc: - last_error = str(exc) - if _is_retryable_error(exc): - _mark_failure_and_maybe_open_circuit() - continue - - if provider_blocked: - continue - - if attempt_index < retries: - elapsed = time.time() - start_time - if elapsed >= LLM_MAX_TOTAL_WAIT_SEC: - break - delay = min(LLM_BACKOFF_MAX_SEC, LLM_BACKOFF_BASE_SEC * (2 ** attempt_index)) - delay += random.uniform(0, 0.5) - remaining_budget = max(0.0, LLM_MAX_TOTAL_WAIT_SEC - elapsed) - if remaining_budget <= 0: - break - time.sleep(min(delay, remaining_budget)) - - reason = "RETRY_EXHAUSTED" - if _is_circuit_open(): - reason = "CIRCUIT_OPEN" - elif last_error: - reason = f"RETRY_EXHAUSTED:{last_error}" - - print(f"⚠️ LLM {purpose} failed. reason={reason}, attempts={attempts}") - return { - "ok": False, - "text": "", - "reason": reason, - "attempts": attempts, - "model": "", - "provider": "", - } \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/Process/main.py b/codience/src/Reviewer_Recommender/Process/main.py deleted file mode 100644 index 26895476..00000000 --- a/codience/src/Reviewer_Recommender/Process/main.py +++ /dev/null @@ -1,32 +0,0 @@ -from codience.src.Reviewer_Recommender.Process.analysis_PR import extract_pr_skills -from codience.src.Reviewer_Recommender.Data.searching_into_vectordb import search_vector_db -from codience.src.Reviewer_Recommender.Process.tests_prs import test_prs - - -def main(): - for mock_pr_data in test_prs: - print(f"\nProcessing PR: {mock_pr_data['title']}") - extraction_result = extract_pr_skills(mock_pr_data) - print(f"Extracted Skills: {extraction_result['required_skills']}") - print(f"RAG Query: {extraction_result['rag_query']}") - skills_to_search = extraction_result['rag_query'] - - - role_matches = search_vector_db(skills_to_search, k=20) - - # 3. Final Step: Rank your reviewers based on these roles - # 4. Check the results - if not role_matches: - print("⚠️ No direct match found. System might need to fallback to general roles.") - else: - for i, match in enumerate(role_matches): - # Extract the role title from the page_content string - content = match.page_content - role_title = content.split('|')[0].replace("rag_content: Role:", "").strip() - - print(f"Rank {i+1}: {role_title}") - # Show more details for verification - print(f" Matches: {content.split('|')[1][:100]}...") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/Process/prompts.py b/codience/src/Reviewer_Recommender/Process/prompts.py deleted file mode 100644 index 2eca809e..00000000 --- a/codience/src/Reviewer_Recommender/Process/prompts.py +++ /dev/null @@ -1,108 +0,0 @@ -SKILL_EXTRACTION_PROMPT = """ -You are a Senior Technical Architect. Your task is to analyze a Pull Request and identify the specific technical skills and programming languages required to audit this code. - -PR DATA: -Title: {title} -Description: {description} -Code Changes (Diff): -{diff} - -INSTRUCTIONS: -1. **Identify Atomic Technical Skills**: Be specific to libraries and logic (e.g., "FastAPI: Dependency Injection", "OpenCV: Image Thresholding"). -2. **Identify Raw Programming Languages**: List the base programming languages involved (e.g., "Python", "Java", "C#", "SQL"). -3. **Format**: Extract skills as 'Technology: Specific Feature'. -4. **Prioritize**: Highlight high-risk logic like security or database migrations. - -OUTPUT FORMAT (JSON ONLY): -{{ - "required_skills": ["Skill A", "Skill B"], - "detected_languages": ["Language A", "Language B"], - "rag_query": "A Senior Engineer with expertise in [Key Skills] and [Languages]." -}} -""" - -JIRA_ANALYSIS_PROMPT = """ -You are an AI tasked with analyzing a developer's recently assigned Jira tickets to understand their current technical domain and skills. - -DEVELOPER USERNAME: {username} - -RECENT TICKETS: -{combined_tickets} - -Task: -Based on the tickets, identify the primary domain the developer is working on (e.g., Authentication, Database Migration, Frontend UI, CI/CD) and the specific technical skills or tools that are apparent from the ticket contents. - -Return the response as a valid JSON object strictly matching this schema: -{{ - "domain": "string (the current primary work domain)", - "recent_skills": ["skill_1", "skill_2"], - "summary": "string (1-2 sentence summary of their recent focus)" -}} -""" - -SCORER_PROMPT = """ -You are an expert tech lead tasked with assigning the best reviewers for a Pull Request. - -PULL REQUEST REQUIREMENTS: -- Required Skills: {pr_skills} -- Analysis Summary: {pr_analysis_summary} - -VECTOR DATABASE RECOMMENDATIONS (Historical Best Roles): -{rag_context} - -CANDIDATES PROFILES: -{candidates_text} - -Task: -Rank ALL candidates based on how well their historical commit skills and current Jira domain match the PR requirements. -Assign each a 'confidence_score' from 0 to 100, where 100 is an absolutely perfect match and 0 is no relevance at all. -Also provide a short 1-sentence 'justification' for why they received this score. - -Output strictly in the following JSON array format: -[ - {{ - "name": "Candidate Name", - "confidence_score": 85, - "justification": "Has strong recent Jira activity in the required domain and commit history matches perfectly." - }} -] -""" - -FILE_DIFF_SUMMARY_PROMPT = """ -You are a Senior Technical Architect analyzing a single file's changes. - -FILE NAME: {filename} -DIFF: -{patch} - -Task: -Summarize the technical changes made in this file in 1-2 sentences. -Highlight any specific programming languages, frameworks, or libraries that are evident. -""" - -COMMIT_CHUNK_SUMMARY_PROMPT = """ -You are analyzing a developer's commit to understand their technical skills. - -COMMIT MESSAGE: {commit_message} - -FILE SUMMARIES: -{file_summaries} - -Task: -Summarize the technical skills, languages, and frameworks demonstrated in this specific commit based on the files changed. -Keep it extremely concise (1-2 sentences). -""" - -DEVELOPER_PROFILE_REDUCE_PROMPT = """ -You are building a technical profile for a developer based on summaries of their recent commits. - -DEVELOPER: {author} - -COMMIT SUMMARIES: -{commit_summaries} - -Task: -Identify the unique programming languages and technical skills this developer possesses. -Return a valid JSON array of strings representing their skills. -Example: ["Python", "React", "AWS", "SQL"] -""" \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/Process/scorer_agent.py b/codience/src/Reviewer_Recommender/Process/scorer_agent.py deleted file mode 100644 index 343da228..00000000 --- a/codience/src/Reviewer_Recommender/Process/scorer_agent.py +++ /dev/null @@ -1,89 +0,0 @@ -import json -import re -from typing import List, Dict, Any -from pydantic import BaseModel, ValidationError -from codience.src.Reviewer_Recommender.Process.llm import generate_with_resilience -from codience.src.Reviewer_Recommender.Process.prompts import SCORER_PROMPT - - - -class CandidateScore(BaseModel): - name: str - confidence_score: int - justification: str - -def calculate_match_scores(pr_analysis: Dict[str, Any], rag_roles: List[Dict[str, Any]], candidates: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - """ - Evaluates a list of candidates against PR requirements and their Jira/Commit context. - Returns a ranked list with a 0 to 100 confidence score. - - pr_analysis: output from extract_pr_skills - rag_roles: list of recommended roles from search_vector_db (if available) - candidates: list of dicts: - [{"name": "DevA", "commit_skills": ["Python"], "jira_context": {"domain": "...", "recent_skills": []}}] - """ - - if not candidates: - return [] - - # Format candidates for the prompt - candidates_text = "" - for i, c in enumerate(candidates): - c_name = c["name"] - c_commits = ", ".join(c.get("commit_skills", [])) - c_jira_domain = c.get("jira_context", {}).get("domain", "Unknown") - c_jira_skills = ", ".join(c.get("jira_context", {}).get("recent_skills", [])) - c_raw_skills = ", ".join(c.get("raw_skills", [])) if isinstance(c.get("raw_skills"), list) else c.get("raw_skills", "None") - - candidates_text += f"\nCandidate {i+1}: {c_name}\n" - candidates_text += f" - Commit History Skills: {c_commits}\n" - candidates_text += f" - Current Jira Domain: {c_jira_domain}\n" - candidates_text += f" - Recent Jira Skills: {c_jira_skills}\n" - candidates_text += f" - Explicitly Provided Skills: {c_raw_skills}\n" - - # Format PR and RAG context - pr_skills = ", ".join(pr_analysis.get("required_skills", pr_analysis.get("detected_languages", []))) - rag_context = "\n".join([f"- {r.page_content}" for r in rag_roles]) if rag_roles else "No specific role found in Vector DB." - - prompt = SCORER_PROMPT.format( - pr_skills=pr_skills, - pr_analysis_summary=pr_analysis.get("summary", ""), - rag_context=rag_context, - candidates_text=candidates_text - ) - - result = generate_with_resilience(prompt, purpose="candidate_scoring") - if result.get("ok"): - raw_text = result.get("text", "") - try: - json_match = re.search(r'\[.*\]', raw_text, re.DOTALL) - json_str = json_match.group() if json_match else raw_text - parsed_data = json.loads(json_str) - validated_results = [] - for item in parsed_data: - validated_results.append(CandidateScore(**item).model_dump()) - - return sorted(validated_results, key=lambda x: x.get("confidence_score", 0), reverse=True) - except json.JSONDecodeError as decode_error: - print(f"⚠️ Scorer JSON decode error: {decode_error}") - except ValidationError as validation_error: - print(f"⚠️ Scorer validation failed: {validation_error}") - except Exception as e: - print(f"⚠️ Scorer parse error: {e}") - else: - print(f"⚠️ Scorer LLM fallback. reason={result.get('reason')}") - - # Fallback heuristic if all retries fail - print("⚠️ Heuristic scorer fallback used.") - fallback_results = [] - req_set = set(pr_analysis.get("detected_languages", [])) - for c in candidates: - c_skills = set(c.get("commit_skills", [])) - match_count = len(req_set.intersection(c_skills)) - score = min(100, int((match_count / max(len(req_set), 1)) * 100)) - fallback_results.append({ - "name": c["name"], - "confidence_score": score, - "justification": "Fallback heuristic used due to LLM error." - }) - return sorted(fallback_results, key=lambda x: x["confidence_score"], reverse=True) diff --git a/codience/src/Reviewer_Recommender/Process/tests_prs.py b/codience/src/Reviewer_Recommender/Process/tests_prs.py deleted file mode 100644 index 15c924fc..00000000 --- a/codience/src/Reviewer_Recommender/Process/tests_prs.py +++ /dev/null @@ -1,65 +0,0 @@ -test_prs = [ - # flutter - { - "title": "Feature: Implement Biometric Authentication Flow", - "description": "Added FaceID and Fingerprint support using the local_auth package. Updated the login screen UI to include a biometric toggle.", - "diff": """ - --- a/lib/screens/login_screen.dart - +++ b/lib/screens/login_screen.dart - + Future _authenticateWithBiometrics() async { - + bool authenticated = await auth.authenticate(localizedReason: 'Scan to login'); - + } - """ - }, - # .NET - { - "title": "Fix: Optimized SQL Query for User Dashboard", - "description": "I added an index to the User table and refactored the Entity Framework query to avoid N+1 issues by using Eager Loading.", - "diff": """ - --- a/Data/UserRepository.cs - +++ b/Data/UserRepository.cs - - var users = context.Users.ToList(); - + var users = context.Users.Include(u => u.Posts).AsNoTracking().ToList(); - """ - }, - # React - { - "title": "Feat: Migrate Component State to Redux Toolkit", - "description": "Replacing local useState hooks with a centralized Redux slice to handle global authentication state and improve data consistency.", - "diff": """ - --- a/src/components/Header.tsx - +++ b/src/components/Header.tsx - - const [user, setUser] = useState(null); - + const user = useSelector((state: RootState) => state.auth.user); - + const dispatch = useDispatch(); - """ - }, - # DevOps - { - "title": "Chore: Multi-stage Docker Build for Production", - "description": "Optimized image size by implementing a multi-stage build process and moving to alpine-based images for the Nginx frontend.", - "diff": """ - --- a/Dockerfile - +++ b/Dockerfile - + FROM node:20-alpine AS builder - + WORKDIR /app - + COPY . . - + RUN npm run build - + FROM nginx:alpine - + COPY --from=builder /app/dist /usr/share/nginx/html - """ - }, - # Python Backend - { - "title": "Feature: Integrate FastAPI Background Tasks", - "description": "Implemented background worker tasks for processing heavy image uploads without blocking the main request-response cycle.", - "diff": """ - --- a/app/main.py - +++ b/app/main.py - + @app.post("/upload/") - + async def create_upload_file(background_tasks: BackgroundTasks, file: UploadFile): - + background_tasks.add_task(process_image_in_background, file.filename) - + return {"message": "Upload started"} - """ - } -] \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/requirements.txt b/codience/src/Reviewer_Recommender/requirements.txt index ca95d535..d0108215 100644 --- a/codience/src/Reviewer_Recommender/requirements.txt +++ b/codience/src/Reviewer_Recommender/requirements.txt @@ -1,16 +1,20 @@ -datasets -pandas -langchain -langchain-huggingface # New -mistralai # NEW -openai # New -redis # NEW -langchain-community -sentence-transformers chromadb +datasets +fastapi google-genai>=0.7.0 groq>=0.11.0 +langchain +langchain-community +langchain-huggingface +langchain-text-splitters +mistralai +nomic +numpy +openai +pandas +pydantic python-dotenv -fastapi -uvicorn[standard] -requests \ No newline at end of file +redis +requests +sentence-transformers +uvicorn[standard] \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/tests/api/test_app.py b/codience/src/Reviewer_Recommender/tests/api/test_app.py new file mode 100644 index 00000000..bdf8ee93 --- /dev/null +++ b/codience/src/Reviewer_Recommender/tests/api/test_app.py @@ -0,0 +1,206 @@ +import pytest +from fastapi.testclient import TestClient +from unittest.mock import patch, MagicMock +from codience.src.app import app + +client = TestClient(app) + +# ========================================== +# /api/analyze/jira-tickets Tests +# ========================================== + +@patch("codience.src.app.analyze_jira_tickets") +def test_analyze_jira_tickets_success(mock_analyze): + mock_analyze.return_value = {"PROJ-123": {"summary": "Test ticket", "components": []}} + response = client.post("/api/analyze/jira-tickets", json={ + "username": "testuser", + "tickets": ["PROJ-123"] + }) + assert response.status_code == 200 + assert response.json() == {"PROJ-123": {"summary": "Test ticket", "components": []}} + +def test_analyze_jira_tickets_validation_error(): + # Missing required field 'username' + response = client.post("/api/analyze/jira-tickets", json={ + "tickets": ["PROJ-123"] + }) + assert response.status_code == 422 + +@patch("codience.src.app.analyze_jira_tickets") +def test_analyze_jira_tickets_empty_list(mock_analyze): + mock_analyze.return_value = {} + response = client.post("/api/analyze/jira-tickets", json={ + "username": "testuser", + "tickets": [] + }) + assert response.status_code == 200 + assert response.json() == {} + +# ========================================== +# /api/analyze/commit-history Tests +# ========================================== + +@patch("codience.src.app.map_commits_to_skills") +def test_analyze_commit_history_success(mock_map_commits): + mock_map_commits.return_value = {"testauthor": {"Python", "FastAPI"}} + response = client.post("/api/analyze/commit-history", json={ + "author": "testauthor", + "commits": ["sha123"] + }) + assert response.status_code == 200 + assert set(response.json()["skills"]) == {"Python", "FastAPI"} + +def test_analyze_commit_history_validation_error(): + # Missing 'commits' field + response = client.post("/api/analyze/commit-history", json={ + "author": "testauthor" + }) + assert response.status_code == 422 + +@patch("codience.src.app.map_commits_to_skills") +def test_analyze_commit_history_empty_list(mock_map_commits): + mock_map_commits.return_value = {} + response = client.post("/api/analyze/commit-history", json={ + "author": "testauthor", + "commits": [] + }) + assert response.status_code == 200 + assert response.json()["skills"] == [] + +# ========================================== +# /api/recommend/reviewer Tests +# ========================================== + +@patch("codience.src.app.get_composite_recommendations") +def test_recommend_reviewer_success(mock_get_composite): + mock_get_composite.return_value = [ + {"name": "reviewer1", "confidence_score": 90, "justification": "Good"}, + {"name": "reviewer2", "confidence_score": 80, "justification": "Okay"} + ] + response = client.post("/api/recommend/reviewer", json={ + "pr_data": {"files": [], "commits": []}, + "candidates": [{"name": "reviewer1"}, {"name": "reviewer2"}], + "options": {} + }) + assert response.status_code == 200 + assert "recommended_reviewers" in response.json() + assert len(response.json()["recommended_reviewers"]) == 2 + +def test_recommend_reviewer_validation_error(): + # Missing 'pr_data' field + response = client.post("/api/recommend/reviewer", json={ + "candidates": [{"name": "reviewer1"}], + "options": {} + }) + assert response.status_code == 422 + +# ========================================== +# /api/recommend-reviewers Tests +# ========================================== + +@patch("codience.src.app.get_pr_data_or_raise") +@patch("codience.src.app._build_engine") +def test_recommend_reviewers_default_engine(mock_build_engine, mock_get_pr_data): + mock_get_pr_data.return_value = {"diff": "some diff"} + + mock_engine = MagicMock() + mock_engine.recommend_v2.return_value = { + "recommended_reviewers": [{"name": "dev1", "confidence_score": 95, "justification": "Expert"}] + } + mock_build_engine.return_value = mock_engine + + response = client.post("/api/recommend-reviewers", json={ + "owner": "org", + "repo": "repo", + "pr_number": 1 + }) + + assert response.status_code == 200 + assert len(response.json()["recommended_reviewers"]) == 1 + mock_build_engine.assert_called_once() + mock_engine.recommend_v2.assert_called_once() + +@patch("codience.src.app.get_pr_data_or_raise") +@patch("codience.src.app._build_engine_for_required") +def test_recommend_reviewers_required_engine(mock_build_required, mock_get_pr_data): + mock_get_pr_data.return_value = {"diff": "some diff"} + + mock_engine = MagicMock() + mock_engine.recommend_v2.return_value = { + "recommended_reviewers": [{"name": "req_dev", "confidence_score": 85, "justification": "Required"}] + } + mock_build_required.return_value = mock_engine + + response = client.post("/api/recommend-reviewers", json={ + "owner": "org", + "repo": "repo", + "pr_number": 1, + "required_reviewers": ["req_dev"] + }) + + assert response.status_code == 200 + assert response.json()["recommended_reviewers"][0]["name"] == "req_dev" + mock_build_required.assert_called_once() + +def test_recommend_reviewers_validation_error(): + # Missing repo, owner, pr_number + response = client.post("/api/recommend-reviewers", json={}) + assert response.status_code == 422 + +# ========================================== +# /api/orchestrator Tests +# ========================================== + +@patch("codience.src.app.get_pr_data_or_raise") +@patch("codience.src.app.ReviewerRecommender") +@patch("codience.src.app._profile_single_user") +@patch("codience.src.app.get_composite_recommendations") +def test_orchestrator_success(mock_get_composite, mock_profile, mock_recommender, mock_get_pr_data): + mock_get_pr_data.return_value = {"diff": "diff data"} + mock_profile.side_effect = [{"name": "userA"}, {"name": "userB"}] + mock_get_composite.return_value = [ + {"name": "userA", "confidence_score": 90, "justification": "Match"}, + {"name": "userB", "confidence_score": 80, "justification": "Match"} + ] + + response = client.post("/api/orchestrator", json={ + "owner": "org", + "repo": "repo", + "pr_number": 123, + "users": [ + {"github_username": "userA"}, + {"github_username": "userB"} + ] + }) + + assert response.status_code == 200 + assert len(response.json()["recommended_reviewers"]) == 2 + assert mock_profile.call_count == 2 + mock_get_composite.assert_called_once() + +@patch("codience.src.app.get_pr_data_or_raise") +@patch("codience.src.app.ReviewerRecommender") +@patch("codience.src.app.get_composite_recommendations") +def test_orchestrator_empty_users(mock_get_composite, mock_recommender, mock_get_pr_data): + mock_get_pr_data.return_value = {"diff": "diff data"} + mock_get_composite.return_value = [] + + response = client.post("/api/orchestrator", json={ + "owner": "org", + "repo": "repo", + "pr_number": 123, + "users": [] + }) + + assert response.status_code == 200 + assert response.json()["recommended_reviewers"] == [] + mock_get_composite.assert_called_once() + +def test_orchestrator_validation_error(): + # Missing 'users' field + response = client.post("/api/orchestrator", json={ + "owner": "org", + "repo": "repo", + "pr_number": 123 + }) + assert response.status_code == 422 diff --git a/codience/src/Reviewer_Recommender/tests/conftest.py b/codience/src/Reviewer_Recommender/tests/conftest.py new file mode 100644 index 00000000..ebfbdc5d --- /dev/null +++ b/codience/src/Reviewer_Recommender/tests/conftest.py @@ -0,0 +1,42 @@ +import pytest + +@pytest.fixture +def mock_pr_data(): + return { + "title": "Add authentication middleware", + "description": "Implemented JWT based authentication for the API.", + "files": [ + {"filename": "src/auth.py", "patch": "+ def verify_token(token):\n+ pass"}, + {"filename": "src/main.py", "patch": "+ from auth import verify_token"} + ] + } + +@pytest.fixture +def mock_commits(): + return [ + { + "author": {"login": "dev1"}, + "commit": {"author": {"name": "dev1", "date": "2023-10-01T12:00:00Z"}}, + "files": [{"filename": "src/auth.py"}], + "sha": "abc1234" + }, + { + "author": {"login": "dev1"}, + "commit": {"author": {"name": "dev1", "date": "2023-10-05T12:00:00Z"}}, + "files": [{"filename": "src/utils.py"}], + "sha": "def5678" + }, + { + "author": {"login": "dev2"}, + "commit": {"author": {"name": "dev2", "date": "2023-09-15T12:00:00Z"}}, + "files": [{"filename": "src/database.py"}], + "sha": "ghi9012" + } + ] + +@pytest.fixture +def mock_history_profiles(): + return { + "dev1": {"Python", "JWT", "FastAPI"}, + "dev2": {"Python", "SQL", "Database Migration"} + } diff --git a/codience/src/Reviewer_Recommender/tests/integration/test_integration.py b/codience/src/Reviewer_Recommender/tests/integration/test_integration.py new file mode 100644 index 00000000..284ed540 --- /dev/null +++ b/codience/src/Reviewer_Recommender/tests/integration/test_integration.py @@ -0,0 +1,23 @@ +import pytest +from codience.src.Reviewer_Recommender.PRNew.Reviewer_Engine import ReviewerRecommender + +def test_engine_initialization(): + engine = ReviewerRecommender(owner="test_owner", repo="test_repo") + assert engine.owner == "test_owner" + assert engine.repo == "test_repo" + +def test_engine_recommend_v2_empty_pr(): + engine = ReviewerRecommender(owner="test_owner", repo="test_repo") + pr_data = { + "files": [], + "commits": [] + } + + result = engine.recommend_v2( + pr_data=pr_data, + required_reviewers=[], + options={}, + ) + + assert "recommended_reviewers" in result + assert isinstance(result["recommended_reviewers"], list) diff --git a/codience/src/Reviewer_Recommender/tests/unit/test_engine_math.py b/codience/src/Reviewer_Recommender/tests/unit/test_engine_math.py new file mode 100644 index 00000000..c1dc9cc3 --- /dev/null +++ b/codience/src/Reviewer_Recommender/tests/unit/test_engine_math.py @@ -0,0 +1,78 @@ +import pytest +import sys +from pathlib import Path +from datetime import datetime, timezone, timedelta + +sys.path.insert(0, str(Path(__file__).resolve().parents[5])) + +from codience.src.Reviewer_Recommender.PRNew.Reviewer_Engine import ReviewerRecommender + +@pytest.fixture +def engine(): + # using mocks reviewerw + return ReviewerRecommender(owner="mock", repo="mock") + +def test_parse_commit_datetime(engine): + date_str = "2023-10-01T12:00:00Z" + parsed = engine._parse_commit_datetime(date_str) + assert parsed is not None + assert parsed.year == 2023 + assert parsed.month == 10 + + assert engine._parse_commit_datetime("invalid-date") is None + assert engine._parse_commit_datetime(None) is None + +def test_build_contributor_stats(engine): + # We dynamically generate dates relative to "now" to test recency scoring + now = datetime.now(timezone.utc) + date_45_days_ago = (now - timedelta(days=45)).isoformat() + date_180_days_ago = (now - timedelta(days=180)).isoformat() + + custom_commits = [ + { + "author": {"login": "dev_recent"}, + "commit": {"author": {"name": "dev_recent", "date": date_45_days_ago}}, + "files": [{"filename": "src/auth.py"}], + "sha": "abc1" + }, + { + "author": {"login": "dev_old"}, + "commit": {"author": {"name": "dev_old", "date": date_180_days_ago}}, + "files": [{"filename": "src/utils.py"}], + "sha": "def2" + } + ] + + stats = engine._build_contributor_stats(custom_commits) + + assert "dev_recent" in stats + assert "dev_old" in stats + + # dev_recent was 45 days ago. Score formula: 1.0 - (min(recency_days, 90) / 90.0) + # 1.0 - (45/90) = 0.5 + assert stats["dev_recent"]["recency_score"] == 0.5 + + # dev_old was 180 days ago (exceeds 90 days threshold). Score should be 0.0 + assert stats["dev_old"]["recency_score"] == 0.0 + +def test_limit_commits_per_reviewer(engine, mock_commits): + # Limit to 1 commit per reviewer + limited = engine._limit_commits_per_reviewer(mock_commits, 1) + + # Should only have 1 for dev1, 1 for dev2 = 2 total + assert len(limited) == 2 + + dev1_commits = [c for c in limited if c["author"]["login"] == "dev1"] + assert len(dev1_commits) == 1 + +def test_normalize_required_reviewers(engine): + required = ["dev1", {"username": "dev2", "raw_skills": ["Python"]}] + + normalized = engine._normalize_required_reviewers(required) + + assert "dev1" in normalized + assert normalized["dev1"]["username"] == "dev1" + + assert "dev2" in normalized + assert normalized["dev2"]["username"] == "dev2" + assert "Python" in normalized["dev2"]["raw_skills"] \ No newline at end of file diff --git a/codience/src/Reviewer_Recommender/tests/unit/test_multiset_engine.py b/codience/src/Reviewer_Recommender/tests/unit/test_multiset_engine.py new file mode 100644 index 00000000..9f1a898d --- /dev/null +++ b/codience/src/Reviewer_Recommender/tests/unit/test_multiset_engine.py @@ -0,0 +1,98 @@ +import pytest +from datetime import datetime, timezone, timedelta +from collections import Counter +from PRNew.multiset_engine import ( + tokenise_path, + commit_multiset, + extinguish, + build_reviewer_profile, + tversky_similarity, + jaccard_similarity, + score_reviewer +) + +def test_tokenise_path(): + assert tokenise_path("src/main/java/package1/SomeClass.java") == ["src", "main", "java", "package1", "someclass", "java"] + assert tokenise_path("path-with-dashes/and_underscores.txt") == ["path", "with", "dashes", "and", "underscores", "txt"] + assert tokenise_path("CamelCaseIsNotSplit/file.ts") == ["camelcaseisnotsplit", "file", "ts"] + +def test_commit_multiset(): + paths = ["src/file1.py", "src/file2.py"] + result = commit_multiset(paths) + assert result == Counter({"src": 2, "file1": 1, "py": 2, "file2": 1}) + +def test_extinguish(): + assert extinguish(0) == 1.0 + assert extinguish(180, decay_factor=2.0, halflife_days=180) == 0.5 + assert extinguish(360, decay_factor=2.0, halflife_days=180) == 0.25 + +def test_build_reviewer_profile_no_decay(): + commits = [ + {"files": ["src/main.py", "src/utils.py"]}, + {"files": ["src/main.py"]} + ] + profile = build_reviewer_profile(commits, use_decay=False) + assert profile == Counter({"src": 3, "main": 2, "py": 3, "utils": 1}) + +def test_build_reviewer_profile_with_decay(): + ref_date = datetime(2023, 1, 1, tzinfo=timezone.utc) + # Commit 1 is exactly 180 days old (halflife = 180, factor = 2.0 -> multiplier 0.5) + date_180_days_ago = (ref_date - timedelta(days=180)).isoformat() + # Commit 2 is today (0 days old -> multiplier 1.0) + date_today = ref_date.isoformat() + + commits = [ + {"files": ["src/old.py"], "date": date_180_days_ago}, + {"files": ["src/new.py"], "date": date_today} + ] + profile = build_reviewer_profile( + commits, use_decay=True, decay_factor=2.0, halflife_days=180, reference_date=ref_date + ) + # old.py elements get multiplied by 0.5 + # new.py elements get multiplied by 1.0 + assert profile["src"] == 1.5 # 0.5 from old, 1.0 from new + assert profile["old"] == 0.5 + assert profile["new"] == 1.0 + assert profile["py"] == 1.5 + +def test_tversky_similarity(): + profile = Counter({"src": 2, "file1": 1}) + commit = Counter({"src": 1, "file2": 1}) + + # Inter: "src": min(2,1) = 1 + # p_only: "src": max(0, 2-1)=1, "file1": max(0, 1-0)=1 -> total p_only = 2 + # c_only: "src": max(0, 1-2)=0, "file2": max(0, 1-0)=1 -> total c_only = 1 + # denom (alpha=0.5, beta=0.5) = 1 + 0.5*2 + 0.5*1 = 1 + 1 + 0.5 = 2.5 + # score = 1 / 2.5 = 0.4 + + score = tversky_similarity(profile, commit, alpha=0.5, beta=0.5) + assert score == 0.4 + + # Empty cases + assert tversky_similarity(Counter(), commit) == 0.0 + assert tversky_similarity(profile, Counter()) == 0.0 + +def test_jaccard_similarity(): + profile = Counter({"src": 2, "file1": 1}) + commit = Counter({"src": 1, "file2": 1}) + + # Inter = 1 + # Union = sum(profile+commit) - Inter = (2+1+1+1) - 1 = 4 + # score = 1 / 4 = 0.25 + score = jaccard_similarity(profile, commit) + assert score == 0.25 + +def test_score_reviewer(): + commits = [ + {"files": ["src/main.py"], "date": datetime.now(timezone.utc).isoformat()} + ] + pr_files = ["src/main.py"] + + res = score_reviewer(commits, pr_files, use_decay=False) + # Profile = {"src":1, "main":1, "py":1} + # Commit = {"src":1, "main":1, "py":1} + # Both identical, scores should be 1.0 + assert res["tversky"] == 1.0 + assert res["jaccard"] == 1.0 + assert res["profile_size"] == 3 + assert res["commit_size"] == 3 diff --git a/codience/src/__pycache__/app.cpython-312.pyc b/codience/src/__pycache__/app.cpython-312.pyc index 7c6811af..49e77d94 100644 Binary files a/codience/src/__pycache__/app.cpython-312.pyc and b/codience/src/__pycache__/app.cpython-312.pyc differ diff --git a/codience/src/app.py b/codience/src/app.py index a5525b64..e0f8f43c 100644 --- a/codience/src/app.py +++ b/codience/src/app.py @@ -1,170 +1,55 @@ # Fast API for reviewer recommendation import os + from typing import Optional, Any -from fastapi import FastAPI, HTTPException +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware # pyrefly: ignore [missing-import] -from pydantic import BaseModel, Field -from codience.src.Reviewer_Recommender.Process.Engine_test import ReviewerRecommender, fetch_real_pr_data -from codience.src.Reviewer_Recommender.Process.jira_agent import analyze_jira_tickets, fetch_jira_tickets -from codience.src.Reviewer_Recommender.Process.Reviewer_Engine_Helper import analyze_user_commit_history -from codience.src.Reviewer_Recommender.Process.analysis_PR import extract_pr_skills -from codience.src.Reviewer_Recommender.Data.searching_into_vectordb import search_vector_db -from codience.src.Reviewer_Recommender.Process.scorer_agent import calculate_match_scores - -app = FastAPI(title="Codience Reviewer Recommender API") - - -# --- Models ------------------------------------------------------------------ - -class BaseRepoRequest(BaseModel): - owner: str = Field(..., description="GitHub repository owner or organization.") - repo: str = Field(..., description="GitHub repository name.") - pr_number: int = Field(..., description="Pull request number.") - - -class RankingOptions(BaseModel): - top_k: Optional[int] = Field(default=None, description="Max recommendations (1-20). Default 5.") - prioritize_recent_activity: Optional[bool] = Field(default=None, description="Toggle recency prioritization.") - commits_per_reviewer: Optional[int] = Field(default=None, description="Recent commits considered (1-100). Default 50.") - - -class ReviewerRequest(BaseRepoRequest): - pass - - -class ReviewerRequestV2(BaseRepoRequest): - required_reviewers: list[Any] = Field(default_factory=list, description="Explicit reviewers to consider (strings or dicts).") - options: Optional[RankingOptions] = None - -class TicketListRequest(BaseModel): - username: str - tickets: list[Any] - - -class CommitHistoryRequest(BaseModel): - author: str - commits: list[Any] - - -class CandidateProfile(BaseModel): - name: str - jira_username: Optional[str] = None - commit_skills: list[str] = [] - jira_context: dict = {} - commit_count: int = 0 - tenure_days: int = 365 - recency_score: float = 0.0 - required_reviewer: bool = False - raw_skills: list[str] = [] - prelim_score: float = 0.0 - - -class ReviewerMatchRequest(BaseModel): - pr_data: dict - candidates: list[CandidateProfile] - options: Optional[RankingOptions] = None - - -class OrchestratorUser(BaseModel): - github_username: str - jira_username: Optional[str] = None - jira_token: Optional[str] = None - jira_cloud_id: Optional[str] = None - jira_project_key: Optional[str] = None - raw_skills: list[str] = [] - - -class OrchestratorRequest(BaseRepoRequest): - users: list[OrchestratorUser] - commits_per_user: Optional[int] = 50 - options: Optional[RankingOptions] = None - - -class ReviewerResponse(BaseModel): - name: str - confidence_score: int - justification: str +from codience.src.models import ( + RecommendReviewersRequest, + TicketListRequest, + CommitHistoryRequest, + ReviewerMatchRequest, + OrchestratorRequest, + ReviewerResponse, +) +from codience.src.helpers import ( + get_pr_data_or_raise, + format_reviewer_results, + _build_engine, + _build_engine_for_required, + _normalize_reviewers, + get_composite_recommendations, + _profile_single_user, +) +from codience.src.Reviewer_Recommender.PRNew.Reviewer_Engine import ReviewerRecommender +from codience.src.Reviewer_Recommender.PRNew.jira_agent import analyze_jira_tickets +from codience.src.Reviewer_Recommender.PRNew.commit_history_utils import map_commits_to_skills +app = FastAPI(title="Codience Reviewer Recommender API") +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], # Allow all origins + allow_credentials=True, + allow_methods=["*"], # Allow all HTTP methods + allow_headers=["*"], # Allow all headers +) # --- Helpers ----------------------------------------------------------------- +# Helper functions and business logic are imported from codience.src.helpers -def get_pr_data_or_raise(owner: str, repo: str, pr_number: int) -> dict: - """Centralized helper to fetch and validate PR data.""" - real_pr = fetch_real_pr_data(owner, repo, pr_number) - if not real_pr: - raise HTTPException(status_code=404, detail=f"Failed to fetch PR #{pr_number} data for {owner}/{repo}.") - return real_pr - -def format_reviewer_results(results: list[dict], limit: int = 5) -> list[ReviewerResponse]: - """Uniformly formats internal reviewer dicts for API response.""" - formatted = [] - for res in results[:limit]: - formatted.append(ReviewerResponse( - name=res.get("name", "Unknown"), - confidence_score=int(res.get("confidence_score", 0)), - justification=res.get("justification", "") - )) - return formatted - - -def _build_engine(owner: str, repo: str, min_commits: Optional[int] = None) -> ReviewerRecommender: - """Full init: indexes all repo contributors.""" - engine = ReviewerRecommender(owner, repo) - max_commits = int(os.getenv("ENGINE_MAX_COMMITS", "1000")) - if min_commits is not None: - max_commits = max(max_commits, int(min_commits)) - max_llm_calls = int(os.getenv("ENGINE_MAX_LLM_CALLS", "30")) - engine.initialize_system(max_commits=max_commits, max_llm_calls=max_llm_calls) - return engine - - -def _build_engine_for_required(owner: str, repo: str, required_reviewers: list, commits_per_reviewer: int = 50) -> ReviewerRecommender: - """Lean init: only fetches history for the specified required reviewers.""" - engine = ReviewerRecommender(owner, repo) - max_llm_calls = int(os.getenv("ENGINE_MAX_LLM_CALLS", "20")) - engine.initialize_for_required_only( - required_reviewers=required_reviewers, - commits_per_reviewer=commits_per_reviewer, - max_llm_calls=max_llm_calls, - ) - return engine - - -def _normalize_reviewers(reviewers: list[Any]) -> list[Any]: - """Deduplicates and normalizes strings/dicts into a clean list of reviewer identifiers.""" - normalized = [] - seen = set() - for r in reviewers: - username = r.strip() if isinstance(r, str) else (r.get("username") or r.get("login") or "").strip() - if username and username.lower() not in seen: - seen.add(username.lower()) - normalized.append(r) - return normalized - - -@app.post("/api/recommend", response_model=dict[str, list[ReviewerResponse]]) -async def recommend(request: ReviewerRequest): - engine = _build_engine(request.owner, request.repo) - pr_data = get_pr_data_or_raise(request.owner, request.repo, request.pr_number) - - results = engine.recommend(pr_data) - return {"reviewers": format_reviewer_results(results)} - - -@app.post("/api/recommend/v2", response_model=dict[str, list[ReviewerResponse]]) -async def recommend_v2(request: ReviewerRequestV2): +@app.post("/api/recommend-reviewers", response_model=dict[str, list[ReviewerResponse]]) +async def recommend_reviewers(request: RecommendReviewersRequest): normalized_required = _normalize_reviewers(request.required_reviewers) options = request.options.model_dump(exclude_none=True) if request.options else {} - # Bound options + # Bound options if "top_k" in options: options["top_k"] = max(1, min(20, options["top_k"])) - if "commits_per_reviewer" in options: - options["commits_per_reviewer"] = max(1, min(100, options["commits_per_reviewer"])) - commits_per_reviewer = options.get("commits_per_reviewer", ReviewerRecommender.DEFAULT_COMMITS_PER_REVIEWER) + commits_per_reviewer = ReviewerRecommender.DEFAULT_COMMITS_PER_REVIEWER if normalized_required: engine = _build_engine_for_required( @@ -178,7 +63,14 @@ async def recommend_v2(request: ReviewerRequestV2): engine = _build_engine(request.owner, request.repo, min_commits=min_commits) pr_data = get_pr_data_or_raise(request.owner, request.repo, request.pr_number) - result = engine.recommend_v2(pr_data, required_reviewers=normalized_required, options=options) + result = engine.recommend_v2( + pr_data, + required_reviewers=normalized_required, + options=options, + jira_token=request.jira_token, + jira_cloud_id=request.jira_cloud_id, + jira_project_key=request.jira_project_key + ) return {"recommended_reviewers": format_reviewer_results(result.get("recommended_reviewers", []))} @@ -190,54 +82,11 @@ async def api_analyze_jira_tickets(request: TicketListRequest): @app.post("/api/analyze/commit-history") async def api_analyze_commit_history(request: CommitHistoryRequest): - skills = analyze_user_commit_history(request.author, request.commits) + skills_set = map_commits_to_skills(request.commits, repo="unknown/unknown", specific_authors=[request.author]).get(request.author, set()) + skills = list(skills_set) return {"skills": skills} -def get_composite_recommendations(pr_data: dict, candidates: list[dict], options: Optional[RankingOptions] = None) -> list[dict]: - """ - Business logic for calculating composite scores based on AI analysis, - preliminary scores, and recency signals. - """ - analysis = extract_pr_skills(pr_data) - required_languages = {lang.strip().title() for lang in analysis.get('detected_languages', [])} - if "C#" in required_languages: - required_languages.remove("C#") - required_languages.add(".NET") - - rag_query = analysis.get('rag_query', '') or ', '.join(required_languages) - try: - rag_roles = search_vector_db(rag_query, k=10) if rag_query else [] - except Exception as e: - print(f"⚠️ Vector DB Search Failed: {e}") - rag_roles = [] - - ai_rankings = calculate_match_scores(analysis, rag_roles, candidates) - ai_by_name = {r.get("name", "").lower(): r for r in ai_rankings} - - final_candidates = [] - for c in candidates: - ai_result = ai_by_name.get(c["name"].lower(), {}) - ai_score = float(ai_result.get("confidence_score", 0)) / 100.0 - - # Scoring weights: 65% Preliminary (Commit/Jira), 35% AI Match (Matchmaker) - final_score = int(round(100 * ((0.65 * c.get("prelim_score", 0)) + (0.35 * ai_score)))) - - reasons = [] - if c.get("required_reviewer"): - reasons.append("required_reviewer") - if c.get("recency_score", 0) >= 0.5: - reasons.append("recent_activity_priority") - - final_candidates.append({ - "name": c["name"], - "confidence_score": max(0, min(100, final_score)), - "justification": ai_result.get("justification", "Composite scoring based on skills and recent contributor activity."), - "reasons": reasons, - "required_reviewer": c.get("required_reviewer", False), - }) - - final_candidates.sort(key=lambda x: x["confidence_score"], reverse=True) - return final_candidates +# get_composite_recommendations moved to codience.src.helpers @app.post("/api/recommend/reviewer", response_model=dict[str, list[ReviewerResponse]]) @@ -247,44 +96,7 @@ async def api_recommend_reviewer(request: ReviewerMatchRequest): return {"recommended_reviewers": format_reviewer_results(results, limit=len(results))} -def _profile_single_user(user: OrchestratorUser, engine: ReviewerRecommender, commits_per_user: int) -> dict: - """Collects GitHub and Jira data for a single user to build their candidate profile.""" - github_username = user.github_username - - # 1. GitHub History - author_commits = engine._fetch_commits_for_author(github_username, commits_per_user) - commit_skills = analyze_user_commit_history(github_username, author_commits) - - # 2. Jira Context - tickets = fetch_jira_tickets( - username=github_username, - jira_username=user.jira_username, - token=user.jira_token, - cloud_id=user.jira_cloud_id, - project_key=user.jira_project_key - ) - jira_context = analyze_jira_tickets(github_username, tickets) - - # 3. Stats & Scoring - stats = engine._build_contributor_stats(author_commits).get(github_username, {}) - recency_score = stats.get("recency_score", 0.0) - - # Simple preliminary skill-match heuristic - skill_score = 0.8 if commit_skills else 0.5 - prelim_score = (0.55 * skill_score) + (0.45 * recency_score) - - return { - "name": github_username, - "jira_username": user.jira_username, - "commit_skills": commit_skills, - "jira_context": jira_context, - "commit_count": stats.get("commit_count", 0), - "tenure_days": stats.get("tenure_days", 365), - "recency_score": recency_score, - "required_reviewer": True, - "raw_skills": user.raw_skills, - "prelim_score": prelim_score - } +# _profile_single_user moved to codience.src.helpers @app.post("/api/orchestrator", response_model=dict[str, list[ReviewerResponse]]) diff --git a/codience/src/helpers.py b/codience/src/helpers.py new file mode 100644 index 00000000..a0b648cc --- /dev/null +++ b/codience/src/helpers.py @@ -0,0 +1,183 @@ +import os +from typing import Optional, Any +from fastapi import HTTPException + +# Models +from codience.src.models import ( + ReviewerResponse, + RankingOptions, + OrchestratorUser, +) + +# External engine and agent imports +from codience.src.Reviewer_Recommender.PRNew.Reviewer_Engine import ReviewerRecommender, fetch_real_pr_data +from codience.src.Reviewer_Recommender.PRNew.jira_agent import analyze_jira_tickets, fetch_jira_tickets +from codience.src.Reviewer_Recommender.PRNew.commit_history_utils import fetch_commit_history_for_author, map_commits_to_skills +from codience.src.Reviewer_Recommender.PRNew.analysis_PR import extract_pr_skills +from codience.src.Reviewer_Recommender.Data.searching_into_vectordb import search_vector_db +from codience.src.Reviewer_Recommender.PRNew.scorer_agent import calculate_match_scores +from codience.src.Reviewer_Recommender.Data.commit_diff_vectordb import search_similar_commits + + +def get_pr_data_or_raise(owner: str, repo: str, pr_number: int) -> dict: + """Centralized helper to fetch and validate PR data.""" + real_pr = fetch_real_pr_data(owner, repo, pr_number) + if not real_pr: + raise HTTPException(status_code=404, detail=f"Failed to fetch PR #{pr_number} data for {owner}/{repo}.") + return real_pr + + +def format_reviewer_results(results: list[dict], limit: int = 5) -> list[ReviewerResponse]: + """Uniformly formats internal reviewer dicts for API response.""" + formatted = [] + for res in results[:limit]: + formatted.append(ReviewerResponse( + name=res.get("name", "Unknown"), + confidence_score=int(res.get("confidence_score", 0)), + justification=res.get("justification", "") + )) + return formatted + + +def _build_engine(owner: str, repo: str, min_commits: Optional[int] = None) -> ReviewerRecommender: + """Full init: indexes all repo contributors.""" + engine = ReviewerRecommender(owner, repo) + max_commits = int(os.getenv("ENGINE_MAX_COMMITS", "1000")) + if min_commits is not None: + max_commits = max(max_commits, int(min_commits)) + engine.initialize_with_cache_check(max_developers=50, max_commits=max_commits) + return engine + + +def _build_engine_for_required(owner: str, repo: str, required_reviewers: list, commits_per_reviewer: int = 50) -> ReviewerRecommender: + """Lean init: only fetches history for the specified required reviewers.""" + engine = ReviewerRecommender(owner, repo) + engine.initialize_with_cache_check( + required_developers=required_reviewers, + commits_per_reviewer=commits_per_reviewer, + max_commits=500, + ) + return engine + +# normalize the required reviewers +def _normalize_reviewers(reviewers: list[Any]) -> list[Any]: + normalized = [] + seen = set() + for r in reviewers: + username = r.strip() if isinstance(r, str) else (r.get("username") or r.get("login") or "").strip() + if username and username.lower() not in seen: + seen.add(username.lower()) + normalized.append(r) + return normalized + + +def get_composite_recommendations(pr_data: dict, candidates: list[dict], options: Optional[RankingOptions] = None) -> list[dict]: + """ + Business logic for calculating composite scores based on AI analysis, + preliminary scores, and recency signals. + """ + analysis = extract_pr_skills(pr_data) + required_languages = {lang.strip().title() for lang in analysis.get('detected_languages', [])} + if "C#" in required_languages: + required_languages.remove("C#") + required_languages.add(".NET") + + rag_query = analysis.get('rag_query', '') or ', '.join(required_languages) + try: + rag_roles = search_vector_db(rag_query, k=10) if rag_query else [] + except Exception as e: + print(f"⚠️ Vector DB Search Failed: {e}") + rag_roles = [] + + pr_patch_text = "\n".join([f.get("patch", "") for f in pr_data.get("files", []) if f.get("patch")]) + rag_commits = [] + if pr_patch_text: + try: + rag_commits = search_similar_commits(pr_patch_text, k=15) + except Exception as e: + print(f"⚠️ Code Diff Vector DB Search Failed: {e}") + + author_rag_matches = {} + for res in rag_commits: + author = res.metadata.get("author") + if author: + author_rag_matches[author.lower()] = author_rag_matches.get(author.lower(), 0) + 1 + + for c in candidates: + rag_match_count = author_rag_matches.get(c["name"].lower(), 0) + max_rag = max(author_rag_matches.values()) if author_rag_matches else 1 + rag_match_score = rag_match_count / max_rag if max_rag > 0 else 0.0 + + c["prelim_score"] = (0.7 * c.get("prelim_score", 0)) + (0.3 * rag_match_score) + + matched_diffs = [res.page_content for res in rag_commits if res.metadata.get("author", "").lower() == c["name"].lower()] + c["rag_code_matches"] = matched_diffs[:3] + + ai_rankings = calculate_match_scores(analysis, rag_roles, candidates) + ai_by_name = {r.get("name", "").lower(): r for r in ai_rankings} + + final_candidates = [] + for c in candidates: + ai_result = ai_by_name.get(c["name"].lower(), {}) + ai_score = float(ai_result.get("confidence_score", 0)) / 100.0 + + # Scoring weights: 65% Preliminary (Commit/Jira), 35% AI Match (Matchmaker) + final_score = int(round(100 * ((0.65 * c.get("prelim_score", 0)) + (0.35 * ai_score)))) + + reasons = [] + if c.get("required_reviewer"): + reasons.append("required_reviewer") + if c.get("recency_score", 0) >= 0.5: + reasons.append("recent_activity_priority") + + final_candidates.append({ + "name": c["name"], + "confidence_score": max(0, min(100, final_score)), + "justification": ai_result.get("justification", "Composite scoring based on skills and recent contributor activity."), + "reasons": reasons, + "required_reviewer": c.get("required_reviewer", False), + }) + + final_candidates.sort(key=lambda x: x["confidence_score"], reverse=True) + return final_candidates + + +def _profile_single_user(user: OrchestratorUser, engine: ReviewerRecommender, commits_per_user: int) -> dict: + """Collects GitHub and Jira data for a single user to build their candidate profile.""" + github_username = user.github_username + + # 1. GitHub History + author_commits = fetch_commit_history_for_author(github_username, engine.owner, engine.repo, limit=commits_per_user) + commit_skills_set = map_commits_to_skills(author_commits, repo=f"{engine.owner}/{engine.repo}", specific_authors=[github_username]).get(github_username, set()) + commit_skills = list(commit_skills_set) + + # 2. Jira Context + tickets = fetch_jira_tickets( + username=github_username, + jira_username=user.jira_username, + token=user.jira_token, + cloud_id=user.jira_cloud_id, + project_key=user.jira_project_key + ) + jira_context = analyze_jira_tickets(github_username, tickets) + + # 3. Stats & Scoring + stats = engine._build_contributor_stats(author_commits).get(github_username, {}) + recency_score = stats.get("recency_score", 0.0) + + # Simple preliminary skill-match heuristic + skill_score = 0.8 if commit_skills else 0.5 + prelim_score = (0.55 * skill_score) + (0.45 * recency_score) + + return { + "name": github_username, + "jira_username": user.jira_username, + "commit_skills": commit_skills, + "jira_context": jira_context, + "commit_count": stats.get("commit_count", 0), + "tenure_days": stats.get("tenure_days", 365), + "recency_score": recency_score, + "required_reviewer": True, + "raw_skills": user.raw_skills, + "prelim_score": prelim_score + } diff --git a/codience/src/models.py b/codience/src/models.py new file mode 100644 index 00000000..a44a5c49 --- /dev/null +++ b/codience/src/models.py @@ -0,0 +1,69 @@ +from typing import Optional, Any +from pydantic import BaseModel, Field + +class BaseRepoRequest(BaseModel): + owner: str = Field(..., description="GitHub repository owner or organization.") + repo: str = Field(..., description="GitHub repository name.") + pr_number: int = Field(..., description="Pull request number.") + + +class RankingOptions(BaseModel): + top_k: Optional[int] = Field(default=None, description="Max recommendations (1-20). Default 5.") + + +class RecommendReviewersRequest(BaseRepoRequest): + required_reviewers: list[Any] = Field(default_factory=list, description="Explicit reviewers to consider (strings or dicts).") + options: Optional[RankingOptions] = None + jira_token: Optional[str] = None + jira_cloud_id: Optional[str] = None + jira_project_key: Optional[str] = None + + +class TicketListRequest(BaseModel): + username: str + tickets: list[Any] + + +class CommitHistoryRequest(BaseModel): + author: str + commits: list[Any] + + +class CandidateProfile(BaseModel): + name: str + jira_username: Optional[str] = None + commit_skills: list[str] = [] + jira_context: dict = {} + commit_count: int = 0 + tenure_days: int = 365 + recency_score: float = 0.0 + required_reviewer: bool = False + raw_skills: list[str] = [] + prelim_score: float = 0.0 + + +class ReviewerMatchRequest(BaseModel): + pr_data: dict + candidates: list[CandidateProfile] + options: Optional[RankingOptions] = None + + +class OrchestratorUser(BaseModel): + github_username: str + jira_username: Optional[str] = None + jira_token: Optional[str] = None + jira_cloud_id: Optional[str] = None + jira_project_key: Optional[str] = None + raw_skills: list[str] = [] + + +class OrchestratorRequest(BaseRepoRequest): + users: list[OrchestratorUser] + commits_per_user: Optional[int] = 50 + options: Optional[RankingOptions] = None + + +class ReviewerResponse(BaseModel): + name: str + confidence_score: int + justification: str diff --git a/codience/src/test_and_evaluate.py b/codience/src/test_and_evaluate.py new file mode 100644 index 00000000..67b6f3c2 --- /dev/null +++ b/codience/src/test_and_evaluate.py @@ -0,0 +1,211 @@ +import unittest +from unittest.mock import patch, MagicMock +from fastapi.testclient import TestClient +import numpy as np +import sys + +# Import the FastAPI application +from codience.src.app import app +from codience.src.models import RecommendReviewersRequest + +client = TestClient(app) + +# ===================================================================== +# PART 1: API UNIT TESTS (FastAPI TestClient) +# ===================================================================== + +class TestEvaluatorAgent(unittest.TestCase): + @patch("codience.src.Reviewer_Recommender.PRNew.evaluator_agent.generate_with_resilience") + def test_evaluate_recommendations_accepted(self, mock_generate): + from codience.src.Reviewer_Recommender.PRNew.evaluator_agent import evaluate_recommendations + + # Mock LLM returning an accepted response + mock_generate.return_value = { + "ok": True, + "text": '{"accepted": true, "feedback": "Looks good"}' + } + + pr_data = {"title": "Add eval layer", "description": "Adds LLM judge"} + recommendations = [{"name": "MalakHisham121", "confidence_score": 90}] + + result = evaluate_recommendations(pr_data, recommendations) + self.assertTrue(result["accepted"]) + self.assertEqual(result["feedback"], "Looks good") + + @patch("codience.src.Reviewer_Recommender.PRNew.evaluator_agent.generate_with_resilience") + def test_evaluate_recommendations_rejected(self, mock_generate): + from codience.src.Reviewer_Recommender.PRNew.evaluator_agent import evaluate_recommendations + + # Mock LLM returning a rejected response with feedback + mock_generate.return_value = { + "ok": True, + "text": '{"accepted": false, "feedback": "Candidate lacks Python skills."}' + } + + pr_data = {"title": "Python script", "description": "Needs Python"} + recommendations = [{"name": "JavaDev", "confidence_score": 80}] + + result = evaluate_recommendations(pr_data, recommendations) + self.assertFalse(result["accepted"]) + self.assertEqual(result["feedback"], "Candidate lacks Python skills.") + + +class TestReviewerRecommenderAPI(unittest.TestCase): + + @patch("codience.src.helpers.fetch_real_pr_data") + @patch("codience.src.helpers.ReviewerRecommender") + def test_recommend_reviewers_endpoint(self, mock_recommender_class, mock_fetch_pr): + """Test the main /api/recommend-reviewers endpoint with mocked dependencies.""" + # 1. Mock PR Data + mock_fetch_pr.return_value = { + "title": "Fix memory leak in trainer", + "description": "Optimized memory footprint", + "files": [{"filename": "src/trainer.py", "patch": "+ def optimize(): pass"}] + } + + # 2. Mock Recommender Engine behavior + mock_engine = MagicMock() + mock_recommender_class.return_value = mock_engine + mock_engine.recommend_v2.return_value = { + "recommended_reviewers": [ + {"name": "ArthurZucker", "confidence_score": 90, "justification": "Expert in training loop"}, + {"name": "younesbelkada", "confidence_score": 75, "justification": "Maintained trainer.py recently"} + ] + } + + # 3. Call endpoint + payload = { + "owner": "huggingface", + "repo": "transformers", + "pr_number": 42, + "required_reviewers": [], + "options": {"top_k": 5} + } + response = client.post("/api/recommend-reviewers", json=payload) + + # 4. Assertions + self.assertEqual(response.status_code, 200) + json_data = response.json() + self.assertIn("recommended_reviewers", json_data) + self.assertEqual(len(json_data["recommended_reviewers"]), 2) + self.assertEqual(json_data["recommended_reviewers"][0]["name"], "ArthurZucker") + self.assertEqual(json_data["recommended_reviewers"][0]["confidence_score"], 90) + + @patch("codience.src.app.analyze_jira_tickets") + def test_analyze_jira_tickets_endpoint(self, mock_analyze): + """Test the JIRA tickets analysis API endpoint.""" + mock_analyze.return_value = {"skills": ["Authentication", "FastAPI"], "resolved_count": 5} + + payload = { + "username": "dev_user", + "tickets": [{"key": "PROJ-101", "summary": "Add OAuth2 integration"}] + } + response = client.post("/api/analyze/jira-tickets", json=payload) + + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json()["resolved_count"], 5) + + +# ===================================================================== +# PART 2: RECOMMENDATION SYSTEM EVALUATION (Metrics) +# ===================================================================== + +def evaluate_recommendations(predictions: list[list[str]], ground_truth: list[list[str]], k_values=[1, 3, 5]): + """ + Evaluates recommendations using standard IR metrics: + - Hit Rate@k (HR@k) + - Mean Reciprocal Rank (MRR) + - Precision@k + - Recall@k + """ + results = {} + n = len(predictions) + if n == 0: + return results + + # 1. Mean Reciprocal Rank (MRR) + rr_list = [] + for pred, gt in zip(predictions, ground_truth): + gt_set = set(gt) + rank = -1 + for i, p in enumerate(pred): + if p in gt_set: + rank = i + 1 + break + rr = 1.0 / rank if rank > 0 else 0.0 + rr_list.append(rr) + results["MRR"] = float(np.mean(rr_list)) + + # 2. Hit Rate, Precision, Recall at different K values + for k in k_values: + hits = 0 + precision_list = [] + recall_list = [] + + for pred, gt in zip(predictions, ground_truth): + pred_k = pred[:k] + gt_set = set(gt) + + # Intersection of recommended and actual reviewers + correct_recs = [p for p in pred_k if p in gt_set] + + # Hit Rate: at least one correct recommendation + if len(correct_recs) > 0: + hits += 1 + + # Precision@k = correct / recommended + precision = len(correct_recs) / k + precision_list.append(precision) + + # Recall@k = correct / total actual + recall = len(correct_recs) / len(gt_set) if len(gt_set) > 0 else 0.0 + recall_list.append(recall) + + results[f"HitRate@{k}"] = hits / n + results[f"Precision@{k}"] = float(np.mean(precision_list)) + results[f"Recall@{k}"] = float(np.mean(recall_list)) + + return results + + +def run_model_evaluation_demo(): + """ + Runs a simulation/evaluation matching a ground-truth dataset + representing real-world pull requests. + """ + print("\n" + "="*60) + # Ground truth: Who actually reviewed these PRs in reality + ground_truth = [ + ["ArthurZucker"], + ["younesbelkada", "ArthurZucker"], + ["younesbelkada"], + ["ArthurZucker"], + ["dev_c", "younesbelkada"] + ] + + # Predictions made by the Recommender (ordered by confidence) + predictions = [ + ["ArthurZucker", "younesbelkada", "dev_c"], # PR 1 + ["ArthurZucker", "dev_c", "younesbelkada"], # PR 2 + ["dev_c", "younesbelkada", "ArthurZucker"], # PR 3 + ["younesbelkada", "dev_c", "ArthurZucker"], # PR 4 + ["dev_c", "younesbelkada", "ArthurZucker"] # PR 5 + ] + + print("📊 Evaluating Recommender System Metrics...") + metrics = evaluate_recommendations(predictions, ground_truth, k_values=[1, 2, 3]) + + print("-" * 60) + for metric, score in metrics.items(): + print(f"🔹 {metric:<15} : {score * 100:.2f}%" if "MRR" not in metric else f"🔹 {metric:<15} : {score:.4f}") + print("="*60 + "\n") + + +if __name__ == "__main__": + print("🧪 Running API Unit Tests...") + # Run unittest suite programmatically + suite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__]) + unittest.TextTestRunner(verbosity=2).run(suite) + + # Run evaluation metrics demonstration + run_model_evaluation_demo()