Commit Graph

3 Commits

Author SHA1 Message Date
dab3bb2437 feat(nadia): @nadia: Fix the two review findings in the research engine: (1) retry failed wor
Outcome: done
Changed: src/typosaurus_sandbox/research/engine.py:108-111,156-163,173-177, src/typosaurus_sandbox/research/pipeline.py:20-23,187-234,296-312, tests/test_research_engine.py:186-290, tests/test_research_pipeline.py:292-354
Verified by: verify() -> "make verify" exit_code 0, "Ran 226 tests OK verification passed"; only pre-existing StarletteDeprecationWarning from fastapi/testclient.py import in tests/test_api.py, none introduced
Findings: Retry: pipeline.py:192-211 retries RsearchError status>=500 with backoff min(0.5*2^(attempt-1),8.0) up to RETRY_MAX_ATTEMPTS=3 (pipeline.py:20-23); status<500 or None not retried. Unexpected exceptions recorded as failure WorkOutcome in consume (pipeline.py:296-312), appended to outcomes. Closure gated on requests_failed==0 (engine.py:159-163); report.closed=requests_failed==0 (engine.py:177); failed round prevents closure, later clean round keeps report.closed False (tests/test_research_engine.py:229-290). Deep/ai wired: every popped query yields WorkItem("web",query,deep=True,ai=True) (engine.py:111); pipeline passes deep/ai to client.search and cache probe (pipeline.py:157-158,170-176); test proves seed+subtopic web calls all carry deep=True and ai=True (tests/test_research_engine.py:203-222). Fix committed as 472a59e; this node's working-tree delta is only trailing-blank cleanup; no new dependencies, client.py/cache.py/config.py/frontier.py untouched.
Open: none
Confidence: high - all six acceptance criteria met with direct

Typosaurus-Run: 4e2afb673c7f4578a12276d9181b982d
Typosaurus-Node: e6071c7595ab487b84f99476243abe28
Typosaurus-Agent: @nadia
Refs: #31
2026-08-08 02:56:05 +00:00
472a59e122 feat(tanya): Audit tests/ for skipped, disabled, or weakened tests
Outcome: done
Changed: none
Verified by: PYTHONPATH=src python3 -m unittest discover -s tests -q -> "Ran 226 tests in 0.634s OK", EXIT_CODE=0
Findings: Criterion 1 PASS - grep for unittest.skip|skipIf|skipUnless|SkipTest|expectedFailure|pytest.mark.skip|pytest.skip|xfail|@skip|@disabled|pytestmark across tests/ returned 0 hits; case-insensitive skipif|skipunless|onlyif|not implemented also 0; runtime report shows no skipped/expected-failure suffix
Findings: Criterion 2 PASS - grep '^\s*(pass|\.\.\.)\s*$' returned 0 hits; AST scan of all 226 test_* functions found none with only-pass body and every one contains >=1 assertion (bare assert or self.assert*/fail* call)
Findings: Criterion 3 PASS - all 25 broad 'skip' grep hits individually inspected and are duplicates_skipped/cache counters or test names, not directives: tests/test_research_engine.py:132-136, tests/test_research_dedup.py:105-233, tests/test_research_scheduling.py:226-496, tests/test_research_client.py:426,434; bare 'return' at tests/test_research_scheduling.py:149,175,289 are worker loop-exit control flow (assertions at 157-162,183-186,298-300); tests/test_research_pipeline.py:333 tests exception handling with assertions at 344-351
Findings: Criterion 4 PASS - evidence recorded as file:line references above and stored in tree finding
Findings: Supplemental sweep for __test__|no cover|pragma|.skip(|mark. returned 0 hits; suite has grown to 226 tests (previous run 219) with no skipped/expected failures reported
Open

Typosaurus-Run: 4e2afb673c7f4578a12276d9181b982d
Typosaurus-Node: 46ed07b2395240b297e0fedbe3b672cd
Typosaurus-Agent: @tanya
Refs: #31
2026-08-08 02:54:49 +00:00
c0a59b4138 feat(nadia): Build content-type agnostic pipeline with bounded asyncio worker pool
Outcome: done
Changed: src/typosaurus_sandbox/research/pipeline.py:1-280 (new), src/typosaurus_sandbox/research/client.py:30-52,98-99,124-148, src/typosaurus_sandbox/research/__init__.py:21-49
Verified by: make verify -> exit_code 0, compileall OK, 195 tests OK, "verification passed" (pre-existing StarletteDeprecationWarning from tests/test_api.py); live smoke: web/images/chat via one pool (3 ok, urls=19, queries=92, contents=10), repeat web item cache_hit=True, empty query -> RsearchError 400 handled, pool survived
Findings:
- ResearchPipeline uses asyncio.Semaphore(max_concurrency, default 8); pool size logged INFO in run(); run(AsyncIterator[WorkItem]) = bounded queue (pool*4) + pool_size workers with None sentinels; process(item) is the public semaphore-guarded path.
- WorkItem(kind: web|images|describe|chat, value, deep=False, ai=False); web -> search(content=True), images -> search(type="images") without deep/ai, describe -> describe(url), chat -> chat(prompt); endpoints /search,/describe,/chat.
- extract_response() handles SearchResponse (results, ai_response, deep sources/markdown), ChatResponse.response, DescribeResponse.description in one function; apply_extraction() registers URLs, query seeds (title/description/extra/text with origin) and content fingerprints into QueryFrontier.
- client.py additive: _search_params() shared by search() and new search_cached()/describe_cached() probes so pipeline cache_hit is accurate; chat/deep cache hit from envelope fields cache

Typosaurus-Run: 4e2afb673c7f4578a12276d9181b982d
Typosaurus-Node: e85a60edbf7b47f1913d87602b9c553c
Typosaurus-Agent: @nadia
Refs: #31
2026-08-07 19:30:57 +00:00