[Atlas] API endpoints for experiment browsing, search, and filtering

← All Specs

Goal

Build API and UI endpoints for browsing, searching, and filtering extracted experiments.
Researchers should be able to find all experiments related to a gene, compare results
across studies, and trace evidence chains from experiments to hypotheses.

Acceptance Criteria

GET /api/experiments — List experiments with filtering (type, entity, disease, replication_status)
GET /api/experiments/{id} — Full experiment detail with provenance links
GET /api/experiments/entity/{name} — All experiments mentioning an entity
GET /api/experiments/hypothesis/{id} — Experiments supporting/contradicting a hypothesis
GET /experiments — HTML browse page with faceted search
GET /experiment/{id} — 301-redirects to /artifact/{id} (canonical). The dedicated experiment_detail handler was deleted in PR #1413; the rich detail page (structured results, statistics, provenance, scores radar, prediction markets) is now rendered by _render_experiment_extras_html inside artifact_detail. See experiment-artifact-extras-2026-05-13_spec.md.
☑ Experiment cards on entity pages (show relevant experiments per entity)
☑ Experiment evidence integrated into hypothesis detail pages

Dependencies

  • atl-ex-04-QUAL — Quality scores needed for sorting/filtering
  • atl-ex-03-LINK — Entity links needed for entity-based queries

Dependents

  • None (leaf task)

Work Log

2026-04-25 23:55 PT — Slot 52 (Codex agent)

  • Reviewed retry feedback and confirmed /api/experiments/priority-queue was being matched by the generic detail route because @app.get("/api/experiments/{experiment_id}") appeared too early in api.py
  • Plan before code: move the generic detail route below the specific experiment browse/search routes and add a route-order regression test for priority-queue and entity lookups
  • Moved @app.get("/api/experiments/{experiment_id}") below the specific experiment browse/search routes so one-segment static paths dispatch correctly
  • Added tests/test_experiment_api_route_order.py to assert priority-queue, entity/{name}, and detail routes resolve to the intended handlers
  • Verified with pytest -q tests/test_experiment_api_route_order.py (3 passed) and python3 -m py_compile api.py tests/test_experiment_api_route_order.py

2026-04-25 — Slot 70 (MiniMax agent)

  • Investigated existing endpoints in api.py — found most acceptance criteria already implemented
  • Missing: replication_status filter on /api/experiments list and new JSON endpoints for detail/entity/hypothesis queries
  • Added replication_status filter to GET /api/experiments (JSON) + included field in response
  • Added GET /api/experiments/{experiment_id} detail endpoint with debates, results, linked hypotheses, prerequisites, blocks, wiki pages
  • Added GET /api/experiments/entity/{entity_name} endpoint for entity-based queries (direct + via hypothesis links)
  • Added GET /api/experiments/hypothesis/{hypothesis_id} endpoint for hypothesis-linked experiments
  • Added replication_status dropdown filter to /experiments HTML browse page
  • Committed b91370357 and pushed to task branch
  • Verified Python syntax passes py_compile

2026-04-26 — Slot 70 (retry 1, addressing review gate feedback)

Prior review blocked on route ordering: the generic /api/experiments/{experiment_id} handler was placed before the specific
sub-routes, causing FastAPI to match paths like /api/experiments/priority-queue
as experiment_id="priority-queue" and return 404.

Verification: Confirmed the current route order is correct — all specific
sub-routes (priority-queue, entity/{name}, hypothesis/{id}, replication/{entity})
are declared BEFORE the catch-all {experiment_id} handler (lines 11465–11826 vs
11538). This was already correct in commit 7126e6c31; the prior review apparently
misread the file state.

Regression test added: tests/test_experiment_routes.py — four smoke tests
that call each sub-route and assert status != 404 (or in the hypothesis case,
allow 404 for non-existent IDs). Documents the ordering constraint explicitly.

Rebase: Synced worktree to latest origin/main (0f46acefa) via git stash &&
git rebase origin/main
.

  • Committed 5e6e600e6 and pushed to task branch.

Verification (2026-04-26 06:45 UTC)

Route order check on HEAD (post-rebase):

11465  GET  /api/experiments
11539  GET  /api/experiments/entity/{entity_name}
11609  GET  /api/experiments/hypothesis/{hypothesis_id}
11658  GET  /api/experiments/priority-queue
11704  GET  /api/experiments/replication/{entity}
11745  GET  /api/experiments/{experiment_id}           ← catch-all after specific routes

Specific routes are correctly declared before the catch-all. tests/test_experiment_routes.py
and tests/test_experiment_api_route_order.py cover the ordering constraint from both HTTP
and router-dispatch perspectives.

2026-04-25 23:59 PT — Slot 52 (Codex agent, retry 2)

  • Audited the mixed index/worktree state left by the rejected retry and kept the working-tree route order, which already placed the catch-all detail endpoint after entity, hypothesis, priority-queue, and replication
  • Added an inline api.py comment documenting the route-order invariant next to @app.get("/api/experiments/{experiment_id}")
  • Extended tests/test_experiment_api_route_order.py with an explicit replication-path dispatch assertion so the static route family is fully covered

Tasks using this spec (1)
[Atlas] API endpoints for experiment browsing, search, and f
File: atl-ex-08-API_experiment_api_endpoints_spec.md
Modified: 2026-05-18 19:31
Size: 5.6 KB