Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions backend/app/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Comment thread
seonghobae marked this conversation as resolved.
)
),
)
Expand Down
37 changes: 33 additions & 4 deletions backend/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import asyncio
import math
import os
import subprocess
import time
import uuid
from contextlib import closing
Expand Down Expand Up @@ -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 (
Expand Down Expand Up @@ -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,
)
Comment thread
seonghobae marked this conversation as resolved.
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())
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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."""

Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down
21 changes: 12 additions & 9 deletions docs/product-technical-gap-baseline.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -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
Expand Down
17 changes: 14 additions & 3 deletions tests/test_backend_worker_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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)
Expand All @@ -74,20 +79,26 @@ 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)
)
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
Expand Down
Loading