feat: admin TOC Validator screen (339595) - #398
Open
Us3r369 wants to merge 3 commits into
Open
Conversation
Add a standalone evaluation script that flags document sections whose
classified-TOC section type is excluded from Search by default despite
falling inside the human-set main-body page range
("Introduction - before beginning of Annexes"). Such sections are body
content that silently disappears from default search results.
Reads the body page range and the classified TOC from the Postgres
sidecar (docs_<data_source>) via PostgresClient.fetch_all_docs(), and
compares each in-range section label against the default-included set
mirrored from ui/frontend/src/utils/searchUrl.ts. Emits a per-document
xlsx report plus a console summary tallying which excluded section types
appear inside body ranges.
Includes unit tests for the page-range parsing, classified-TOC parsing
(incl. the real "[Front]" marker and roman-numeral page aliases),
in-range exclusion detection, document verdict, and document selection.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire the section-inclusion check into the app as a new superuser-only admin
tab. It lists documents, lets an admin select some or all and run validation,
persists and shows each verdict (pass/fail/skipped, with the excluded section
types), and links out to the Metadata and Contents views to verify or fix a
classification manually. Editing a classification re-validates that document.
The check compares the *current* classified TOC against the human-set body page
range ("Introduction - before beginning of Annexes"); it does not re-tag.
Shared logic
- Extract the validation logic into pipeline/validation/section_inclusion.py so
the backend service and the offline eval script share one implementation; the
eval script now imports from it (no behaviour change).
Backend (superuser-only, rate-limited)
- POST /toc-validator/run — validate selected docs, persist, return results
- GET /toc-validator/results — previously-stored results for the screen on load
- Results are stored per document under sys_toc_validation via
merge_doc_sys_fields (same mechanism as sys_toc_approved); no migration needed
as docs_<source> tables auto-create sys_* columns on write.
Frontend
- New TOC Validator admin tab (TocValidatorManager + table + result cell +
useTocValidator hook), reusing the /documents endpoint and the existing
MetadataModal and TocModal. Styling uses the app's design tokens and shared
badge/table/button classes.
Tests & docs
- Unit tests for the shared logic and the backend service; frontend tests for
the manager, table and result cell. Docs page at docs/admin/toc-validator.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
When testing locally, the TOC validator flagged many cases with section type "introduction" outside of the "Introduction - before beginning of Annexes (start_page_number, end_page_number)" range. Flagging this here to discuss if this is expected and acceptable or should be adjusted! |
dividor
requested changes
Jul 21, 2026
dividor
left a comment
Owner
There was a problem hiding this comment.
Please ensure the table column is clearly labelled so a person reading it knows exactly what it is 'Table of Contents review'. Also make sure it's filterable if not already.
- Rename the verdict column header "Validation" -> "Table of Contents review". - Add per-column filters (funnel popovers) to Title, Organization, Status and the review verdict, reusing the Documents Library filter styling (filter-popover / filter-multiselect classes). - Load all documents for the data source client-side so every filter — including the client-only verdict — applies across the whole set, not just one page; filtering, pagination and "select all" now operate on the filtered set. New TocValidatorFilterPopover (text filter for title, checkbox multiselect for organization/status/review). Frontend tests cover the rename and status filtering; full suite green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
@dividor adjusted column header and added filters in latest commit |
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
Adds an admin TOC Validator screen (ticket 339595) that surfaces documents whose body content is at risk of being hidden from Search because of how its sections are tagged.
Search's default content type filter only returns chunks whose section type is one of the "real content" types (
executive_summary, context, methodology, findings, conclusions, recommendations, other). Everything else —front_matter, acronyms, annexes, appendix, bibliography, introduction— is excluded by default. Tagging is automatic at upload, so a body section mis-tagged as e.g.annexessilently disappears from default search results.Each document carries a human-set body page range in its source metadata (
Introduction - before beginning of Annexes). This feature checks that every section falling inside that range uses a default-included type, and lets an admin verify/fix the classification.Screenshots
What it does
/documentsendpoint), with an indication of any prior validation result.Verdicts: pass (all in-range sections included), fail (an excluded type inside the body range), skipped (no range / no classified contents).
How it's built
Shared logic — extracted into
pipeline/validation/section_inclusion.pyso the backend service and the existing offline eval script (tests/evaluation/section_inclusion/) share one implementation (the script now imports it; no behaviour change).Backend (superuser-only, rate-limited) in
ui/backend/routes/toc_validator.py+services/toc_validator.py:POST /toc-validator/run— validate selected docs, persist, return resultsGET /toc-validator/results— stored results for the screen on loadFrontend — new admin tab:
TocValidatorManager+TocValidatorTable+TocValidationResultCell+useTocValidator, reusingMetadataModal/TocModaland the app's design tokens + shared badge/table/button classes.Persistence — note for reviewers
Results are stored per document under a
sys_toc_validationfield viamerge_doc_sys_fields(the same mechanismsys_toc_approveduses). No Alembic migration: the per-data-sourcedocs_<source>tables are created/altered dynamically at runtime by theensure_*helpers — they are not Alembic-managed except foruneg, so a migration would only (wrongly) touch that one source. This matches the existing per-doc-field precedent.A finding worth a decision
Across the WFP corpus the dominant failure is sections tagged
introductioninside the body range. That is systemic, not per-document mis-tagging: the body range starts at the introduction, andintroductionis not in the default-included set (and has no checkbox in Search settings). The genuinely actionable mis-tags areannexes/acronyms/bibliography/front_matterappearing mid-body (e.g. a report whose Findings/Recommendations chapters were labelledannexesbecause headings contained "(EQs 1-5, Annex 8)"). Whether to addintroductionto the defaults is a product decision this tool now makes visible.Testing
test_section_inclusion.py) and service (test_toc_validator_service.py); service round-tripped against real WFP data (persist + read-back).tocValidator.test.tsx(manager/table/result cell); full suite 518 passing,tscclean, eslint zero warnings.Docs:
docs/admin/toc-validator.md(added to the sidebar).🤖 Generated with Claude Code