Commit 99dc75d
Major improvements: checkpoint/resume, quality gate, citation fixes (#25)
* fix(citations): Wire citation style from CLI to generator, remove broken Chicago/MLA
- Citation style selection (APA/IEEE) now flows from CLI through to CitationDatabase
instead of being hardcoded to APA 7th
- Remove Chicago and MLA from CLI and type definitions (they silently fell back to APA)
- Unsupported styles now raise NotImplementedError instead of silent fallback
- Add citation_count field to Citation model for impact metrics
- Add GEMINI_API_KEY as alias for GOOGLE_API_KEY in config
- Rewrite concurrency_config with tier-adaptive logic (free/paid/custom)
- Add Serper.dev and Firecrawl integrations as preferred search/scrape backends
- Update model references to gemini-3-flash-preview
- Add citation style test suite (11 tests)
- Add citation styles technical roadmap
* docs: Add comprehensive 19-agent pipeline visualization
Documents all 6 phases, 13 active agents, 6 optional agents, data flow
between phases, citation research cascade, file locations, and word count
targets by academic level.
* feat: Add fact-check verification agent to QA pipeline
Introduces a web-grounded fact-checking step (QA 3/3) that extracts
verifiable claims from the draft, searches for evidence via Gemini
grounded search, and produces a report with find/replace corrections
for any contradicted claims. Parallel verification with ThreadPoolExecutor
for speed. Feature-flagged via ENABLE_FACTCHECK env var (default: true).
* chore: Remove hardcoded API keys, delete artifacts, add Phase 2.5 pipeline
- Delete 3 test scripts containing hardcoded Groq API key
- Remove hardcoded key fallback from groq_adapter.py (env-only)
- Delete pip artifact file (=2.0.0)
- Add output directory patterns to .gitignore
- Stage Phase 2.5 modular pipeline (phases/, token tracking, models)
- Add generation scripts, Groq adapter, and new tests
* feat: Sync engine utilities, add reference doc, LaTeX escaping, soffice detection, expanded citation support
- Add custom-reference.docx and create_reference_doc.py
- Add _escape_latex_special_chars() to pandoc engine
- Add macOS soffice fallback in LibreOffice engine
- Add GEMINI_API_KEY env var fallback in api_tier_detector
- Expand citation_compiler with legal citation types and NALT style
- Add clean_agent_output() with 3-pass artifact stripping
- Expand token_counter and token_tracker with per-phase tracking
- Add deep_research parallel search and source dedup
- Add zip_bundle_manager utility
- Add test_security and expanded test coverage
* Fix import errors: add phases package to setuptools include
Fixes:
- "cannot import name 'generate_draft' from 'draft_generator'"
- "no module named 'concurrency'"
The phases package was missing from setuptools.packages.find include
pattern, causing imports to fail when installed via pip.
Also adds tenacity to dependencies (was missing).
Closes reported issues.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add text_cleanup.py - deterministic cleanup utilities from V2
Pure functions with zero external dependencies:
- apply_full_cleanup(text) - 10-step cleanup pipeline
- ensure_authors_list(value) - fixes LLM author format issues
- detect_repetition(text) - thesis + phrase frequency warnings
- detect_advocacy_language(text) - overconfident tone warnings
Cleanup pipeline:
1. Filler transitions (Furthermore, Moreover, etc.)
2. Empty intensifiers (very, extremely, highly)
3. Synonym chains
4. Meta-commentary
5. Verbose phrases
6. Thesis restatements
7. Vocabulary diversification (rotates overused words)
8. Claim calibration (hedges overconfident language)
9. Duplicate References headings
10. Whitespace cleanup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Integrate text_cleanup into compile phase
Wire apply_full_cleanup() into the compile pipeline to apply:
- Vocabulary diversification (rotating overused words)
- Claim calibration (hedging overconfident language)
- Filler transition removal
- Intensifier stripping
- Verbose phrase compression
- Thesis restatement neutralization
Adds verbose output and tracker logging showing cleanup stats.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* migrate gemini runtime to google-genai
* fix output cleaning regressions and reference handling
* add quality gates and verified fixes log
* stabilize pytest harness for ticket and integration tests
* harden live factcheck tests for offline and restricted envs
* add push preflight runbook and guard script
* add changelog and maintainer commit hygiene guidance
* align cli and npm version requirements
* harden live scripts and run full tests in CI
* sync fixes documentation with current CI and test status
* add secret-gated live validation workflow
* fix live validation workflow secret gating
* stabilize live validation invocation paths
* stabilize audit model selection in live validation
* sync docs with verified live validation closure
* fix quality CI collection error in citation compiler
* add manual dispatch trigger for quality workflow
* feat: add Chicago and MLA citation styles, fix citation format bug
- Add Chicago (Author-Date) and MLA 9th Edition citation styles
- Fix citation summary bug: {cite_cite_001} -> {cite_001}
- Update CLI to include Chicago and MLA options
- Add _format_chicago_in_text, _format_chicago_reference
- Add _format_mla_in_text, _format_mla_reference
- Update CitationStyle type to include new styles
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test: add Chicago/MLA tests, remove obsolete NotImplementedError tests
- Add TestChicagoInTextCitations with single/two/multiple author tests
- Add TestMLAInTextCitations with single/two/multiple author tests
- Remove tests expecting Chicago/MLA to raise NotImplementedError
- Keep Harvard test for unsupported styles
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Major improvements: checkpoint/resume, quality gate, circular import fixes
Features added:
- Checkpoint/resume system: saves state after each phase, resume with --resume flag
- Quality gate: scores draft quality (0-100), skips QA if score >= 85
- Inter-phase validation: fail early if phase outputs are empty/invalid
Bug fixes:
- Fixed circular imports: moved slugify/get_language_name to utils/text_utils.py
- Citation bug {cite_cite_001} already fixed in previous commit
Code cleanup:
- Deleted 8 obsolete generate_thesis_*.py scripts (CLI handles all cases)
- Moved 3 dev scripts to engine/dev/ (tracked, llama4, gptoss)
Files:
- NEW: utils/checkpoint.py - checkpoint save/load/restore
- NEW: utils/quality_gate.py - quality scoring after compose
- NEW: ISSUES.md - issue tracker with all fixes documented
- MOD: draft_generator.py - validation, checkpoints, quality gate
- MOD: phases/compile.py, phases/citations.py - fixed imports
- MOD: utils/text_utils.py - added shared slugify/get_language_name
- MOD: opendraft/cli.py - added --resume flag
All 290 tests pass.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add tests for checkpoint and quality gate modules
- 17 tests for checkpoint save/load/restore
- 15 tests for quality gate scoring
- Tests found and fixed fixture issues
Total: 322 tests passing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix checkpoint bug: empty dict treated as None
Bug: _serialize_scout_result({}) returned None instead of {}
Fix: Changed `if not scout_result:` to `if scout_result is None:`
Added 4 more tests for Citation serialization roundtrip:
- test_serialize_citation_objects
- test_deserialize_citation_dicts
- test_citation_roundtrip
- test_empty_scout_result (caught the bug)
Total: 326 tests passing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add warning for topic mismatch on checkpoint resume
When user runs `opendraft "New Topic" --resume checkpoint.json`,
warn if the checkpoint has a different topic than CLI argument.
Checkpoint topic is used, not CLI topic.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add comprehensive edge case tests for checkpoint and quality gate
- Add 9 new checkpoint tests: corrupt JSON, missing fields, unicode,
overwrite behavior, resume workflow, full context roundtrip
- Add 8 new quality gate tests: borderline scores, citation formats,
unicode content, empty targets, max score bounds, academic levels
Total tests: 341 (up from 326)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add resume integration tests and quality gate calibration
Resume Integration Tests (16 tests):
- Real resume workflow: skip completed phases, continue from checkpoint
- Topic mismatch handling: warns but uses checkpoint topic
- Citation object serialization roundtrip preservation
- Various topic types: technical, humanities, German, Chinese, long, special chars
Quality Gate Calibration (15 tests):
- Research paper: 3000-5000 words, 10-15 citations
- Bachelor thesis: 8000-15000 words, 20-40 citations
- Master thesis: 15000-30000 words, 40-80 citations
- PhD dissertation: 50000-100000 words, 100+ citations
- Citation density: 1 per 500 words is good
- Section completeness and structure scoring
Total tests: 372 (up from 341)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add process-level interrupt, benchmark, and statistical validation tests
- test_process_interrupt.py: 7 tests for SIGKILL/SIGTERM checkpoint survival
- test_checkpoint_benchmarks.py: 14 tests for save/load/restore performance
- test_quality_statistical.py: 17 tests for scoring consistency and thresholds
Total: 410 tests passing (38 new)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add true E2E subprocess kill tests and real academic content validation
TRUE 10/10 tests:
1. test_e2e_subprocess_kill.py (13 tests):
- Spawns actual Python subprocesses with mock pipeline
- Sends real SIGKILL/SIGTERM signals mid-execution
- Verifies checkpoint survives process death
- Tests resume across process boundaries
- Multiple kill/resume cycles to completion
- Concurrent thread writes (race conditions)
- Edge cases: unicode, 2MB strings, JSON escaping, empty fields
- Flaky detection: 100-run determinism checks
2. test_quality_real_content.py (11 tests):
- Uses actual academic writing patterns (not synthetic)
- Real intro/lit review/methodology/results/discussion/conclusion
- Validates quality gate against realistic content
- Compares synthetic vs real content scoring
- Detects placeholders (TODO, INSERT, Lorem ipsum)
- Tests academic level scaling (paper → PhD)
Total: 434 tests passing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add LIVE Gemini API integration tests
Real API tests that verify:
- Checkpoint preserves actual LLM output (not mocked)
- Quality gate scores real AI-generated academic content
- Full mini-pipeline with real API calls can be interrupted and resumed
- Unicode and long outputs from real LLM work correctly
10 new tests using gemini-2.5-flash:
- test_api_connection
- test_api_returns_academic_content
- test_checkpoint_preserves_llm_output
- test_multiple_llm_outputs_checkpoint
- test_quality_gate_scores_real_content
- test_research_to_checkpoint
- test_resume_continues_from_checkpoint
- test_llm_unicode_output
- test_llm_long_output
- test_full_mini_pipeline_with_interrupt_simulation
Total: 444 tests (434 unit/integration + 10 live API)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Federico De Ponte <federicodeponte@Federicos-MacBook-Air-3.local>
Co-authored-by: Federico De Ponte <noreply@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>1 parent c754ecb commit 99dc75d
122 files changed
Lines changed: 18898 additions & 3317 deletions
File tree
- .github/workflows
- docs
- engine
- concurrency
- dev
- examples
- opendraft.egg-info
- opendraft
- phases
- prompts
- 03_compose
- 04_validate
- utils
- api_citations
- pdf_engines
- npm
- scripts
- tests
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
250 | 250 | | |
251 | 251 | | |
252 | 252 | | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
253 | 257 | | |
254 | 258 | | |
255 | 259 | | |
| |||
258 | 262 | | |
259 | 263 | | |
260 | 264 | | |
| 265 | + | |
261 | 266 | | |
262 | 267 | | |
263 | 268 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
0 commit comments