diff --git a/.dockerignore b/.dockerignore index ea278bb2c..7e44b5537 100644 --- a/.dockerignore +++ b/.dockerignore @@ -27,3 +27,23 @@ devops/helm *.png *.jpg *.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/** diff --git a/docs-archived/implplan/SPRINT_20260308_002_FE_search_live_browser_reproduction_and_fix.md b/docs-archived/implplan/SPRINT_20260308_002_FE_search_live_browser_reproduction_and_fix.md new file mode 100644 index 000000000..ece7cc46f --- /dev/null +++ b/docs-archived/implplan/SPRINT_20260308_002_FE_search_live_browser_reproduction_and_fix.md @@ -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. diff --git a/docs-archived/implplan/SPRINT_20260308_003_AdvisoryAI_live_search_compose_parity.md b/docs-archived/implplan/SPRINT_20260308_003_AdvisoryAI_live_search_compose_parity.md new file mode 100644 index 000000000..a061a8730 --- /dev/null +++ b/docs-archived/implplan/SPRINT_20260308_003_AdvisoryAI_live_search_compose_parity.md @@ -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. diff --git a/docs/modules/advisory-ai/knowledge-search.md b/docs/modules/advisory-ai/knowledge-search.md index 6a6430111..b56ea3f40 100644 --- a/docs/modules/advisory-ai/knowledge-search.md +++ b/docs/modules/advisory-ai/knowledge-search.md @@ -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. - 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. +- 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 diff --git a/src/AdvisoryAI/StellaOps.AdvisoryAI/StellaOps.AdvisoryAI.csproj b/src/AdvisoryAI/StellaOps.AdvisoryAI/StellaOps.AdvisoryAI.csproj index d5daac278..8dc6a3514 100644 --- a/src/AdvisoryAI/StellaOps.AdvisoryAI/StellaOps.AdvisoryAI.csproj +++ b/src/AdvisoryAI/StellaOps.AdvisoryAI/StellaOps.AdvisoryAI.csproj @@ -23,12 +23,71 @@ PreserveNewest + src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/doctor-search-seed.json PreserveNewest + src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/doctor-search-seed.de.json PreserveNewest + src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/doctor-search-seed.fr.json + + + PreserveNewest + src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/doctor-search-controls.json + + + PreserveNewest + src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/knowledge-docs-allowlist.json + + + PreserveNewest + src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/knowledge-docs-manifest.json + + + PreserveNewest + devops/compose/openapi_current.json + + + PreserveNewest + docs/README.md + + + PreserveNewest + docs/INSTALL_GUIDE.md + + + PreserveNewest + docs/modules/advisory-ai/%(RecursiveDir)%(Filename)%(Extension) + + + PreserveNewest + docs/modules/authority/%(RecursiveDir)%(Filename)%(Extension) + + + PreserveNewest + docs/modules/cli/%(RecursiveDir)%(Filename)%(Extension) + + + PreserveNewest + docs/modules/platform/%(RecursiveDir)%(Filename)%(Extension) + + + PreserveNewest + docs/modules/policy/%(RecursiveDir)%(Filename)%(Extension) + + + PreserveNewest + docs/modules/router/%(RecursiveDir)%(Filename)%(Extension) + + + PreserveNewest + docs/modules/scanner/%(RecursiveDir)%(Filename)%(Extension) + + + PreserveNewest + docs/operations/%(RecursiveDir)%(Filename)%(Extension) PreserveNewest diff --git a/src/AdvisoryAI/__Tests/INFRASTRUCTURE.md b/src/AdvisoryAI/__Tests/INFRASTRUCTURE.md index d35c79c45..a93f6964b 100644 --- a/src/AdvisoryAI/__Tests/INFRASTRUCTURE.md +++ b/src/AdvisoryAI/__Tests/INFRASTRUCTURE.md @@ -220,6 +220,7 @@ curl -X POST http://127.0.0.1:10451/v1/search/index/rebuild \ 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 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. Migration files (all idempotent, safe to re-run): diff --git a/src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/KnowledgeSearch/KnowledgeSearchRepositoryRootResolverTests.cs b/src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/KnowledgeSearch/KnowledgeSearchRepositoryRootResolverTests.cs index 519d02d96..ff05849c9 100644 --- a/src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/KnowledgeSearch/KnowledgeSearchRepositoryRootResolverTests.cs +++ b/src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/KnowledgeSearch/KnowledgeSearchRepositoryRootResolverTests.cs @@ -40,6 +40,21 @@ public sealed class KnowledgeSearchRepositoryRootResolverTests 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 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); + } + } + } }