Repair live AdvisoryAI search corpus parity

This commit is contained in:
master
2026-03-08 13:33:21 +02:00
parent f9d652da32
commit 3e531f0b9e
7 changed files with 299 additions and 0 deletions

View File

@@ -27,3 +27,23 @@ devops/helm
*.png *.png
*.jpg *.jpg
*.jpeg *.jpeg
!docs/
!docs/README.md
!docs/INSTALL_GUIDE.md
!docs/modules/
!docs/modules/advisory-ai/
!docs/modules/advisory-ai/**
!docs/modules/authority/
!docs/modules/authority/**
!docs/modules/cli/
!docs/modules/cli/**
!docs/modules/platform/
!docs/modules/platform/**
!docs/modules/policy/
!docs/modules/policy/**
!docs/modules/router/
!docs/modules/router/**
!docs/modules/scanner/
!docs/modules/scanner/**
!docs/operations/
!docs/operations/**

View File

@@ -0,0 +1,77 @@
# Sprint 20260308-002 - FE Search Live Browser Reproduction And Fix
## Topic & Scope
- Reproduce the reported global-search failure in a live browser session instead of relying on prior mocked regressions.
- Identify why searches are not returning usable results across pages and fix the concrete operator-facing failure.
- Add focused regression coverage so live search interaction stays usable on primary routes.
- Working directory: `src/Web/StellaOps.Web`.
- Expected evidence: live Playwright/browser reproduction, focused FE tests, and updated UI docs if behavior changes.
## Dependencies & Concurrency
- Depends on the archived search rollout and clarify-guidance sprints.
- Safe parallelism: avoid unrelated Router, trust-admin, offline-kit, and audit-bundle worktree changes.
- Cross-module allowance: documentation updates may touch `docs/modules/ui/**` if the operator search contract changes.
## Documentation Prerequisites
- `src/Web/StellaOps.Web/AGENTS.md`
- `docs/modules/ui/search-self-serve-contract.md`
- `docs/modules/ui/search-zero-learning-primary-entry.md`
## Delivery Tracker
### FE-SEARCH-LIVE-001 - Reproduce the operator failure in a real browser session
Status: DONE
Dependency: none
Owners: Developer (FE), QA
Task description:
- Use Playwright against the live `stella-ops.local` shell to reproduce the reported inability to search from real pages.
- Capture the exact failing interaction path, route context, and UI/network behavior so the fix targets the real defect.
Completion criteria:
- [x] Failure reproduced or disproved on live pages using Playwright.
- [x] Root cause narrowed to a concrete UI, request, or data-readiness issue.
- [x] Execution log records the live reproduction evidence.
### FE-SEARCH-LIVE-002 - Fix the live search interaction failure
Status: DONE
Dependency: FE-SEARCH-LIVE-001
Owners: Developer (FE)
Task description:
- Implement the smallest frontend fix that restores usable search from the live shell.
- Prefer behavior that works without requiring the operator to learn special search syntax or page-specific rituals.
Completion criteria:
- [x] Global search returns usable results or explicit grounded fallback on affected routes.
- [x] The fix does not break prior search guidance/answer behavior.
- [x] Focused tests cover the repaired interaction.
### FE-SEARCH-LIVE-003 - Verify and close
Status: DONE
Dependency: FE-SEARCH-LIVE-002
Owners: QA, Documentation, Project Manager
Task description:
- Re-run browser validation after the fix, add any missing regression coverage, and archive the sprint when complete.
Completion criteria:
- [x] Focused automated coverage passes.
- [x] Execution log records live browser verification after the fix.
- [x] Sprint is archived only after all tasks are DONE.
## Execution Log
| Date (UTC) | Update | Owner |
| --- | --- | --- |
| 2026-03-08 | Sprint created to reproduce and fix the reported live search failure from the operator shell. | Developer |
| 2026-03-08 | Live Playwright reproduction on `https://stella-ops.local` confirmed the operator report: `POST /api/v1/search/query` returned `200` with zero indexed matches on `/releases/versions`, `/security/triage`, `/ops/policy`, and `/ops/operations/doctor`, while `POST /api/v1/search/suggestions/evaluate` returned `404`. Direct inspection of the compose-backed AdvisoryAI service at `127.1.0.44` showed knowledge rebuild output `documentCount=0`, `apiOperationCount=0`, and `doctorProjectionCount=0`, plus stale unified rows with unusable live FTS behavior. A runtime database backfill on `advisoryai.kb_chunk.body_tsv_en` restored exact-term search from the browser for indexed entities such as `critical findings`, `CVE-2024-21626`, `CVE-2025-1001`, and `Deny critical vulnerabilities in production`, but generic Doctor/Release suggestions still fail because the compose service lacks knowledge/API/Doctor corpus parity and does not expose `POST /v1/search/suggestions/evaluate`. | Developer |
| 2026-03-08 | Closure verification completed after the AdvisoryAI runtime parity repair landed in `SPRINT_20260308_003_AdvisoryAI_live_search_compose_parity.md`: live Playwright on `https://stella-ops.local` now returns grounded answers on `/releases/versions`, `/security/triage`, `/ops/policy`, and `/ops/operations/doctor`, and release suggestion chips such as `What blocked this promotion?` execute into grounded answer states. No FE-specific code change was required once the compose-backed AdvisoryAI service shipped the missing docs/OpenAPI/Doctor corpus. | Developer |
## Decisions & Risks
- Decision: validate the report in a live browser session before making any further search UX changes.
- Risk: prior mocked regression coverage may not reflect the real runtime path on `stella-ops.local`.
- Mitigation: reproduce on the live shell first, then add regression coverage for the exact failure mode.
- Risk: the remaining live failure is not primarily in FE scope. The compose-backed AdvisoryAI service behind `stella-ops.local` is running without knowledge/API/Doctor ingestion parity and without the suggestion-viability endpoint that current FE logic expects.
- Mitigation: keep FE fallback work isolated, but track the remaining repair as an AdvisoryAI/runtime follow-up before claiming full live-search recovery.
- Decision: close this sprint without FE code changes because the verified operator failure was caused by compose runtime corpus omission, not by a surviving shell interaction defect.
## Next Checkpoints
- 2026-03-08: live browser reproduction captured.
- 2026-03-08: fix implemented and verified if root cause is in FE scope.

View File

@@ -0,0 +1,80 @@
# Sprint 20260308-003 - AdvisoryAI Live Search Compose Parity
## Topic & Scope
- Repair the compose-backed AdvisoryAI service behind `https://stella-ops.local` so live search has the same corpus and endpoint surface as the source-run validation lane.
- Restore knowledge/API/Doctor ingestion parity and the suggestion-viability endpoint required by the current search UX.
- Verify the repaired service from the real browser on `stella-ops.local` instead of relying on isolated backend tests.
- Working directory: `src/AdvisoryAI`.
- Expected evidence: focused AdvisoryAI/runtime verification, live browser search checks, and updated docs if setup/runtime behavior changes.
## Dependencies & Concurrency
- Depends on [SPRINT_20260308_002_FE_search_live_browser_reproduction_and_fix.md](/C:/dev/New%20folder/git.stella-ops.org/docs/implplan/SPRINT_20260308_002_FE_search_live_browser_reproduction_and_fix.md) for the live reproduction evidence.
- Safe parallelism: avoid unrelated Router, Web trust-admin, offline-kit, and audit-bundle changes.
- Cross-module allowance: docs under `docs/modules/advisory-ai/**` and `docs/modules/ui/**` may be updated if live-search setup or operator guidance changes; repo-root `.dockerignore` may be updated only as needed to let the AdvisoryAI image package its documented search corpus subset.
## Documentation Prerequisites
- `src/AdvisoryAI/AGENTS.md`
- `src/AdvisoryAI/__Tests/INFRASTRUCTURE.md`
- `docs/modules/advisory-ai/knowledge-search.md`
- `docs/modules/ui/search-zero-learning-primary-entry.md`
## Delivery Tracker
### AI-LIVE-SEARCH-001 - Restore compose AdvisoryAI endpoint parity
Status: DONE
Dependency: none
Owners: Developer (AdvisoryAI)
Task description:
- Determine why the compose-backed AdvisoryAI service at `advisoryai.stella-ops.local` returns `404` for `POST /v1/search/suggestions/evaluate` even though the current source maps that endpoint.
- Repair the runtime so the live service exposes the same search surface as the source-run validation lane.
Completion criteria:
- [x] `POST /v1/search/suggestions/evaluate` returns a valid response from the compose-backed service.
- [x] Root cause is documented in the execution log.
- [x] Any required docs are updated.
### AI-LIVE-SEARCH-002 - Restore compose knowledge corpus parity
Status: DONE
Dependency: AI-LIVE-SEARCH-001
Owners: Developer (AdvisoryAI), QA
Task description:
- Determine why compose rebuilds return `documentCount=0`, `apiOperationCount=0`, and `doctorProjectionCount=0`.
- Repair the live compose ingestion path so Doctor/knowledge/API corpus is present and searchable.
Completion criteria:
- [x] Compose rebuild reports non-zero knowledge/API/Doctor corpus counts.
- [x] Doctor and release-oriented queries return grounded results where live corpus exists.
- [x] Evidence is recorded in the execution log.
### AI-LIVE-SEARCH-003 - Verify live browser search parity
Status: DONE
Dependency: AI-LIVE-SEARCH-002
Owners: QA, Documentation, Project Manager
Task description:
- Re-run live Playwright verification from `https://stella-ops.local` across Doctor, releases, findings, and policy routes.
- Archive the sprint only after the compose-backed live service behaves consistently with the documented search experience.
Completion criteria:
- [x] Live Playwright evidence shows grounded or explicit supported fallback on the primary routes.
- [x] Documentation reflects the repaired live-search setup.
- [x] Sprint is archived only after all tasks are DONE.
## Execution Log
| Date (UTC) | Update | Owner |
| --- | --- | --- |
| 2026-03-08 | Sprint created after live Playwright reproduction showed that the compose-backed AdvisoryAI service behind `stella-ops.local` lacked knowledge/API/Doctor corpus parity and returned `404` for `POST /v1/search/suggestions/evaluate`. | Developer |
| 2026-03-08 | Root cause confirmed: the compose image published by `stellaops/advisory-ai-web:dev` did not carry the repo-shaped docs/OpenAPI/KnowledgeSearch corpus required by `KnowledgeSearchRepositoryRootResolver`, and the Docker build context excluded the relevant `docs/**` subset. That left the live service with `documentCount=0`, `apiOperationCount=0`, `doctorProjectionCount=0`, and no mapped `POST /v1/search/suggestions/evaluate` surface on the older image. | Developer |
| 2026-03-08 | Repaired runtime packaging by publishing the required corpus assets from `StellaOps.AdvisoryAI.csproj`, allowing the Docker context to include the documented subset via `.dockerignore`, and adding resolver coverage for the published app layout. Focused verification passed: `KnowledgeSearchRepositoryRootResolverTests` `3/3`, `dotnet publish` produced `/app/docs/**`, `/app/devops/compose/openapi_current.json`, and `/app/src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/*.json`. | Developer |
| 2026-03-08 | Rebuilt and force-recreated `stellaops-advisory-ai-web`, then verified live compose parity directly: `POST /v1/search/suggestions/evaluate` returned grounded viability for `database connectivity`; `POST /v1/advisory-ai/index/rebuild` returned `documentCount=470`, `chunkCount=9050`, `apiSpecCount=1`, `apiOperationCount=2190`, `doctorProjectionCount=8`; `POST /v1/search/index/rebuild` returned `domainCount=8`, `chunkCount=8`. | Developer |
| 2026-03-08 | Live Playwright/browser verification on `https://stella-ops.local` passed after the runtime repair. Typed queries returned grounded answers on `/releases/versions` (`database connectivity`, `pending approvals`), `/security/triage` (`critical findings`), `/ops/policy` (`signed SBOM`), and `/ops/operations/doctor` (`database connectivity`). Release-page suggestion chips also executed successfully: `What blocked this promotion?` returned a grounded answer state from the live shell. | Developer |
## Decisions & Risks
- Decision: treat the remaining live-search failure as an AdvisoryAI/runtime parity problem, not as a frontend-only issue.
- Risk: a partial runtime-only hotfix can restore exact searches while leaving generic operator suggestions misleading.
- Mitigation: verify both endpoint parity and corpus parity before claiming live-search recovery.
- Decision: ship the compose parity fix by packaging a bounded repo-shaped search corpus inside the published AdvisoryAI service image rather than relying on host-mounted repo content.
- Decision: keep the live browser proof against `https://stella-ops.local` even after direct backend checks passed, because the original report was a real shell failure.
## Next Checkpoints
- 2026-03-08: confirm compose endpoint parity root cause.
- 2026-03-08: confirm compose corpus parity repair or record blocker.

View File

@@ -382,6 +382,7 @@ Notes:
- AdvisoryAI knowledge ingestion now auto-detects the repository root from the current working directory and `AppContext.BaseDirectory` when it is running inside a normal Stella Ops source checkout. - AdvisoryAI knowledge ingestion now auto-detects the repository root from the current working directory and `AppContext.BaseDirectory` when it is running inside a normal Stella Ops source checkout.
- Set `AdvisoryAI__KnowledgeSearch__RepositoryRoot` only when you are running the service from a non-standard layout or a packaged binary tree that is not inside the repository. - Set `AdvisoryAI__KnowledgeSearch__RepositoryRoot` only when you are running the service from a non-standard layout or a packaged binary tree that is not inside the repository.
- `stella advisoryai index rebuild` and `stella search index rebuild` invoke authenticated backend endpoints. For a local source-checkout verification lane without a signed-in CLI session, use `sources prepare` via CLI and the direct HTTP rebuild calls above with explicit `X-StellaOps-*` headers. - `stella advisoryai index rebuild` and `stella search index rebuild` invoke authenticated backend endpoints. For a local source-checkout verification lane without a signed-in CLI session, use `sources prepare` via CLI and the direct HTTP rebuild calls above with explicit `X-StellaOps-*` headers.
- Compose/runtime requirement: the published AdvisoryAI service image must carry a repo-shaped local corpus under its app content root so `POST /v1/advisory-ai/index/rebuild` can resolve `docs/**`, `devops/compose/openapi_current.json`, and `src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/*.json` even when the source checkout is not mounted into the container. If those assets are absent, live search on `stella-ops.local` degrades to partial unified rows only and documentation/Doctor/API answers disappear.
### CLI setup in a source checkout ### CLI setup in a source checkout

View File

@@ -23,12 +23,71 @@
<ItemGroup> <ItemGroup>
<None Update="KnowledgeSearch/doctor-search-seed.json"> <None Update="KnowledgeSearch/doctor-search-seed.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/doctor-search-seed.json</TargetPath>
</None> </None>
<None Update="KnowledgeSearch/doctor-search-seed.de.json"> <None Update="KnowledgeSearch/doctor-search-seed.de.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/doctor-search-seed.de.json</TargetPath>
</None> </None>
<None Update="KnowledgeSearch/doctor-search-seed.fr.json"> <None Update="KnowledgeSearch/doctor-search-seed.fr.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/doctor-search-seed.fr.json</TargetPath>
</None>
<None Update="KnowledgeSearch/doctor-search-controls.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/doctor-search-controls.json</TargetPath>
</None>
<None Update="KnowledgeSearch/knowledge-docs-allowlist.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/knowledge-docs-allowlist.json</TargetPath>
</None>
<None Update="KnowledgeSearch/knowledge-docs-manifest.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/knowledge-docs-manifest.json</TargetPath>
</None>
<None Include="..\..\..\devops\compose\openapi_current.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>devops/compose/openapi_current.json</TargetPath>
</None>
<None Include="..\..\..\docs\README.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/README.md</TargetPath>
</None>
<None Include="..\..\..\docs\INSTALL_GUIDE.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/INSTALL_GUIDE.md</TargetPath>
</None>
<None Include="..\..\..\docs\modules\advisory-ai\**\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/modules/advisory-ai/%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</None>
<None Include="..\..\..\docs\modules\authority\**\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/modules/authority/%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</None>
<None Include="..\..\..\docs\modules\cli\**\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/modules/cli/%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</None>
<None Include="..\..\..\docs\modules\platform\**\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/modules/platform/%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</None>
<None Include="..\..\..\docs\modules\policy\**\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/modules/policy/%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</None>
<None Include="..\..\..\docs\modules\router\**\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/modules/router/%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</None>
<None Include="..\..\..\docs\modules\scanner\**\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/modules/scanner/%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</None>
<None Include="..\..\..\docs\operations\**\*.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>docs/operations/%(RecursiveDir)%(Filename)%(Extension)</TargetPath>
</None> </None>
<None Update="models/all-MiniLM-L6-v2.onnx"> <None Update="models/all-MiniLM-L6-v2.onnx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

View File

@@ -220,6 +220,7 @@ curl -X POST http://127.0.0.1:10451/v1/search/index/rebuild \
Notes: Notes:
- `stella advisoryai sources prepare` needs `STELLAOPS_BACKEND_URL` or equivalent CLI config when it performs live Doctor discovery. If you only need local search verification and the checked-in Doctor seed/control files are sufficient, the HTTP-only rebuild path is valid. - `stella advisoryai sources prepare` needs `STELLAOPS_BACKEND_URL` or equivalent CLI config when it performs live Doctor discovery. If you only need local search verification and the checked-in Doctor seed/control files are sufficient, the HTTP-only rebuild path is valid.
- `stella advisoryai index rebuild` and `stella search index rebuild` call authenticated backend endpoints. In the local live-search test lane above, use direct HTTP requests with explicit `X-StellaOps-*` headers unless you already have an authenticated CLI session. - `stella advisoryai index rebuild` and `stella search index rebuild` call authenticated backend endpoints. In the local live-search test lane above, use direct HTTP requests with explicit `X-StellaOps-*` headers unless you already have an authenticated CLI session.
- Compose/runtime note: the `stellaops/advisory-ai-web:dev` image must publish a repo-shaped search corpus under `/app` (`docs/**`, `devops/compose/openapi_current.json`, and `src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/*.json`). Without those assets, compose rebuilds report zero knowledge/API/Doctor counts and the browser shell can only search whatever unified rows were already persisted.
- Current live verification coverage includes the Doctor/knowledge query `database connectivity`, which returns `contextAnswer.status = grounded` plus citations after the rebuild sequence above. - Current live verification coverage includes the Doctor/knowledge query `database connectivity`, which returns `contextAnswer.status = grounded` plus citations after the rebuild sequence above.
Migration files (all idempotent, safe to re-run): Migration files (all idempotent, safe to re-run):

View File

@@ -40,6 +40,21 @@ public sealed class KnowledgeSearchRepositoryRootResolverTests
Assert.NotEqual("configured", resolution.Source); Assert.NotEqual("configured", resolution.Source);
} }
[Fact]
public void Resolve_accepts_runtime_publish_layout_when_app_base_contains_repo_shaped_corpus()
{
using var fixture = RuntimePublishLayoutFixture.Create();
var options = new KnowledgeSearchOptions();
var resolution = KnowledgeSearchRepositoryRootResolver.Resolve(
options,
fixture.AppBaseDirectory,
fixture.AppBaseDirectory);
Assert.True(resolution.Validated);
Assert.Equal(fixture.AppBaseDirectory, resolution.Path);
}
private sealed class RepositoryRootFixture : IDisposable private sealed class RepositoryRootFixture : IDisposable
{ {
private RepositoryRootFixture( private RepositoryRootFixture(
@@ -99,4 +114,50 @@ public sealed class KnowledgeSearchRepositoryRootResolverTests
} }
} }
} }
private sealed class RuntimePublishLayoutFixture : IDisposable
{
private RuntimePublishLayoutFixture(string workspaceRoot, string appBaseDirectory)
{
WorkspaceRoot = workspaceRoot;
AppBaseDirectory = appBaseDirectory;
}
public string WorkspaceRoot { get; }
public string AppBaseDirectory { get; }
public static RuntimePublishLayoutFixture Create()
{
var workspaceRoot = Path.Combine(Path.GetTempPath(), "stellaops-knowledge-runtime-" + Guid.NewGuid().ToString("N"));
var appBaseDirectory = Path.Combine(workspaceRoot, "app");
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"));
File.WriteAllText(Path.Combine(appBaseDirectory, "docs", "README.md"), "# docs");
File.WriteAllText(Path.Combine(appBaseDirectory, "docs", "modules", "advisory-ai", "knowledge-search.md"), "# advisory");
File.WriteAllText(Path.Combine(appBaseDirectory, "devops", "compose", "openapi_current.json"), "{}");
File.WriteAllText(
Path.Combine(appBaseDirectory, "src", "AdvisoryAI", "StellaOps.AdvisoryAI", "KnowledgeSearch", "knowledge-docs-allowlist.json"),
"{ \"include\": [\"docs/modules/advisory-ai\"] }");
File.WriteAllText(
Path.Combine(appBaseDirectory, "src", "AdvisoryAI", "StellaOps.AdvisoryAI", "KnowledgeSearch", "doctor-search-seed.json"),
"[]");
File.WriteAllText(
Path.Combine(appBaseDirectory, "src", "AdvisoryAI", "StellaOps.AdvisoryAI", "KnowledgeSearch", "doctor-search-controls.json"),
"[]");
return new RuntimePublishLayoutFixture(workspaceRoot, appBaseDirectory);
}
public void Dispose()
{
if (Directory.Exists(WorkspaceRoot))
{
Directory.Delete(WorkspaceRoot, recursive: true);
}
}
}
} }