From eed7cabd84dce17ae351bb9a8a9560107b07bca2 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 27 Aug 2026 01:27:13 +0900 Subject: [PATCH 1/2] fix: restore Global Ask worker capabilities --- backend/app/worker.py | 4 +++ backend/tests/test_api.py | 37 +++++++++++++++++++++++++--- tests/test_backend_worker_process.py | 17 ++++++++++--- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/backend/app/worker.py b/backend/app/worker.py index fb9662f26..06bfaee10 100644 --- a/backend/app/worker.py +++ b/backend/app/worker.py @@ -12,9 +12,11 @@ from backend.app.global_ask_queue import run_global_ask_worker from backend.app.main import ( _adjudication_client, + _claim_verification_client_factory, _embedding_client, _post_chat_client, _post_structure_client, + _semantic_query_client, _vision_client, ) from backend.app.post_content_worker import run_post_content_worker @@ -59,6 +61,8 @@ async def run_worker_process() -> None: timeout=load_settings().orchestrator_answer_timeout_seconds ), embedding_factory=_embedding_client, + semantic_query_factory=_semantic_query_client, + claim_verification_factory=_claim_verification_client_factory, ) ), ) diff --git a/backend/tests/test_api.py b/backend/tests/test_api.py index 46638f0fb..8bc95d482 100644 --- a/backend/tests/test_api.py +++ b/backend/tests/test_api.py @@ -15,6 +15,7 @@ import asyncio import math import os +import subprocess import time import uuid from contextlib import closing @@ -193,6 +194,21 @@ / "migrations" / "0203_global_ask_authorization_scope.sql" ) +_GLOBAL_ASK_EVIDENCE_SEARCH_MIGRATION = ( + Path(__file__).resolve().parents[2] + / "migrations" + / "0210_global_ask_evidence_search_indexes.sql" +) +_GLOBAL_ASK_PUBLIC_VERIFICATION_MIGRATION = ( + Path(__file__).resolve().parents[2] + / "migrations" + / "0218_global_ask_public_verification.sql" +) +_GLOBAL_ASK_KNOWLEDGE_CUTOFF_MIGRATION = ( + Path(__file__).resolve().parents[2] + / "migrations" + / "0212_global_ask_knowledge_cutoff.sql" +) _PRODUCT_SEMANTIC_MIGRATIONS = tuple( Path(__file__).resolve().parents[2] / "migrations" / name for name in ( @@ -420,7 +436,18 @@ def seeded_db(demo_analyst_token): cur.execute(_LEFTOVER_MAP_COVERAGE_MIGRATION.read_text()) cur.execute(_GLOBAL_ASK_JOB_MIGRATION.read_text()) cur.execute(_GLOBAL_ASK_SCOPE_MIGRATION.read_text()) - cur.execute(_GLOBAL_ASK_EVIDENCE_SEARCH_MIGRATION.read_text()) + subprocess.run( + [ + "psql", + "-X", + "-v", + "ON_ERROR_STOP=1", + db_dsn, + "-f", + str(_GLOBAL_ASK_EVIDENCE_SEARCH_MIGRATION), + ], + check=True, + ) cur.execute(_GLOBAL_ASK_KNOWLEDGE_CUTOFF_MIGRATION.read_text()) cur.execute(_GLOBAL_ASK_PUBLIC_VERIFICATION_MIGRATION.read_text()) cur.execute(_EVENT_OCCURRED_AT_MIGRATION.read_text()) @@ -845,6 +872,8 @@ async def run_worker() -> None: timeout=load_settings().orchestrator_answer_timeout_seconds ), embedding_factory=lambda: main_module._embedding_client(), + semantic_query_factory=lambda: main_module._semantic_query_client(), + claim_verification_factory=lambda: main_module._claim_verification_client_factory(), ) assert client.portal is not None @@ -5553,7 +5582,7 @@ async def _fake_compute_answer(*_args, **_kwargs): def test_ask_public_verification_is_opt_in_and_separate_from_post_citations( - client, demo_analyst_token, seeded_db, monkeypatch + client_with_ask_worker, demo_analyst_token, seeded_db, monkeypatch ) -> None: """A cited public semantic claim can be refuted without changing its post id.""" @@ -5607,7 +5636,7 @@ def verify(self, claim): lambda: _FakeVerificationClient(), ) headers = {"Authorization": f"Bearer {demo_analyst_token}"} - submitted = client.post( + submitted = client_with_ask_worker.post( "/api/ask", json={"question": "Apollo", "verify_external": True}, headers=headers, @@ -5618,7 +5647,7 @@ def verify(self, claim): deadline = _time.monotonic() + 30 body: dict = {} while _time.monotonic() < deadline: - body = client.get(f"/api/ask/jobs/{job_id}", headers=headers).json() + body = client_with_ask_worker.get(f"/api/ask/jobs/{job_id}", headers=headers).json() if body["job_status_code"] in ("succeeded", "failed"): break _time.sleep(0.25) diff --git a/tests/test_backend_worker_process.py b/tests/test_backend_worker_process.py index 4ba2b0a4d..2d57eb31f 100644 --- a/tests/test_backend_worker_process.py +++ b/tests/test_backend_worker_process.py @@ -52,6 +52,7 @@ def test_worker_process_owns_all_three_durable_consumers(monkeypatch) -> None: pool = _Closable() valkey = _Closable() calls: list[str] = [] + global_ask_kwargs: dict = {} settings = SimpleNamespace( database_url="db", valkey_url="valkey", @@ -63,6 +64,10 @@ def test_worker_process_owns_all_three_durable_consumers(monkeypatch) -> None: async def called(name: str, *_args, **_kwargs) -> None: calls.append(name) + async def global_ask(*_args, **kwargs) -> None: + global_ask_kwargs.update(kwargs) + calls.append("global_ask") + monkeypatch.setattr(worker, "load_settings", lambda: settings) monkeypatch.setattr(worker, "create_pool", lambda _url: _async_value(pool)) monkeypatch.setattr(worker, "create_valkey_client", lambda _url: valkey) @@ -74,6 +79,12 @@ async def called(name: str, *_args, **_kwargs) -> None: monkeypatch.setattr(worker, "_embedding_client", lambda: object()) monkeypatch.setattr(worker, "_post_structure_client", lambda: object()) monkeypatch.setattr(worker, "_post_chat_client", lambda **_kwargs: object()) + semantic_client = object() + verification_client = object() + monkeypatch.setattr(worker, "_semantic_query_client", lambda: semantic_client) + monkeypatch.setattr( + worker, "_claim_verification_client_factory", lambda: verification_client + ) monkeypatch.setattr(worker, "run_worker_heartbeat", lambda: _async_value(None)) monkeypatch.setattr( worker, "run_analysis_run_worker", lambda *a, **kw: called("analysis", *a, **kw) @@ -81,13 +92,13 @@ async def called(name: str, *_args, **_kwargs) -> None: monkeypatch.setattr( worker, "run_post_content_worker", lambda *a, **kw: called("content", *a, **kw) ) - monkeypatch.setattr( - worker, "run_global_ask_worker", lambda *a, **kw: called("global_ask", *a, **kw) - ) + monkeypatch.setattr(worker, "run_global_ask_worker", global_ask) asyncio.run(worker.run_worker_process()) assert calls[:3] == ["analysis", "content", "global_ask"] + assert global_ask_kwargs["semantic_query_factory"]() is semantic_client + assert global_ask_kwargs["claim_verification_factory"]() is verification_client assert calls[-1] == "shutdown" assert pool.closed assert valkey.closed From c7e961b8b4b85400e013fc4ea73d0a2694120565 Mon Sep 17 00:00:00 2001 From: Codex Date: Thu, 27 Aug 2026 01:45:30 +0900 Subject: [PATCH 2/2] docs: record Dashboard worker follow-up evidence --- docs/product-technical-gap-baseline.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index fbfe5c9d5..f5e3b0851 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,14 +1,17 @@ # Product & Technical Gap Baseline -> Dashboard delivery snapshot: 2026-08-27 00:50 KST. Protected `main` was +> Dashboard delivery snapshot: 2026-08-27 01:44 KST. Protected `main` was > `ff7431bd1851c03e737808d22c6a2d43968582f9`. Dashboard PR #640 exact -> observed head was `fa9f0aeb5225035264ebc0579c127d1f283c0b17`; this branch is not -> protected-main release evidence. The queue contained 23 open PRs (21 -> `BLOCKED`, one `UNSTABLE`, one `CLEAN`) and no exact-head approval. Stacked -> repair PR #715 was based exactly on #640 and its pre-documentation head -> `5746c57d` passed 44 focused tests; it repairs the four stale HTTP transport -> test doubles and narrowly excludes one Python-before-3.7 Semgrep rule that -> contradicts the repository's Python >=3.12 contract. +> observed head was `5594029c801263a7f629c287ce41580ecf4e0739`; this branch is not +> protected-main release evidence. The queue contained 29 open PRs (22 +> `BLOCKED`, five `UNSTABLE`, two `CLEAN`) and no exact-head approval. PR #715 +> merged normally into #640 and repaired the four stale HTTP transport test +> doubles plus one Python-before-3.7 Semgrep false positive that contradicted +> the repository's Python >=3.12 contract. Stacked PR #722 pre-documentation +> head `eed7cabd` restores semantic-query and opt-in public-verification +> factories in the dedicated Ask worker and the production-equivalent +> concurrent-migration fixture path; its focused evidence is 46 unit tests and +> one live Keycloak/PostgreSQL public-verification integration test. ## Operations Dashboard PRD/TRD traceability @@ -22,7 +25,7 @@ the current #640 head. The canonical containers currently return HTTP 200 from backend `/healthz` and the frontend root, but their Compose labels do not prove the source commit; therefore neither the running stack nor the historical k6 run is exact-head authenticated acceptance. Exact-head desktop/mobile -screenshots and k6 remain required after #715 is incorporated and #640 is +screenshots and k6 remain required after #722 is incorporated and #640 is rebuilt. Historical test projects are retired only by their exact Compose project label and without named-volume deletion. PR #678 implementation head `da98de07` fixes the default project name; its follow-up exact-label audit also