Repository navigation
Conversation
feat(research): add municipality research areas
refactor(geo): use research area search across admin
feat(research-ai): add event vector search benchmark
feat(research): add experimental semantic event search
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Promotes the current
devbranch tomainwith municipality-based Research areas, a shared administrative area selector, an event vector retrieval pilot, and explicitly selected experimental semantic event search for authenticated Research users.mainwas fetched and merged intodevwithout conflicts, rebase, or rewritten history. The two main-only commits (3242152, PR #130;8a11d2d, PR #133) are previous promotion merges: each has exactly the same tree as its merged dev parent, so their content was already present. Integration merge:1a6c60d0840f3884a9a911ce93f8086fa831e54b. A separate3d4db23commit removes seven trailing-whitespace occurrences; no functional release-preparation changes were needed.Comparison before integration: main
8a11d2deedb5f6f3751200fb21877efbc94960bb, dev7a85a608a788b36bbd283d6f50a8ba0e72cadf8a; 2 main-only and 21 dev-only commits. During validation, remote dev advanced to183097e33cf0d1399a80cdff3e4f18f336e87031(PR #137, commitsaf2a724and1ef00ee). Those three additional commits were preserved via mergea03dc01aec4ffd3d12bbdb479770fc26eb7be270in an isolated release worktree. Final comparison: 0 main-only and 27 dev-only commits. Backend/frontend checks were rerun; the Ansible tree is identical to the fully tested tree.Highlights
Database
backend/migrations/versions/0016_research_area.py, following0015.alembic headsandalembic historyconfirm a linear chain. No migration conflict or merge migration.admin.research_area, geometry/centroid and population provenance constraints, a GiST geometry index and a country/type index. No Uranus DDL or writes.admin_migratorconnection before starting the new backend/workers, then provision the documented grants: runtimeadmin_usergets SELECT only;admin_auth_operatorgets SELECT/INSERT/UPDATE. Readiness enforces the current head and grants.alembic checkwere not run locally because no disposable DB was used. CI is required for those checks.AI / Search
This diff provides both operator-only indexing/benchmarking and authenticated experimental semantic event search. Classic search remains the default; users explicitly select semantic mode. The Research API requires journalist or system administrator access, and PostgreSQL remains authoritative for current public eligibility, displayed records and structured filters. Vector payload prose and scores are not displayed.
Online retrieval fixes the model to Jina v3. The direct encoder/Qdrant path fetches at most 50 chunks and returns at most 20 rehydrated current events. The optional exact HTTPS
/searchgateway supplies at most 10 candidates before filtering. Counts describe the bounded selection, not all source matches; semantic mode does not offer misleading full-result export, pagination or classic sorting. Network calls finish before acquiring the source snapshot, with an 8-second overall deadline under Nitro's 10-second proxy limit. Errors fail safely without automatic fallback.SEMANTIC_SEARCH_NONCOMMERCIAL_JINAdefaults false and requires explicit operator acknowledgment for the noncommercial pilot. OptionalSEMANTIC_SEARCH_URLselects the configured HTTPS gateway; otherwise protected encoder/Qdrant credentials are required. Query text is sent to the selected trusted service. The documented gateway currently accepts requests without authentication, but no admin cookies, vector keys or other admin credentials are forwarded. Redirects and environment proxies are disabled; query/body logging must remain off. No production configuration, new service deployment or source write is performed by this PR preparation.The optional CPU encoder/Qdrant pilot supports pinned E5-small, E5-base and Jina-v3 models, private authenticated services, single-job indexing, resource ceilings and offline model loading. No model weights, Qdrant storage/snapshots, private keys, runtime/operator env files or production secrets are committed. Checked-in benchmark JSON/CSV and snapshot metadata under
docs/research-ai/results/2026-09-27/are intentional documentation, not binary snapshots or local test output.backend/.env.examplecontains only example/default settings.Historical benchmark measurements retain provenance; no relevance judgments or production model winner are fabricated. The legacy exports lack review excerpts and must be regenerated into a new private directory for pooled manual review. No LLM, chat, generated SQL, automatic interpretation of geographic/date constraints or automatic indexing is introduced.
Validation
uv sync --lockeduv run alembic heads/historyuv run mypyuv run pytest -q -rapnpm install --frozen-lockfilepnpm testpnpm build/tmpbash -npassedgit diff --check origin/main...devThe extra non-gating Prettier audit of all changed Markdown files reports
ansible/README.md,backend/docs/development.mdandbackend/docs/geo-scope.md. The same three files already fail onorigin/main, with identical formatting-change line counts (88, 106 and 87 respectively). No repository Markdown CI gate is configured; this pre-existing formatting debt is preserved and disclosed.Local E2E covers the four relevant specs, not the entire visual suite. The first production attempt stopped before tests because an existing
test-results/.last-run.jsonwas not writable; the successful rerun used a fresh/tmpoutput directory. Final Production E2E also covers the newly integrated semantic-search UI. The full pinned browser/OS visual suite, database deployment matrix, CodeQL and dependency review remain GitHub Actions checks; CodeQL was not recreated locally.Local Docker tests were explicitly excluded by the requester. This PR is intentionally not a draft, also explicitly requested; outstanding integration checks are disclosed rather than treated as passing. No production database, deployment or live AI service was touched.
Deployment notes
/ready, workers and Research/GeoScope behavior separately; import reviewed municipality boundaries/population data with the separate operator commands when needed.Risk / rollback
The largest changes affect spatial selection across Research/Operations, area schema/privileges, the optional vector extraction/index lifecycle, and external semantic retrieval. Candidate limits can omit relevant matches, index ranking can lag edits, and upstream rate limits/timeouts can make semantic search unavailable. PostgreSQL/PostGIS/Qdrant integration and the CI deployment matrix remain release gates; local browser checks do not establish live backend integration.
An older backend expects its exact migration head, so application-only rollback against revision 0016 can fail readiness. Coordinate rollback with a reviewed admin backup/schema plan; downgrading 0016 drops imported area metadata and requires a backup/reimport plan. Never change Uranus data for rollback. The optional AI stack can be stopped separately; preserve protected credentials, model cache and Qdrant storage/snapshots for recovery or rebuild from the read-only source.
No force push, direct main change, auto-merge or branch-protection bypass is part of this promotion.