Repair live unified search corpus runtime
This commit is contained in:
@@ -8,6 +8,15 @@ internal sealed record KnowledgeSearchRepositoryRootResolution(
|
||||
internal static class KnowledgeSearchRepositoryRootResolver
|
||||
{
|
||||
public static string ResolvePath(KnowledgeSearchOptions options, string configuredPath)
|
||||
{
|
||||
return ResolvePath(options, configuredPath, Directory.GetCurrentDirectory(), AppContext.BaseDirectory);
|
||||
}
|
||||
|
||||
internal static string ResolvePath(
|
||||
KnowledgeSearchOptions options,
|
||||
string configuredPath,
|
||||
string? currentDirectory,
|
||||
string? appBaseDirectory)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(configuredPath);
|
||||
@@ -17,7 +26,7 @@ internal static class KnowledgeSearchRepositoryRootResolver
|
||||
return Path.GetFullPath(configuredPath);
|
||||
}
|
||||
|
||||
var repositoryRoot = Resolve(options);
|
||||
var repositoryRoot = Resolve(options, currentDirectory, appBaseDirectory);
|
||||
return Path.GetFullPath(Path.Combine(repositoryRoot.Path, configuredPath));
|
||||
}
|
||||
|
||||
|
||||
@@ -95,15 +95,31 @@
|
||||
</None>
|
||||
<None Update="UnifiedSearch/Snapshots/findings.snapshot.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>UnifiedSearch/Snapshots/findings.snapshot.json</TargetPath>
|
||||
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/findings.snapshot.json</TargetPath>
|
||||
</None>
|
||||
<None Update="UnifiedSearch/Snapshots/vex.snapshot.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>UnifiedSearch/Snapshots/vex.snapshot.json</TargetPath>
|
||||
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/vex.snapshot.json</TargetPath>
|
||||
</None>
|
||||
<None Update="UnifiedSearch/Snapshots/policy.snapshot.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>UnifiedSearch/Snapshots/policy.snapshot.json</TargetPath>
|
||||
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/policy.snapshot.json</TargetPath>
|
||||
</None>
|
||||
<None Update="UnifiedSearch/Snapshots/graph.snapshot.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/graph.snapshot.json</TargetPath>
|
||||
</None>
|
||||
<None Update="UnifiedSearch/Snapshots/opsmemory.snapshot.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/opsmemory.snapshot.json</TargetPath>
|
||||
</None>
|
||||
<None Update="UnifiedSearch/Snapshots/timeline.snapshot.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/timeline.snapshot.json</TargetPath>
|
||||
</None>
|
||||
<None Update="UnifiedSearch/Snapshots/scanner.snapshot.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/scanner.snapshot.json</TargetPath>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -176,13 +176,7 @@ internal sealed class GraphNodeIngestionAdapter : ISearchIngestionAdapter
|
||||
|
||||
private string ResolvePath(string configuredPath)
|
||||
{
|
||||
if (Path.IsPathRooted(configuredPath))
|
||||
{
|
||||
return configuredPath;
|
||||
}
|
||||
|
||||
var root = string.IsNullOrWhiteSpace(_knowledgeOptions.RepositoryRoot) ? "." : _knowledgeOptions.RepositoryRoot;
|
||||
return Path.GetFullPath(Path.Combine(root, configuredPath));
|
||||
return KnowledgeSearchRepositoryRootResolver.ResolvePath(_knowledgeOptions, configuredPath);
|
||||
}
|
||||
|
||||
private static string BuildEntityKey(
|
||||
@@ -224,4 +218,3 @@ internal sealed class GraphNodeIngestionAdapter : ISearchIngestionAdapter
|
||||
return raw is not null && DateTimeOffset.TryParse(raw, out var timestamp) ? timestamp : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,13 +141,7 @@ internal sealed class OpsDecisionIngestionAdapter : ISearchIngestionAdapter
|
||||
|
||||
private string ResolvePath(string configuredPath)
|
||||
{
|
||||
if (Path.IsPathRooted(configuredPath))
|
||||
{
|
||||
return configuredPath;
|
||||
}
|
||||
|
||||
var root = string.IsNullOrWhiteSpace(_knowledgeOptions.RepositoryRoot) ? "." : _knowledgeOptions.RepositoryRoot;
|
||||
return Path.GetFullPath(Path.Combine(root, configuredPath));
|
||||
return KnowledgeSearchRepositoryRootResolver.ResolvePath(_knowledgeOptions, configuredPath);
|
||||
}
|
||||
|
||||
private static string GuessSubjectType(string subjectRef)
|
||||
@@ -234,4 +228,3 @@ internal sealed class OpsDecisionIngestionAdapter : ISearchIngestionAdapter
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,13 +139,7 @@ internal sealed class ScanResultIngestionAdapter : ISearchIngestionAdapter
|
||||
|
||||
private string ResolvePath(string configuredPath)
|
||||
{
|
||||
if (Path.IsPathRooted(configuredPath))
|
||||
{
|
||||
return configuredPath;
|
||||
}
|
||||
|
||||
var root = string.IsNullOrWhiteSpace(_knowledgeOptions.RepositoryRoot) ? "." : _knowledgeOptions.RepositoryRoot;
|
||||
return Path.GetFullPath(Path.Combine(root, configuredPath));
|
||||
return KnowledgeSearchRepositoryRootResolver.ResolvePath(_knowledgeOptions, configuredPath);
|
||||
}
|
||||
|
||||
private static string? ReadString(JsonElement obj, string propertyName)
|
||||
@@ -187,4 +181,3 @@ internal sealed class ScanResultIngestionAdapter : ISearchIngestionAdapter
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,13 +144,7 @@ internal sealed partial class TimelineEventIngestionAdapter : ISearchIngestionAd
|
||||
|
||||
private string ResolvePath(string configuredPath)
|
||||
{
|
||||
if (Path.IsPathRooted(configuredPath))
|
||||
{
|
||||
return configuredPath;
|
||||
}
|
||||
|
||||
var root = string.IsNullOrWhiteSpace(_knowledgeOptions.RepositoryRoot) ? "." : _knowledgeOptions.RepositoryRoot;
|
||||
return Path.GetFullPath(Path.Combine(root, configuredPath));
|
||||
return KnowledgeSearchRepositoryRootResolver.ResolvePath(_knowledgeOptions, configuredPath);
|
||||
}
|
||||
|
||||
private static (string? EntityKey, string EntityType) ExtractEntity(string targetRef)
|
||||
|
||||
@@ -55,6 +55,39 @@ public sealed class KnowledgeSearchRepositoryRootResolverTests
|
||||
Assert.Equal(fixture.AppBaseDirectory, resolution.Path);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ResolvePath_points_all_default_unified_snapshot_paths_at_runtime_publish_corpus()
|
||||
{
|
||||
using var fixture = RuntimePublishLayoutFixture.Create();
|
||||
var knowledgeOptions = new KnowledgeSearchOptions();
|
||||
var unifiedOptions = new StellaOps.AdvisoryAI.UnifiedSearch.UnifiedSearchOptions();
|
||||
var unrelatedCurrentDirectory = Path.Combine(fixture.WorkspaceRoot, "outside");
|
||||
Directory.CreateDirectory(unrelatedCurrentDirectory);
|
||||
|
||||
var configuredPaths = new[]
|
||||
{
|
||||
knowledgeOptions.UnifiedFindingsSnapshotPath,
|
||||
knowledgeOptions.UnifiedVexSnapshotPath,
|
||||
knowledgeOptions.UnifiedPolicySnapshotPath,
|
||||
unifiedOptions.Ingestion.GraphSnapshotPath,
|
||||
unifiedOptions.Ingestion.OpsMemorySnapshotPath,
|
||||
unifiedOptions.Ingestion.TimelineSnapshotPath,
|
||||
unifiedOptions.Ingestion.ScannerSnapshotPath,
|
||||
};
|
||||
|
||||
foreach (var configuredPath in configuredPaths)
|
||||
{
|
||||
var resolved = KnowledgeSearchRepositoryRootResolver.ResolvePath(
|
||||
knowledgeOptions,
|
||||
configuredPath,
|
||||
unrelatedCurrentDirectory,
|
||||
fixture.AppBaseDirectory);
|
||||
|
||||
Assert.StartsWith(fixture.AppBaseDirectory, resolved, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.True(File.Exists(resolved), $"Expected runtime corpus asset for {configuredPath} at {resolved}.");
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class RepositoryRootFixture : IDisposable
|
||||
{
|
||||
private RepositoryRootFixture(
|
||||
@@ -131,10 +164,12 @@ public sealed class KnowledgeSearchRepositoryRootResolverTests
|
||||
{
|
||||
var workspaceRoot = Path.Combine(Path.GetTempPath(), "stellaops-knowledge-runtime-" + Guid.NewGuid().ToString("N"));
|
||||
var appBaseDirectory = Path.Combine(workspaceRoot, "app");
|
||||
var snapshotDirectory = Path.Combine(appBaseDirectory, "src", "AdvisoryAI", "StellaOps.AdvisoryAI", "UnifiedSearch", "Snapshots");
|
||||
|
||||
Directory.CreateDirectory(Path.Combine(appBaseDirectory, "docs", "modules", "advisory-ai"));
|
||||
Directory.CreateDirectory(Path.Combine(appBaseDirectory, "devops", "compose"));
|
||||
Directory.CreateDirectory(Path.Combine(appBaseDirectory, "src", "AdvisoryAI", "StellaOps.AdvisoryAI", "KnowledgeSearch"));
|
||||
Directory.CreateDirectory(snapshotDirectory);
|
||||
|
||||
File.WriteAllText(Path.Combine(appBaseDirectory, "docs", "README.md"), "# docs");
|
||||
File.WriteAllText(Path.Combine(appBaseDirectory, "docs", "modules", "advisory-ai", "knowledge-search.md"), "# advisory");
|
||||
@@ -148,6 +183,13 @@ public sealed class KnowledgeSearchRepositoryRootResolverTests
|
||||
File.WriteAllText(
|
||||
Path.Combine(appBaseDirectory, "src", "AdvisoryAI", "StellaOps.AdvisoryAI", "KnowledgeSearch", "doctor-search-controls.json"),
|
||||
"[]");
|
||||
File.WriteAllText(Path.Combine(snapshotDirectory, "findings.snapshot.json"), "[]");
|
||||
File.WriteAllText(Path.Combine(snapshotDirectory, "vex.snapshot.json"), "[]");
|
||||
File.WriteAllText(Path.Combine(snapshotDirectory, "policy.snapshot.json"), "[]");
|
||||
File.WriteAllText(Path.Combine(snapshotDirectory, "graph.snapshot.json"), "[]");
|
||||
File.WriteAllText(Path.Combine(snapshotDirectory, "opsmemory.snapshot.json"), "[]");
|
||||
File.WriteAllText(Path.Combine(snapshotDirectory, "timeline.snapshot.json"), "[]");
|
||||
File.WriteAllText(Path.Combine(snapshotDirectory, "scanner.snapshot.json"), "[]");
|
||||
|
||||
return new RuntimePublishLayoutFixture(workspaceRoot, appBaseDirectory);
|
||||
}
|
||||
|
||||
@@ -299,20 +299,24 @@ public sealed class UnifiedSearchIngestionAdaptersTests
|
||||
try
|
||||
{
|
||||
Directory.SetCurrentDirectory(fixture.ServiceDirectory);
|
||||
var knowledgeOptions = Options.Create(new KnowledgeSearchOptions
|
||||
{
|
||||
RepositoryRoot = fixture.RepositoryRoot
|
||||
});
|
||||
|
||||
var findingsAdapter = new FindingIngestionAdapter(
|
||||
new StubVectorEncoder(),
|
||||
Options.Create(new KnowledgeSearchOptions()),
|
||||
knowledgeOptions,
|
||||
NullLogger<FindingIngestionAdapter>.Instance);
|
||||
var policyAdapter = new PolicySearchAdapter(
|
||||
new StubHttpClientFactory(),
|
||||
new StubVectorEncoder(),
|
||||
Options.Create(new KnowledgeSearchOptions()),
|
||||
knowledgeOptions,
|
||||
NullLogger<PolicySearchAdapter>.Instance);
|
||||
var vexAdapter = new VexSearchAdapter(
|
||||
new StubHttpClientFactory(),
|
||||
new StubVectorEncoder(),
|
||||
Options.Create(new KnowledgeSearchOptions()),
|
||||
knowledgeOptions,
|
||||
NullLogger<VexSearchAdapter>.Instance);
|
||||
|
||||
var findings = await findingsAdapter.ProduceChunksAsync(CancellationToken.None);
|
||||
|
||||
Reference in New Issue
Block a user