You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Improve large-guideline parsing and WHO extraction handling.
Add chunked parse/merge for large guidelines and harden query normalization so real WHO guideline runs produce much broader, more usable output instead of failing on LLM formatting and vocabulary mismatches.
Made-with: Cursor
Copy file name to clipboardExpand all lines: CHANGES_LOG.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,14 @@
2
2
3
3
## 2026-03-25
4
4
5
+
-**Add**: automatic chunked parsing for large guidelines in `parse.py`. Herald now narrows to recommendation-heavy sections, splits by subsection headings, parses chunks independently, and merges metadata/fields/synonyms/decisions with deterministic ID conflict handling.
6
+
-**Fix**: chunk parsing now prefers the longest real recommendations chapter instead of the table-of-contents hit, and sanitizes common LLM schema-shape errors before validation (for example bool field value arrays and `null` recommendation strings). Rationale: the first real WHO chunked runs exposed TOC mis-detection and predictable malformed field shapes.
7
+
-**Fix**: query normalization now handles canonical enum values with underscores, pluralized guideline vocab (`adult` ↔ `adults`), null enum vocab lists, and composite values like `children_and_adolescents`. Rationale: the WHO chunked parse exposed valid recommendations that were being missed at query time due to vocab-shape mismatches.
8
+
-**Fix**: `parse.py` now preserves `field_synonyms`, extracts JSON from common LLM wrapper text, and raises the default LLM output budget to `20000` tokens. Rationale: the real WHO mhGAP parse exposed dropped synonyms, prose-before-JSON responses, and mid-JSON truncation.
9
+
-**Fix**: `query.py` now handles parsed `patient_fields` with `values: null` / `known_values: null`, and `any_match` now supports scalar membership against expected enum lists. Rationale: the WHO parse produced these shapes and they broke or suppressed valid queries.
10
+
-**Fix**: CLI commands now surface expected runtime/data failures as clean `Error: ...` messages instead of raw Python tracebacks. Added `tests/test_cli.py` to lock in missing-API-key and invalid-JSON behavior.
11
+
-**Fix**: `convert.py` now strips form-feed page-break characters from `markitdown` output before whitespace normalization. This reduces real-PDF ingestion noise from the WHO mhGAP guideline. Also corrected stale install hints from `guideline-as-code[...]` to `herald-cpg[...]`.
12
+
-**Add**: `workflow_state.md` — bounded Planner packet for a repo-wide quality pass using the WHO mhGAP guideline PDF; keeps execution and judging disciplined.
5
13
-**Fix**: `herald --version` crashed with `RuntimeError: 'herald_cli' is not installed`. Root cause: `@click.version_option()` inferred package name from module (`herald_cli`) instead of the installed package (`herald-cpg`). Fixed by passing `package_name="herald-cpg"`.
6
14
7
15
-**Add**: `tests/test_diff.py` — 21 tests covering `diff_guidelines()` (identical, added, removed, modified nodes/metadata/fields, complex mixed diffs) and `format_markdown()` (all output sections). `diff.py` now at 99% coverage.
-`MultiQueryEngine`: Queries multiple guidelines simultaneously with conflict detection.
42
43
-`parse_patient_description()`: NLP parser that converts natural language ("34F ADHD, comorbid anxiety") into structured patient dicts. Handles age/sex extraction, medical abbreviations, negation detection, vital signs, medication history, and guideline-driven dynamic field extraction via synonyms.
43
44
-`parse_csv_patients()`: Batch processing from CSV.
45
+
- Query extraction now tolerates `values: null` / `known_values: null` in parsed `patient_fields`.
46
+
- Condition matching now treats `any_match` with a scalar patient value plus a list of expected enum values as membership, which makes the engine more resilient to imperfect LLM condition encoding.
47
+
- Enum extraction now matches canonical values with underscores normalized to spaces (for example `bipolar_disorder` ↔ `bipolar disorder`), aligns derived enum values to guideline vocab (`adult` → `adults`), and treats composite values like `children_and_adolescents` as matching child/adolescent patients.
48
+
49
+
### `cli.py` — User-Facing Command Layer
50
+
51
+
- Wraps expected runtime/data failures (`RuntimeError`, `ValueError`, `OSError`, JSON decode errors) as `click.ClickException`, so the CLI prints clean `Error: ...` messages instead of Python tracebacks.
52
+
- Manual CLI coverage now includes `--help`, `--version`, `convert`, `parse` missing-key failure path, `query`, `validate`, `diff`, `export`, batch query, audit logging, and multi-guideline query.
- Supports Anthropic (claude-sonnet-4-20250514 default) and OpenAI (gpt-4o default).
49
58
-`_validate_references()`: Ensures all branch `next_decision` IDs point to valid nodes.
59
+
- Provider dependency/install error strings now reference the correct package extras: `herald-cpg[anthropic]` and `herald-cpg[openai]`.
60
+
- Parsed trees now preserve `field_synonyms`, matching the documented schema and what `query.py` expects.
61
+
- The parser now strips common LLM wrapper text and extracts fenced/embedded JSON payloads before `json.loads()`.
62
+
- Default output budget for LLM parse calls is now `20000` tokens so large real-world guideline parses are less likely to truncate mid-JSON.
63
+
- Large guidelines now automatically switch to chunked parsing:
64
+
- tries to narrow to a recommendations chapter when one is clearly present
65
+
- splits by numbered subsection headings (fallback: markdown headings, then paragraph-size chunks)
66
+
- sends each chunk with shared top-of-document metadata context
67
+
- merges guideline metadata, patient fields, synonyms, and decisions deterministically
68
+
- renames conflicting decision IDs safely and validates references after merge
69
+
- Before schema validation, parse output is sanitized to clean up common LLM shape mistakes seen in real runs (for example `bool` fields incorrectly carrying `[true, false]` value arrays, or nullable recommendation string fields arriving as `null`).
70
+
71
+
### `convert.py` — PDF Conversion
72
+
73
+
- Uses Microsoft `markitdown`, then post-processes output with `_normalize_markdown()`.
74
+
- Normalization now strips embedded form-feed/page-break characters before collapsing whitespace so real PDF conversions do not leak `\f` artifacts into downstream parse input.
50
75
51
76
### `export.py` — FHIR Export
52
77
@@ -64,10 +89,15 @@ examples/
64
89
```bash
65
90
pip install -e ".[dev]"# Install with dev deps (pytest, ruff, pytest-cov)
66
91
ruff check src/ tests/ # Lint
67
-
pytest tests/ -v --tb=short # Run tests (98 tests)
92
+
pytest tests/ -v --tb=short # Run tests (101 tests)
68
93
pytest tests/ --cov=herald_cli # Coverage report
69
94
```
70
95
96
+
## Workflow Discipline
97
+
98
+
-`workflow_state.md` tracks the active Planner-owned task packet, success criteria, and verification steps for non-trivial work.
99
+
- Real-system validation matters for this project because the highest-risk paths are CLI execution, PDF conversion fidelity, and LLM-backed parsing behavior against real guideline documents.
100
+
71
101
## Schema
72
102
73
103
Decision trees follow Herald Schema v0.1 (see `SCHEMA.md`). Every recommendation traces back to `source_section`, `source_page`, and `source_text` for auditability.
@@ -83,4 +113,9 @@ Decision trees follow Herald Schema v0.1 (see `SCHEMA.md`). Every recommendation
83
113
## Known Issues
84
114
85
115
- Repo state: `Desktop/herald` has source files deleted from HEAD. Full project only in Downloads copies.
86
-
- Coverage: `cli.py` at 0% (no CLI integration tests). `query.py` at 47% — many extractors and batch/multi-engine paths uncovered.
116
+
-`query.py` coverage is still relatively low for the full NLP extraction surface and multi-guideline behavior.
117
+
- Real WHO PDF conversion still includes repeated running headers/page numbers and some OCR-style spacing artifacts such as `E xecutive summar y`, even though form-feed control characters are now stripped.
118
+
- Multi-guideline queries return duplicate recommendations if equivalent guidelines are loaded more than once; no deduplication layer exists yet.
119
+
- After chunked parsing, the WHO mhGAP parse improved from 14 to 19 decision nodes and became materially more queryable (anxiety, ADHD, bipolar mania, and canonical-phrase depression queries returned results), but fidelity remains low at 50% with partial-only matches. The remaining issue is extraction quality, not parser/runtime stability.
120
+
- Real-world large-guideline extraction still depends heavily on the model producing good local condition vocab. For example, some WHO diagnoses/age buckets were emitted in awkward canonical forms (`moderate_to_severe_depression`, `children_and_adolescents`) that required extra query normalization.
121
+
- The fully chunked WHO rerun currently requires more than five minutes for the complete 23-chunk pass. Under the current workflow rules, that means it must be treated as a long-running operation and discussed before retrying.
0 commit comments