docpluck 2.4.99__tar.gz → 2.4.102__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/_project/lessons.md +37 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/LEARNINGS.md +26 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/SKILL.md +1 -1
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-qa/SKILL.md +1 -1
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-qa/references/check-13-escicheck-production.md +1 -1
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-qa/references/check-5-escicheck-library.md +1 -1
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-qa/references/check-6-escicheck-local-webapp.md +1 -1
- {docpluck-2.4.99 → docpluck-2.4.102}/CHANGELOG.md +40 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/PKG-INFO +1 -1
- {docpluck-2.4.99 → docpluck-2.4.102}/TODO.md +9 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/__init__.py +1 -1
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/extract_structured.py +704 -18
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/normalize.py +158 -8
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/render.py +447 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/camelot_extract.py +221 -42
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/cell_cleaning.py +83 -0
- docpluck-2.4.102/docpluck/tables/detect.py +662 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/flatten.py +31 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/whitespace.py +123 -6
- docpluck-2.4.102/docs/FINDINGS_2026-07-01_chandrashekar_sidebyside_deinterleave.md +149 -0
- docpluck-2.4.102/docs/FINDINGS_2026-07-01_efendic_t2_and_collabra_pairing.md +184 -0
- docpluck-2.4.102/docs/FINDINGS_2026-07-01_parallel_session_verification.md +161 -0
- docpluck-2.4.102/docs/FINDINGS_2026-07-02_concurrent_session_reconciliation.md +67 -0
- docpluck-2.4.102/docs/TRIAGE_2026-07-03_head_v2.4.101_assessment.md +122 -0
- docpluck-2.4.102/docs/superpowers/specs/table_extraction_rearchitecture_2026-06-28.md +135 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/pyproject.toml +1 -1
- docpluck-2.4.102/tests/test_dropped_minus_ci_upper_recovery_real_pdf.py +233 -0
- docpluck-2.4.102/tests/test_major_section_heading_promotion.py +479 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_minus_sign_recovery_real_pdf.py +110 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_tables_flatten_blank_header_recovery.py +56 -21
- docpluck-2.4.99/docpluck/tables/detect.py +0 -373
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/_project/canary.json +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-cleanup/SKILL.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-deploy/SKILL.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/ai-full-doc-verify.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/cycle-report-template.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/local-verification.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/rationalizations.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/real-library-real-pdf.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/release-flow.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/self-improvement.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/subagent-parallelization.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-iterate/references/three-tier-parity.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-qa/references/benchmark-mode.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-qa/references/check-11-hard-rules.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-qa/references/check-7-batch-smoke.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.claude/skills/docpluck-review/SKILL.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.github/workflows/bump-app-pin.yml +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.github/workflows/publish.yml +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.github/workflows/test.yml +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/.gitignore +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/CLAUDE.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/CUSTOMER_UPDATE_2026-06-19_tables_sections_api.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/HANDOFF_SECTIONS_APP_INTEGRATION.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/LESSONS.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/LICENSE +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/README.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REPLY_FROM_DOCPLUCK_v1.4.5.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REPLY_FROM_DOCPLUCK_v1.5.0.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REPLY_FROM_DOCPLUCK_v2.4.93.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REPLY_FROM_DOCPLUCK_v2.4.94.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REPLY_FROM_DOCPLUCK_v2.4.95.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REQUEST_08_CHUNKING_ENDPOINT.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REQUEST_09_REFERENCE_LIST_NORMALIZATION.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REQUEST_10_TABLE_FLATTEN_HTTP_EXPOSURE.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REQUEST_10_TIER2_ORPHANED_LABEL_ROW_RECOVERY.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/REQUEST_11_FLATTEN_FIELDS_NONCLINICAL_TABLES.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/__main__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/batch.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/cli.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/extract.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/extract_columns.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/extract_docx.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/extract_html.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/extract_layout.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/figures/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/figures/detect.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/quality.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/annotators/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/annotators/docx.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/annotators/html.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/annotators/pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/annotators/text.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/blocks.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/boundaries.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/core.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/taxonomy.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/sections/types.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/bbox_utils.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/captions.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/cluster.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/confidence.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/tables/render.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/telemetry.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docpluck/version.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/BENCHMARKS.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/BENCHMARKS_liteparse_2026-06.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/DESIGN.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-07_sections_strict_iteration.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-09_session_state_and_followups.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-09_unified_extraction_brainstorm.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-10_table_rendering_iteration.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-10_table_rendering_iteration_2.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-10_table_rendering_iteration_3.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-10_table_rendering_iteration_4.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-10_table_rendering_iteration_5.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-10_table_rendering_iteration_6.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-10_table_rendering_iteration_7.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-11_PROMOTE_SPIKE_TO_LIBRARY.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-11_table_rendering_iteration_8.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-11_visual_review_findings.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-12_phase2_101pdf_corpus.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-12_remaining_ui_and_chrome_verification.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-12_visual_verify_results.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-13_apa_50_expansion.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-13_apa_50_expansion_iter_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-13_apa_50_expansion_iter_2.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-13_iterate_skill_first_use.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-13_iterative_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-13_iterative_library_improvement.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-13_table_extraction_next_iteration.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-14_continue_iterations_v2_4_30_to_15n.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-14_full_corpus_iteration_v2_4_30.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-14_iterate_6_cycles_complete.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-14_iterate_9_cycle_run.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-14_iterate_resume_4_cycles.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-14_iterate_v2_4_31_cycle_15n.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-14_phase_5d_gold_audit_v2_4_29.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-15_autonomous_apa_first_10h.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-15_iterate_apa_run_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-16_ai-gold-instructions.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-16_iterate_apa_run_2.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-16_iterate_apa_run_3.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-16_iterate_run_4_final.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-16_iterate_run_4_fix_and_continue.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-16_iterate_run_5.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-16_iterate_run_6.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-17_iterate_run_7.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-17_iterate_run_8.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-17_iterate_run_9.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-18_iterate_run_9_cont.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-18_iterate_run_9_cont2.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-20_iterate_run_9_cont3.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-22_iterate_run_9_session4_final.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-22_iterate_run_9_session5_close.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-25_haiku-orchestration-pretest.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-05-25_pretest-followups.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-08_iterate_splice-wordintegrity-runningheader.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-08_untested_sweep_v2.4.81.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-13_sciencearena_grobid_liteparse.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-15_docpluck-iterate-resume.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-15_rc1-step2-continue.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-16_docpluck-iterate-resume.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-17_iterate_resume-cycle1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-17_iterate_v2491_shipped.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-18_iterate_v2492_affiliation_caption-revert.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-20_request11_flatten_nonclinical_tables.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/HANDOFF_2026-06-25_iterate_branch-reconcile_rc1-banded-flip-rejected.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/ITERATION_VERIFICATION_LESSONS.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/LIBRARY_APP_SYNC.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/NORMALIZATION.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/README.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/TRIAGE_2026-05-10_corpus_assessment.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/TRIAGE_2026-05-14_phase_5d_gold_audit.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/TRIAGE_2026-06-08_untested_corpus_sweep.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/TRIAGE_2026-06-15_head_v2.4.88_assessment.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/TRIAGE_2026-06-21_head_v2.4.95_assessment.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/TRIAGE_2026-06-25_escicheck_handoff_defects.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-22-b1-next-iteration.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-22-b2-remaining-halluc-head.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-22-b3-b7-structural-defects.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-22-residual-after-locally-doable-pass.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-23-bundled-residual-cycle-CLOSED.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-23-residual-after-iterate-spine-cycles-1-3.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-25-canary-audit-architecture-and-cluster-A-B-C-landed.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-25-wrapup-r4-cycle.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-26-run-11-cluster-A-ter-and-C-bis-landed.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-05-26-text-extraction-defects-from-citationguard-audit.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-06-07-text-extraction-defects-from-citationguard-iterate.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-06-07-v2.4.78-landed-canary-iterate.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-06-07-v2.4.79-findings-1-2-cleared.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-06-20_docpluck-skill-file-edits-from-app-cron-fix.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-06-21-rc-t-table-region-implementation.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/handoffs/2026-06-22-dp2-dp5-flatten-fixes-commit.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/2026-05-06-section-identification.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/2026-05-06-table-extraction.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/2026-05-07-sections-strict-iteration-progress.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/2026-05-08-unified-extraction-phase-0-splice-spike.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/2026-05-23-haiku-orchestration-pretest.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/sections-deferred-items.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/sections-issues-backlog.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/2026-05-07_spot-01_apa.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/2026-05-07_spot-02_pattern-A-shipped.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/2026-05-08_spot-final_all-styles.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/COMPARISON.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-a/korbmacher_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-a/option-a.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-a/ziano_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-b/korbmacher_notes_raw.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-b/korbmacher_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-b/notes.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-b/option-b.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-b/ziano_notes_raw.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-b/ziano_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-c/korbmacher_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-c/notes.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-c/option-c.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-c/sample-pdftotext-bbox.html +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-c/ziano_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-d/korbmacher_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-d/notes.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-d/option-d.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-d/ziano_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-e/korbmacher_2022_kruger_bbox.html +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-e/korbmacher_bbox.html +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-e/korbmacher_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-e/option-e.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-e/sample-bbox.html +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-e/ziano_2021_joep_bbox.html +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-e/ziano_bbox.html +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/experiments/option-e/ziano_table1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/html-fallback-demo.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/chandrashekar_2023_mp.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/chandrashekar_2023_mp.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/efendic_2022_affect.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/efendic_2022_affect.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/ieee_access_2.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/ieee_access_2.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/ip_feldman_2025_pspb.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/ip_feldman_2025_pspb.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/korbmacher_2022_kruger.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/korbmacher_2022_kruger.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/nat_comms_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/nat_comms_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/ziano_2021_joep.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs/ziano_2021_joep.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/am_sociol_rev_3.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/am_sociol_rev_3.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/amc_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/amc_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/amj_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/amj_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/amle_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/amle_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ar_apa_j_jesp_2009_12_010.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ar_apa_j_jesp_2009_12_010.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ar_royal_society_rsos_140066.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ar_royal_society_rsos_140066.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ar_royal_society_rsos_140072.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ar_royal_society_rsos_140072.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/bjps_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/bjps_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/chan_feldman_2025_cogemo.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/chan_feldman_2025_cogemo.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/chen_2021_jesp.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/chen_2021_jesp.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/demography_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/demography_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ieee_access_3.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ieee_access_3.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ieee_access_4.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/ieee_access_4.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/jama_open_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/jama_open_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/jama_open_2.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/jama_open_2.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/jmf_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/jmf_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/nat_comms_2.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/nat_comms_2.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/sci_rep_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/sci_rep_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/social_forces_1.err +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/outputs-new/social_forces_1.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/papers.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/report.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/splice_spike.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/plans/spot-checks/splice-spike/test_splice_spike.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/specs/2026-04-27-request-09-reference-normalization-design.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/specs/2026-05-06-section-identification-design.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/specs/2026-05-06-table-extraction-design.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/specs/2026-05-08-unified-extraction-design.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/specs/2026-05-23-haiku-orchestration-pretest-design.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/specs/2026-06-07-ip_feldman-B4-R4-column-interleave-diagnosis.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/specs/2026-06-08-rc1-region-aware-column-architecture.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/docs/superpowers/specs/2026-06-21-rc-t-table-region-prose-contamination.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/check_app_pin_sync.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/check_docs_consistency.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/README.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/VERIFIER_PROMPT.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/baseline_matrix.json +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/checks.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/corpus.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/corpus_manifest.json +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/extract.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/gold_keys.json +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/harness/inspect.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/lint_rendered_corpus.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/pretest_capture_tokens.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/verify_corpus.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/scripts/verify_corpus_full.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/conftest.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/fixtures/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/fixtures/sections/__init__.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/fixtures/sections/builders.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/fixtures/structured/.gitkeep +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/fixtures/structured/MANIFEST.json +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/fixtures/structured/README.md +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/golden/sections/apa_multi_study_pdf.json +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/golden/sections/apa_single_study_pdf.json +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/golden/sections/html_real_headings.json +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/amj_lattice.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/apa_chan_feldman_lineless.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/apa_chen_jesp_lineless.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/apa_efendic_affect.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/apa_ip_feldman_pspb.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/bmc_lattice.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/ieee_figure_heavy.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/ieee_lattice.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/jama_lattice.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/nat_comms_figure_only.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/nature_minimal_rule.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/snapshots/scirep_minimal_rule.txt +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_a3c_leading_zero_decimal_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_a4_ci_period_to_comma.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_affiliation_heading_promote_guard_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_all_caps_section_promote_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_bbox_utils.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_benchmark_docx_html.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_cambridge_footer_strip_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_camelot_lattice_augment.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_camelot_temp_cleanup.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_canary_provenance.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_caption_only_table_heading_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_caption_regex.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_chart_data_trim_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_check_app_pin_sync.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_cid_minus_recovery_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_cli_sections.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_cli_structured.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_confidence.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_corpus_smoke.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_d5_normalization_audit.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_dropped_minus_layout_recovery_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_edge_cases.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_elsevier_footer_strip_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_equation_page_header_strip_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_extract_columns.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_extract_docx.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_extract_filter_sugar.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_extract_html.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_extract_layout.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_extract_pdf_structured.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_extraction.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_f0_table_region_aware.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_fffd_comparison_recovery_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_figure_caption_trim_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_figure_detect.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_fixtures_manifest.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_hallucinated_heading_continuation_guard.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_harness_text_loss_reflow.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_harvard_refs_pagebreak_stitch.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_jama_open_cluster_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_lattice_cluster.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_letterspaced_label_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_ligature_decomposition_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_lt_operator_recovery_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_mathitalic_greek_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_metaesci_followups.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalization.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalize_a3_r2_body_integer_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalize_f0_footnote_strip.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalize_idempotent_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalize_layout_param.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalize_metadata_leak_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalize_report_layout_fields.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalize_soft_hyphen_dehyphenation.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_normalize_v18_strips.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_numbered_heading_promotion_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_numbered_section_promotion_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_o5_reference_inversion_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_orphan_multilevel_number_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_orphan_section_number_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_p0r_recurring_running_header_strip.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_preserve_math_glyphs_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_pretest_capture_tokens.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_pua_glyph_recovery_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_quality.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_r1_whitespace_cells_wiring_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_r4_column_correction_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_rc1_banded_column_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_rc1_general_column_correction_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_rc_t_degenerate_table_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_rc_t_layer2_raw_text_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_render.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_render_frontmatter_masthead.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_render_html.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_render_subsection_chain_promotion.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_request_09_reference_normalization.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_residual_2026_05_23_bundled.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_roman_numeral_section_promote_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_section_row_label_no_merge_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_boundaries.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_boundary_truncation.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_core_partition.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_docx_annotator.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_extract_text.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_footnote_section.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_golden.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_html_annotator.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_pdf_annotator.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_public_api.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_real_corpus.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_taxonomy.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_text_annotator.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_types.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_unit_corpus.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_v161_coalesce.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_v161_subheadings.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_v161_taxonomy.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_v161_text_annotator.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_sections_version.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_single_column_subsection_promote_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_smoke_fixtures.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_structured_result_type.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_structured_types.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_structured_version.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_table_caption_cell_region_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_table_detect.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_tables_cell_cleaning.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_tables_flatten.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_tables_superheader_alignment_real_pdf.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_text_mode.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_v23_1_fixes.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_v23_bug_fixes.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_v23_post_corpus.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_v23_post_corpus_v2.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_v2_backwards_compat.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_v2_top_level_exports.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_whitespace_char_fallback.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tests/test_whitespace_cluster.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tools/canary_provenance.py +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tools/fix_python_env.ps1 +0 -0
- {docpluck-2.4.99 → docpluck-2.4.102}/tools/render_for_audit.py +0 -0
|
@@ -653,3 +653,40 @@ Rotation picks `pool[(N mod L) : (N mod L) + rotation_size]` wrapping. Over `cei
|
|
|
653
653
|
## 2026-06-25 — Word-multiset preservation is BLIND to reading-order regressions; AI-verify is mandatory before any reorder flip
|
|
654
654
|
|
|
655
655
|
The RC-1 banded column-correction flag passed a full-corpus word-preservation scan (26/26 baseline papers, 0 multiset violations) — looked safe to flip default-ON. The 8-canary AI-verify then found **3 ON_REGRESSION** the scan was structurally blind to: running-header furniture injected into prose, Abstract/Intro section order inverted, prose fragmented on a *single-column* paper (false-positive gutter). A pure reorder/furniture-injection preserves the word multiset exactly. **Never flip a reading-order-affecting default on word-preservation (or char-ratio / Jaccard) evidence alone — those gates cannot see "right words, wrong order / wrong place." AI-verify against the gold is required, and the bar is zero ON_REGRESSION across the full canary set.** Re-validates the project ground-truth hard rule.
|
|
656
|
+
|
|
657
|
+
## 2026-07-02 · docpluckapp (frontend + service, NOT the library) · "Unhandled error in /api/extract" = heavy extraction outran the transport, escaping as an unhandled throw
|
|
658
|
+
|
|
659
|
+
**What (fix).** Daily digest showed 2 distinct fingerprints / 6 total, all `POST /api/extract?normalize=academic&quality=true&structured=true§ions=true` in one ~47-min window. Ground truth from prod `system_logs.context.errorStack` (queried read-only via the Neon `DATABASE_URL` in `PDFextractor/frontend/.env.local`): `TimeoutError: The operation was aborted due to timeout` ×3 and `SocketError: other side closed` (undici `onHttpSocketEnd`) ×3 — two faces of ONE slow request. Root cause was two-part: (1) **the FastAPI service blocked its own event loop** — `/extract` `/sections` `/render` `/tables` `/analyze` are `async def` but called the synchronous CPU-bound docpluck entrypoints (`extract_pdf`, `extract_pdf_structured` [Camelot], `extract_sections`, `render_pdf_to_markdown`) directly on the loop, so a big structured+sections paper held the loop tens of seconds, starving Railway's healthcheck/keep-alive → Railway edge dropped the socket; (2) **the Next route didn't guard the response-body read** — `fetch()` resolves on headers, so `await serviceResponse.json()` (the body read) was OUTSIDE the try/catch that wrapped `fetch()`; a mid-stream abort/close threw there and escaped to Next's `onRequestError`. Fixes (all general, not paper-specific): service `_offload()` (thin `starlette.concurrency.run_in_threadpool` wrapper) on all 20 heavy call sites; route `classifyTransportError()` (TimeoutError/AbortError→504, else 502) wrapping BOTH the fetch-init catch and the body read, plus a malformed-2xx-body→502 guard and `export const maxDuration = 150`; Dockerfile `uvicorn --timeout-keep-alive 75`; and — surfaced by /docpluck-review rule 19 — the handler was NOT wrapped in `withRouteErrorLogging` (pre-existing), now `export const POST = withRouteErrorLogging("api/extract", handleExtract)`. Regression test `frontend/src/app/api/extract/transport-error.test.ts` (pure classifier extracted to `transport-error.ts` so it imports no `next/server` and runs under `node --test`) asserts the two exact incident signatures map to 504/502.
|
|
660
|
+
|
|
661
|
+
**How to detect / avoid next time.** (1) **Never call a synchronous CPU-bound library from inside an `async def` FastAPI handler** — offload to the threadpool, or one heavy request starves healthchecks and serializes all traffic. (2) **`fetch()` resolves on headers; the body read is a SEPARATE failure surface** — guard `await res.json()`/`.text()`, not just the `fetch()` call. (3) **Pin `maxDuration` above any in-handler fetch timeout** so your own clean error fires before the platform's opaque 504. (4) A repo-wide pre-existing gap can hide a whole error class: the service test suite could not even run locally (async httpx fixture needed `anyio`+`httpx`, neither declared/installed; local FastAPI 0.137.2 was missing `annotated-doc` — `pip check` flags it). Added `service/requirements-dev.txt` and installed the missing dep; full suite now runs (156 passed / 2 skipped). Companion to the 2026-06-20 daily-digest entry (same `system_logs` ground-truth technique). App-only change — no library version bump, deploys via docpluckapp `master` push → Vercel + Railway.
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## 2026-07-03 · A DISABLE_CAMELOT glyph-recovery test does NOT prove the production Camelot HTML-table path
|
|
666
|
+
|
|
667
|
+
**What.** `recover_minus_via_ci_pairing` (W0d) recovers a `2`-for-U+2212 minus on a
|
|
668
|
+
bracket-less point estimate by pairing it with the CI in the SAME record. It fired
|
|
669
|
+
for efendic in the `DOCPLUCK_DISABLE_CAMELOT=1` unstructured-table channel (CI on the
|
|
670
|
+
same text line) but **silently missed every negative B-coefficient in the Camelot
|
|
671
|
+
HTML-table channel** — the production default — because Camelot emits each `<td>` on
|
|
672
|
+
its own line, so the SE cell between the B cell and the CI cell pushes the char-gap
|
|
673
|
+
(37) past the 30-char bare-bracket proximity cap. The existing regression test passed
|
|
674
|
+
only because it set `DISABLE_CAMELOT=1`. Result: 27 corrupt cells (`20.09` for `−0.09`)
|
|
675
|
+
shipped in production for the whole v2.4.x series while the test stayed green.
|
|
676
|
+
|
|
677
|
+
**How to detect.** For ANY glyph/text recovery that can reach a table cell, render the
|
|
678
|
+
affected paper WITH Camelot ON (the plain `render_pdf_to_markdown`, no env) and grep the
|
|
679
|
+
corruption signature in `<td>` cells — do NOT trust a `DISABLE_CAMELOT` test. Each glyph
|
|
680
|
+
fix must be verified in all three channels (body normalize, Camelot `cell_cleaning`, and
|
|
681
|
+
the final `render_pdf_to_markdown` post-process) — memory `glyph-fixes-need-all-three-text-channels`.
|
|
682
|
+
|
|
683
|
+
**How to fix (general).** In an HTML table row, columns pair by geometry, not prose
|
|
684
|
+
distance. Relax a bare bracket's proximity to the labeled-bracket rule when the record
|
|
685
|
+
is a `<tr>` (`"<td" in record`), keeping `_INDEPENDENT_STAT_BETWEEN_RE` as the guard so
|
|
686
|
+
it still can't pair back across a different estimate's column. Prose lines keep the
|
|
687
|
+
strict gap. Keyed on `<tr>` structure, not paper identity → general.
|
|
688
|
+
|
|
689
|
+
**Bonus (leave-nothing-behind).** Widening a recovery is the moment to run an adversarial
|
|
690
|
+
"what could this now WRONGLY recover" battery — it caught a pre-existing bare-bracket FP
|
|
691
|
+
(prose `SD = 2.01 … d = 0.09 [-1.86,0.04]` flipping `2.01`) that the happy-path test's
|
|
692
|
+
slightly-different string had never exercised.
|
|
@@ -1368,3 +1368,29 @@ aren't skipped.
|
|
|
1368
1368
|
|
|
1369
1369
|
### Verification
|
|
1370
1370
|
- `tests/test_whitespace_char_fallback.py` (5 cases incl. real-PDF ip_feldman T10 = all 7 gold rows recovered; synthetic tight-kerned recovery; word-space reinsertion; delegation wiring; single-column-no-fabrication guard). 15/15 pass on the whitespace/char/caption-table suite; 0 failures across the broad table/render run; word path proven byte-identical (restored verbatim).
|
|
1371
|
+
|
|
1372
|
+
---
|
|
1373
|
+
|
|
1374
|
+
## Run: 2026-07-03 · cycle 1 · @ v2.4.101 → v2.4.102 · verdict FAIL (A1 shipped; corpus still FAIL)
|
|
1375
|
+
|
|
1376
|
+
**Goal:** user `/docpluck-iterate 5 hours`. TRIAGE (2026-06-25) was stale (predated v2.4.99/100/101) → cycle 1 = mandatory broad-read + full canary baseline reproduction at HEAD.
|
|
1377
|
+
|
|
1378
|
+
### Headline finding — the canary corpus is 5/5 FAIL at v2.4.101 (reproduce-before-trust paid off)
|
|
1379
|
+
Rendered the 3 fixed + 2 rotating canaries at HEAD and dispatched 5 parallel Sonnet AI-gold verifiers (Claude Max). **All 5 FAIL.** The stale TRIAGE's DP-* items had mostly shipped, but the underlying clusters are wide open. New fresh TRIAGE written (`docs/TRIAGE_2026-07-03_head_v2.4.101_assessment.md`) with 4 root-cause clusters: A (GLYPH sign corruption), B (table data-loss/RC-T, architectural), C (heading split/demotion), D (figure-axis-label leak). Plus broad-read discovery of E1-E4 (title-glyph `T` injection, keyword→heading promotion, RSOS citation-masthead-before-title, Collabra body-sentence→heading).
|
|
1380
|
+
|
|
1381
|
+
### What shipped (clean, verified) — A1: 2-for-minus reaches the Camelot HTML-table channel (v2.4.102)
|
|
1382
|
+
- **The bug:** efendic rendered **27 corrupt `2X.XX` B-column cells** (`20.09` for `−0.09`) across regression Tables 2-5 — a silently-WRONG number, the worst meta-science defect class. Root cause: `recover_minus_via_ci_pairing` (W0d) pairs a bracket-less estimate with the CI in its **same record** and recovers the minus by containment; but Camelot emits each `<td>` on its own line, so the **SE cell sits between the B cell and the CI cell**, pushing the char-gap to 37 (past the 30-char cap W0d applies to *bare* brackets). The recovery fired in the DISABLE_CAMELOT unstructured-table channel but **silently missed the Camelot HTML-table channel — the production default.**
|
|
1383
|
+
- **The blind spot (the key lesson):** the existing `test_efendic_table_point_estimates_recovered_via_ci` PASSED at HEAD — but it runs with `DOCPLUCK_DISABLE_CAMELOT=1`. So a green test masked a production-path defect. This is `glyph-fixes-need-all-three-text-channels` again: a recovery landed in one channel; the Camelot table channel was uncovered. **A DISABLE_CAMELOT test does NOT prove the production Camelot HTML-table path is correct.** Added a Camelot-ON real-PDF test that renders through the production default.
|
|
1384
|
+
- **The fix (general, structural):** inside an HTML `<tr>` columns pair by table geometry, not prose adjacency — a bare bracket now uses the relaxed (labeled) proximity, still guarded by `_INDEPENDENT_STAT_BETWEEN_RE`. Prose lines (no `<td>`) keep the strict 30-char cap. Keyed on `<td>`/`<th>` presence, not paper identity → generalizes to any regression-table with the same signature. 27→0 corrupt cells; genuine `2.56` (Direction row, `∈[2.42,2.69]`) correctly preserved by the containment invariant; idempotent.
|
|
1385
|
+
- **Leave-nothing-behind bonus:** while adversarially battery-testing, found a PRE-EXISTING bare-bracket FP — the tight-spaced majumder variant `M=5.37, SD=2.01, t(1827)=1.83, d=0.09 [-1.86,0.04]` is only 25 chars gap so the cap alone let `2.01` flip to `-.01`, but the CI is `d`'s. Fixed by running the independent-stat guard for EVERY bracket kind (not just labeled). Confirmed pre-existing at HEAD (git show comparison), not introduced by my change.
|
|
1386
|
+
|
|
1387
|
+
### Verification (ground truth = AI-gold via article-finder, never pdftotext)
|
|
1388
|
+
efendic Camelot-ON render 27→0; independent Sonnet AI-gold re-verify: A1 resolved, B-column exact vs gold, **0 new regressions**. Full minus suite 22 pass (6 new); adversarial over-recovery battery all pass; broad normalize/render/sections/heading **557 pass**; flatten 39; RC-T degenerate-table (Camelot) 8; deterministic DISABLE_CAMELOT body-text diff of 8 corpus papers = **0 changed** (surgical). iterate-gate `--cycle 1` = FAIL on I3 only (the honest canary FAILs) — all other I-rules (I1/I2/I5/I8/I10/I11/I12) pass.
|
|
1389
|
+
|
|
1390
|
+
### Honest standing verdict: FAIL (rule 0e-bis)
|
|
1391
|
+
A1 is one root-cause class shipped. efendic still FAILs (A2 `×`-for-`3`, A3 SE-spurious-minus, affiliation-leak remain); the other 4 canaries FAIL on clusters B/C/D. The run continues — A2 is cycle 2. Did NOT report "clean." Standing corpus verdict FAIL until the canary set is clean or budget exhausted.
|
|
1392
|
+
|
|
1393
|
+
### Process wins
|
|
1394
|
+
- **Reproduce-at-HEAD before trusting a stale TRIAGE** (card `reproduce-triage-defect-at-head`) — the 2026-06-25 TRIAGE would have sent me chasing already-shipped DP-* items; the fresh 5-canary baseline surfaced the REAL open clusters.
|
|
1395
|
+
- **5 parallel Sonnet verifiers** for the canary baseline (subagent-parallelization mandate) — one orchestrator context, 5 independent verdicts in ~80s.
|
|
1396
|
+
- **Adversarial battery beat the unit tests** — a hand-written 7-case over-recovery battery caught the pre-existing majumder-variant FP that the existing test's slightly-different string missed. For a recovery-widening change, an adversarial "what could this now wrongly recover" battery is worth more than the happy-path test.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: docpluck-iterate
|
|
3
|
-
description: Use when the user wants to run an autonomous library→local→deploy iteration loop on docpluck — fix-verify-release-deploy cycles working through a backlog of corpus defects until a stop condition is met (time budget, iteration count, corpus pass-rate threshold, or explicit "until X"). Self-improving: appends LEARNINGS each cycle and proposes SKILL.md amendments after recurring patterns. Triggers on phrases like "iterate on docpluck", "run the docpluck loop", "self-improve docpluck", "fix-and-deploy until X", "keep working on the corpus", or after a v2.x.y release when the user asks to continue iterating.
|
|
3
|
+
description: 'Use when the user wants to run an autonomous library→local→deploy iteration loop on docpluck — fix-verify-release-deploy cycles working through a backlog of corpus defects until a stop condition is met (time budget, iteration count, corpus pass-rate threshold, or explicit "until X"). Self-improving: appends LEARNINGS each cycle and proposes SKILL.md amendments after recurring patterns. Triggers on phrases like "iterate on docpluck", "run the docpluck loop", "self-improve docpluck", "fix-and-deploy until X", "keep working on the corpus", or after a v2.x.y release when the user asks to continue iterating.'
|
|
4
4
|
tags: [docpluck, python, fastapi, nextjs, vercel, railway, neon, iterate, orchestration, self-improving, qa, deploy]
|
|
5
5
|
user-invocable: true
|
|
6
6
|
argument-hint: "[--goal time:60m | iters:5 | baseline:26/26+full:95/101 | until:\"description\"] [--no-broad-read] [--dry-run]"
|
|
@@ -29,7 +29,7 @@ If QA surfaces an issue — any issue, however small, whether pre-existing, alre
|
|
|
29
29
|
- **Frontend:** Next.js 16 + Auth.js + Drizzle (in `frontend/`), port 6116
|
|
30
30
|
- **Service:** Python FastAPI importing `docpluck` library (in `service/`), port 6117
|
|
31
31
|
- **Database:** Neon Postgres (docpluck project)
|
|
32
|
-
- **ESCIcheck PDFs:** `C:\Users\filin\Dropbox\Vibe\
|
|
32
|
+
- **ESCIcheck PDFs:** `C:\Users\filin\Dropbox\Vibe\MetaScienceProjects\COREteamToolsTemplates\COREcoding\testpdfs\Coded already\` (50 PDFs, APA psychology papers)
|
|
33
33
|
- **Test PDFs:** `test-pdfs/` (47 PDFs, 8 citation styles)
|
|
34
34
|
- **Test suite:** `service/tests/` (151 tests across 6 files)
|
|
35
35
|
|
|
@@ -14,7 +14,7 @@ if not API_KEY:
|
|
|
14
14
|
print('SKIP: set DOCPLUCK_API_KEY env var to run production check')
|
|
15
15
|
exit(0)
|
|
16
16
|
|
|
17
|
-
ESCI_DIR = r'C:\Users\filin\Dropbox\Vibe\
|
|
17
|
+
ESCI_DIR = r'C:\Users\filin\Dropbox\Vibe\MetaScienceProjects\COREteamToolsTemplates\COREcoding\testpdfs\Coded already'
|
|
18
18
|
pdfs = sorted(os.listdir(ESCI_DIR))[:10]
|
|
19
19
|
|
|
20
20
|
results = []
|
|
@@ -10,7 +10,7 @@ python -c "
|
|
|
10
10
|
import os, re, sys
|
|
11
11
|
from docpluck import extract_pdf, normalize_text, NormalizationLevel, compute_quality_score
|
|
12
12
|
|
|
13
|
-
ESCI_DIR = r'C:\Users\filin\Dropbox\Vibe\
|
|
13
|
+
ESCI_DIR = r'C:\Users\filin\Dropbox\Vibe\MetaScienceProjects\COREteamToolsTemplates\COREcoding\testpdfs\Coded already'
|
|
14
14
|
pdfs = sorted(os.listdir(ESCI_DIR))[:10] # First 10 alphabetically
|
|
15
15
|
|
|
16
16
|
results = []
|
|
@@ -15,7 +15,7 @@ Then run:
|
|
|
15
15
|
python -c "
|
|
16
16
|
import os, re, json, requests
|
|
17
17
|
|
|
18
|
-
ESCI_DIR = r'C:\Users\filin\Dropbox\Vibe\
|
|
18
|
+
ESCI_DIR = r'C:\Users\filin\Dropbox\Vibe\MetaScienceProjects\COREteamToolsTemplates\COREcoding\testpdfs\Coded already'
|
|
19
19
|
pdfs = sorted(os.listdir(ESCI_DIR))[:10]
|
|
20
20
|
|
|
21
21
|
# Test via the Python service directly (bypasses auth)
|
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.4.102] — 2026-07-03
|
|
4
|
+
|
|
5
|
+
**'2'-for-minus glyph recovery now reaches the Camelot HTML-table channel — every negative B-coefficient in a regression table (`20.09` for `−0.09`) is recovered, not just the ones in the no-Camelot fallback.** `NORMALIZATION_VERSION` → `1.9.37`. A cycle-1 AI-gold canary re-verify at v2.4.101 found efendic_2022_affect rendering **27 corrupt `2X.XX` B-column cells** across regression Tables 2–5 (gold `−0.09` → `20.09`, `−1.09` → `21.09`, …) — a silently-wrong statistic, the worst defect class for a meta-science tool.
|
|
6
|
+
|
|
7
|
+
**Root cause (a text-channel-coverage gap, not a new corruption).** The `2`-for-U+2212 recovery `recover_minus_via_ci_pairing` (W0d) pairs a bracket-less point estimate with the confidence interval in its **same record** and recovers the minus by the containment invariant (a point estimate lies inside its own CI). Camelot emits each table cell on its own line, so inside a multi-line `<tr>` the SE cell sits **between** the B-column estimate and the CI cell — pushing the char-gap from the estimate to the bracket to 37 chars, past the 30-char cap W0d applies to *bare* (unlabeled) brackets. The recovery therefore fired in the `DISABLE_CAMELOT` unstructured-table channel (where the CI is on the same text line, close) but **silently missed every negative B-coefficient in the Camelot HTML-table channel — the production default.** The existing test passed only because it set `DOCPLUCK_DISABLE_CAMELOT=1` (a channel blind spot; memory `glyph-fixes-need-all-three-text-channels`).
|
|
8
|
+
|
|
9
|
+
**The fix.** Inside an HTML table row the columns pair by table geometry, not prose adjacency — the CI column belongs to the estimate column of the same row regardless of the intervening SE cell. So a bare bracket in a `<tr>` now uses the same relaxed proximity as a *labeled* CI, still guarded by `_INDEPENDENT_STAT_BETWEEN_RE` (which rejects pairing back across a *different* estimate's column). A prose text line (no `<td>`) keeps the strict 30-char cap, so the majumder prose false-positive stays blocked. All 27 efendic cells recover; the genuine positive `2.56` (Direction row, `2.56 ∈ [2.42, 2.69]`) is correctly left by the containment invariant.
|
|
10
|
+
|
|
11
|
+
**Also fixed (pre-existing, leave-nothing-behind).** The independent-stat guard now runs for **every** bracket kind, not only labeled ones. A tight-spaced prose variant `M = 5.37, SD = 2.01, t(1827)=1.83, d = 0.09 [-1.86, 0.04]` is only 25 chars from `2.01` to the bracket — within the cap — so the gap check alone let `SD = 2.01` wrongly recover to `-.01`; the CI is `d`'s and `t`/`d` intervene, so it is now rejected.
|
|
12
|
+
|
|
13
|
+
**Verification** (ground truth = AI multimodal read of the source PDF via article-finder `reading` golds, **never** pdftotext / Camelot). efendic rendered with Camelot ON: 27 corrupt B-cells → 0; genuine `2.56` preserved; the recovery is idempotent (the render post-process applies W0d, so a second pass is a no-op). Independent Sonnet AI-gold re-verify: A1 resolved, all B-column values in Tables 2–5 exact vs gold, **0 new regressions**. Full minus-recovery suite 22 pass (incl. 6 new — multiline-HTML-row recovery, genuine-positive-preserved, prose-strict-gap, independent-stat-across guard); adversarial over-recovery battery all pass; broad normalize/render/sections/heading suite **557 pass**; table flatten 39 pass; RC-T degenerate-table (Camelot) 8 pass; a deterministic `DISABLE_CAMELOT` body-text render diff of 8 corpus papers = **0 changed** (the change is surgical — only the Camelot HTML-table branch + the specific prose FP pattern are affected). Known remaining efendic defects are queued as their own cycles and are NOT touched by this fix: `×`-as-`3` in interaction-term names (no handler yet), SE-column spurious minus, mid-Introduction affiliation leak. Triage: `docs/TRIAGE_2026-07-03_head_v2.4.101_assessment.md`.
|
|
14
|
+
|
|
15
|
+
## [2.4.101] — 2026-07-02
|
|
16
|
+
|
|
17
|
+
**Concurrent-session reconciliation: six in-flight table-extraction fixes landed onto ONE verified release.** `TABLE_EXTRACTION_VERSION` → `2.4.7`, `NORMALIZATION_VERSION` → `1.9.36`. Roughly five overlapping Claude Code sessions had left the working tree and six sibling branches tangled around the region-driven table-capture path (see `docs/superpowers/handoffs/HANDOFF_2026-07-01_reconcile_concurrent_table_*.md`). This release serializes them onto the committed **v2.4.100 greedy `_find_caption_for_table` + `_rescue_duplicate_starved_captions`** base.
|
|
18
|
+
|
|
19
|
+
**Pairing architecture decision — the global-assignment refactor was REJECTED.** One session had replaced greedy pairing with an order-independent global max-token-overlap assignment (`_assign_tables_to_captions_global` / `_best_assignment_for_page`). It was empirically confirmed to **regress `test_chan_feldman_t6_prose_not_in_any_table`** (a degenerate prose grid promoted into a table) and, per the v2.4.100 record, reshuffles ~24 papers — the same net-harmful class of change the 2026-06-25 triage and memory `project_docpluck_region_driven_camelot` already recorded. Greedy + narrow rescue is kept; the good ideas from the refactor (bare-digit token exclusion) were ported onto it.
|
|
20
|
+
|
|
21
|
+
**The six fixes:**
|
|
22
|
+
1. **chandrashekar Table 3/4 side-by-side de-interleave.** A page with ≥2 captions straddling a whitespace **gutter** drives each caption's region to its OWN column (`_detect_column_gutters` / `_assign_caption_columns` / `_label_x_midpoint` / `_column_table_bottom`, isolated Camelot calls), rebuilding caption + body from that column. Table 4's `17×2` column-straddling merge → clean **9×2**; both captions gold-exact; Table 3 body de-contaminated. Gated behind a true side-by-side signature (inert on single-column / stacked pages).
|
|
23
|
+
2. **efendic Table 1 (categorical) + Table 2 (detect).** Unified `detect.py`: a contiguous **aligned-row-run** (prose-robust, replaces the global column-stability fraction), **widen-aware geometry** (`_detect_geometry_widen_aware` keeps the more-columnar of the narrow/widened band), a contiguous-footnote-gap clamp, and `whitespace._is_categorical_grid` acceptance. Table 1 `3×2` → **5×3**; Table 2 `0×0` stub → **11×5** (all 8 coefficients).
|
|
24
|
+
3. **efendic Table 3 running-header + Tables 2–5 caption-tail-prose strip.** `_RUNNING_HEADER_PATTERNS` gains an `Author et al. <page-number>` two-cell running-header shape (the `Efendic et al. 1179` row 0). `_drop_caption_first_row` also drops a leading single-cell **caption-continuation prose fragment** (`DV.`, `performance and their amount of planning in the subsequent trials.`), context-guarded to fire only above genuine multi-cell table structure. This is done UPSTREAM so a prose tail can't reach a `<th>` and trip `render._strip_phantom_camelot_tables`, which drops the whole table (it was silently dropping jdm_.2023.16 Table 7's real `13×10` grid).
|
|
25
|
+
4. **collabra_77859 Tables 2↔3 same-page mispairing.** Bare integers excluded from the caption-overlap tokenizer (`_CAPTION_TOKEN_RE` → `[a-z]{3,}|\d+\.\d+`), so a stray `Table 2` / `Study 2` digit stops manufacturing false overlap; region-driven capture then pins Tables 2/3/4/5 correctly AND deterministically. (A reading-order visit-order tie-break was tried and **rejected** — it perturbed greedy visit order and regressed chan_feldman T6.)
|
|
26
|
+
5. **cog_emo Table 8 caption-marker hint.** An absorbed `Table N.` first row (`_leading_table_caption_number`) authoritatively pins a grid to caption N, beating degenerate caption-token-overlap ties. Table 8 recovers its real **17×6** intercorrelation matrix; Table 9 its **12×8** (was a `0×0` stub).
|
|
27
|
+
6. **Registered-Report major-section heading promoter** (`render.py`, `_promote_isolated_major_section_headings`) + **dropped-minus CI-upper recovery** (`normalize.recover_dropped_minus_ci_upper` wired into flatten / cell-cleaning / grid — a CI upper bound that lost its leading minus on a tight-kerned PDF, e.g. `[-0.78, -0.66]` parsed as `[-0.78, 0.67]`, is recovered by the estimate-containment invariant).
|
|
28
|
+
|
|
29
|
+
**Verification** (ground truth = AI multimodal read of the source PDF, **never** pdftotext / Camelot, per the project rule): full unit + real-PDF table suites green (per-file, to dodge the Camelot cumulative-load flake); `test_chan_feldman_t6_prose_not_in_any_table` PASS; 904 render/section/normalize tests pass; full **101-PDF structured diff** vs v2.4.100 — Camelot verified **deterministic** on this host (two identical-code runs byte-identical, 392 tables each), so every diff is real, not flake; AI-gold re-verification on the changed papers returned **15 BETTER, 5 SAME, 0 WORSE** across a broad sample (recovered truncated/missing data, corrected caption→table pairings, correct caption-tail strips) — the one regression it surfaced (jdm_.2023.16 Table 7 render-drop) was root-caused and fixed in the same run.
|
|
30
|
+
|
|
31
|
+
## [2.4.100] — 2026-07-01
|
|
32
|
+
|
|
33
|
+
**bmc_med_3 duplicate-fragment pairing FIXED — a narrow, order-independent duplicate-starvation rescue in `_find_caption_for_table`'s aftermath.** `TABLE_EXTRACTION_VERSION` → `2.4.6`. Resolves the hard case explicitly deferred in v2.4.99 (both a same-page raw-text dedupe and a bbox-proximity pairing were tried and reverted there — each regressed another paper).
|
|
34
|
+
|
|
35
|
+
**The bug.** On a page carrying ≥2 table captions, Camelot's `stream` sometimes emits two *near-identical fragments* of one table (stream + lattice both fire). The greedy `_find_caption_for_table` loop walks Camelot's tables in emission order and lets each claim the best still-free caption, so the first caption took one copy and the second caption — now the only free one — was handed the **duplicate** second copy, even though that copy is not its table. The second caption's real, distinct table then found no free caption and was dropped. **bmc_med_3 p8:** captions Table 2 + Table 3; Camelot emitted Table 2's 29×5 twice plus Table 3's real 11×6. Table 3 was given the second copy of Table 2's 29×5 and its own "Comparisons of SCE …" 11×6 grid was discarded.
|
|
36
|
+
|
|
37
|
+
**The fix (`_rescue_duplicate_starved_captions`, extract_structured.py).** A post-pass over the greedy assignment that fires *only* on that exact signature: on a page where ≥2 captions were assigned tables with **identical `raw_text`**, the caption that overlaps the shared table best keeps it and each other ("starved") caption is reassigned to the best **unassigned** same-page table that fits it at least as well as the duplicate it was holding. Duplicates are kept as separate assignable tables (a genuinely two-caption / two-identical-grid page — bmc_med_4 — still fills both captions unchanged); only a real distinct table that greedy stranded is recovered. bmc_med_3 Table 3 → its real 11×6 (`method` gains `dup_rescue:1`), verified cell-for-cell against the AI multimodal read of the source page (SCE comparisons: Patients-with-SCE, lesion-diameter/volume IQRs, the "Classification of lesions" group-header row) — NEVER pdftotext, per the project ground-truth rule.
|
|
38
|
+
|
|
39
|
+
**Why narrow, not a global re-assignment.** A full order-independent max-token-overlap matching per page *does* fix bmc_med_3, but a 101-PDF structured diff showed it **reshuffled ~24 papers and un-did verified token-overlap fixes** — chen / chandrashekar / ieee_access_4 / cmaj_2 swaps, and it *promoted a degenerate prose fragment to chan_feldman Table 6* (a real regression: `test_chan_feldman_t6_prose_not_in_any_table` went from pass to fail 3/3). Global re-optimization is exactly the class of change memory `project_docpluck_region_driven_camelot` and the 2026-06-25 triage recorded as net-harmful. The rescue is therefore keyed on the duplicate signature alone, so **every page without that signature keeps its greedy assignment byte-for-byte** — chan_feldman's T6 test passes 3/3, and a whole-corpus `dup_rescue`-firing scan confirms the new code path activates on only the intended page(s); every other paper runs the identical HEAD path and cannot be changed by this fix.
|
|
40
|
+
|
|
41
|
+
**Verification** (ground truth = AI multimodal read / article-finder golds, never pdftotext): bmc_med_3 Table 3 AI-gold-verified; bmc_med_4 byte-identical (rescue correctly does not fire); `test_chan_feldman_t6_prose_not_in_any_table` 3/3 pass; whole-corpus `dup_rescue` scan shows the fix is surgical (Camelot's run-to-run non-determinism — memory `feedback_camelot_flake_cumulative_load` — defeats naive before/after fingerprint diffing, so surgicality is proven at the code-path level, not by comparing flaky shapes). Full table unit + real-PDF suite green (per-file, to dodge the Camelot cumulative-load flake).
|
|
42
|
+
|
|
3
43
|
## [2.4.99] — 2026-06-29
|
|
4
44
|
|
|
5
45
|
**Region-driven table capture (DP-1/DP-2): drive Camelot with docpluck's own caption-anchored region as `table_areas` — AI-gold-verified, the first CAPTURE-PATH change in the v2.4.x table series.** `TABLE_EXTRACTION_VERSION` → `2.4.5`. Instead of running Camelot blind (`pages="all"`) and pairing tables to captions after the fact, each table caption now drives a `stream` extraction constrained to its OWN region (`extract_tables_camelot_by_region` + `_region_driven_capture` in `extract_structured.py`), so a caption gets exactly its table by construction. This recovers the **stacked / side-by-side multi-table-per-page** class that blind detection + token-overlap pairing could not separate — **efendic Tables 4+5 now split correctly** (was a 30×2 merge + empty stub), and **12 papers' previously-empty `0×0` stubs become real tables** (chandrashekar, jdm, ieee×4, bmc_med_3 T4, bmj_open_1, …).
|
|
@@ -243,3 +243,12 @@ Add only when a real downstream consumer asks for one. YAGNI until then.
|
|
|
243
243
|
### ScienceArena adapter (their repo — fixed this session, verify there)
|
|
244
244
|
|
|
245
245
|
- [ ] **Re-run the ScienceArena benchmark** with docpluck ≥ 2.4.83 installed in ITS venv. The adapter fixes (commit `de35f4a` on sciencearena `main`: pass `layout=`, read `report.footnote_texts`, strip the caption label) are logic-verified against local docpluck but NOT run end-to-end there (docpluck isn't installed in that repo). Also recommend ranking `docpluck-standard` as the primary real-document variant (Greek preserved).
|
|
246
|
+
|
|
247
|
+
- [ ] R-0040 | bug | P1 | from cross-project-learning-reviewer 2026-06-29 | per-row n mis-bound to comparison arm (collabra.90203 T10) + dropped-minus CI upper bound (cog_emo T8 sign-flip); T10 test encodes WRONG n (see project-review R-0040)
|
|
248
|
+
- **VERIFIED-AT-HEAD 2026-06-29 (interactive session) — split into two findings:**
|
|
249
|
+
- **Part A (per-row n mis-bound, collabra.90203 T10): NOT REPRODUCIBLE — false positive.** Ran `pytest tests/test_tables_superheader_alignment_real_pdf.py::test_collabra_90203_table10_all_six_conditions_real_pdf tests/test_tables_flatten.py::TestT90203Table10` → **3 passed**. The real-PDF test already asserts the CORRECT arm split (Target arm: r=.34, n=170; Replication arm: r=.63, CI[.53,.72]) and is GREEN. n=170 is the Target arm's correct n, NOT a wrong binding; the synthetic `TestT90203Table10` table is a 3-column no-arm table where n=170 is correct by construction. The reviewer's "test encodes the WRONG n" reading is the ~26%-false-positive class (cf. R-0006: reproduce at HEAD before fixing). **No fix needed for Part A** unless a NEW failing repro is produced.
|
|
250
|
+
- **Part B (dropped-minus CI upper bound, cog_emo T8): REAL — reproduces at HEAD.** Rendering `PDFextractor/test-pdfs/apa/chan_feldman_2025_cogemo.pdf` via `extract_pdf_structured` → `flatten_table`, Table 8 emits:
|
|
251
|
+
- `2bi: r=-0.73 CI=[-0.78, 0.67]` ← upper bound should be **-0.66** (sibling row above correctly reads `[-0.78,-0.66]`)
|
|
252
|
+
- `2bii: r=-0.43 CI=[-0.52, 0.33]` ← upper bound should be **-0.33**
|
|
253
|
+
The minus on the **CI upper bound** is dropped (tight-kerned U+2212 in symbol font; pdftotext drops the glyph — same class as W0g/W0h betas, but on the CI's own bound). Existing recovery (`docpluck/normalize.py`: `recover_dropped_minus_via_ci_pairing` W0g @2663, `recover_dropped_minus_via_layout` W0h @2782) recovers *coefficient* tokens proven negative by their CI bracket — it does NOT recover a minus dropped from the **bracket itself**, because it trusts the bracket.
|
|
254
|
+
- **Fix path (do via `/docpluck-iterate`, NOT a blind edit):** add a general, structurally-keyed recovery for "CI upper bound whose minus was dropped" — likely a layout-channel check (W0h-style, via the `dropped_minus_layout` LayoutDoc already threaded into the pipeline @3005/3029) OR a point-estimate-containment invariant (when the reported point estimate is negative and the parsed CI is `[neg, pos]` such that the interval is implausibly asymmetric about the estimate, the positive upper bound is the dropped-minus victim — but tune carefully so legitimate zero-straddling CIs are NOT corrupted). MUST: key on the structural signature (general, not this one PDF); verify against the AI gold under `ArticleRepository/ai_gold/` (never pdftotext); add a regression test mirroring `test_dropped_minus_layout_recovery_real_pdf.py` for the CI-bound case; run the full 26-paper baseline for no regression. ESCIcheck already works around the downstream effect (NOTE-path + `ESCIcheckapp/docs/REPLY_TO_DOCPLUCK_2026-06-26.md`).
|
|
@@ -78,7 +78,7 @@ from .figures import Figure
|
|
|
78
78
|
from .extract_structured import TABLE_EXTRACTION_VERSION, StructuredResult, extract_pdf_structured
|
|
79
79
|
from .render import render_pdf_to_markdown
|
|
80
80
|
|
|
81
|
-
__version__ = "2.4.
|
|
81
|
+
__version__ = "2.4.102"
|
|
82
82
|
__author__ = "Gilad Feldman"
|
|
83
83
|
__license__ = "MIT"
|
|
84
84
|
|