Implement the text reconstruction pipeline (§4.1 steps 2-5) for the M0 Spike B gate: - GlyphRun.h: input model (Glyph, GlyphRun, Line, Paragraph, GroundTruth) mirroring §3.2/§3.3 - Reconstruct.cpp: flatten → line detection (baseline cluster, 0.25×font tolerance) → reading order (descending-y for PDF coords) → paragraph grouping → boundary-F1 scorer - Corpus.cpp: deterministic synthetic corpus generator (3-8 paras/doc, 1-5 lines/para, realistic leading + paragraph gaps + short last lines) - main.cpp: emits the contract JSON; exit 0 if F1 ≥ target Gate MET: F1=0.963 (precision 0.929, recall 1.000) on 500 synthetic docs, target ≥0.85. Verified clean under ASan+UBSan. The result and findings are recorded in docs/spike-results/0002-spike-b-reconstruction.md. Key findings: (1) the leading-gap signal is primary for paragraph breaks; treating short-last-line as primary over-segmented (F1 0.37→0.96 fixed). (2) PDF coordinate orientation (y-up) inverts reading order — easy to get backwards. (3) column-width inference must use a percentile not the max. (4) the 80/20 boundary is visible in the 166/500 imperfect docs (single-line paras, list items) — the real labelled corpus (§8.1) is needed for the 0.93 release gate. Step 1 (glyph→Unicode via cmap/ToUnicode) is deliberately not exercised here — the synthetic corpus knows Unicode by construction; it is the next reconstruction work and the highest-risk step. CI: add a spike-gates job to .gitea/workflows/build.yml that runs Spike A (informational — the byte-identity gate is met by §4.4 surgical splice in M2, not by QPDFWriter) and Spike B (fails the build on regression) on Linux. Signed-off-by: ai-ad4 <ai-ad4@users.noreply.gitea.lm.je> |
||
|---|---|---|
| .gitea/workflows | ||
| LICENSES | ||
| ci | ||
| cmake | ||
| docs | ||
| packaging | ||
| spike | ||
| src | ||
| test | ||
| .clang-format | ||
| .clang-tidy | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| .gitleaks.toml | ||
| .pre-commit-config.yaml | ||
| CMakeLists.txt | ||
| CMakePresets.json | ||
| CODEOWNERS | ||
| CONTRIBUTING.md | ||
| README.md | ||
| REUSE.toml | ||
| SECURITY.md | ||
| TRADEMARK.md | ||
| vcpkg-configuration.json | ||
| vcpkg.json | ||
README.md
FreePDFEditor
A cross-platform native desktop PDF editor with a true WYSIWYG interface and full content editing: edit existing text with reflow, replace images, manipulate vector objects, plus annotations, forms, signatures, and page assembly.
- Stack: C++20, Qt 6.7 (Widgets shell, custom canvas), CMake, vcpkg.
- License: GPL-3.0-or-later (see
LICENSES/GPL-3.0-or-later.txt). Qt is dynamically linked under LGPL-3.0. - Targets: Windows 10+, macOS 12+ (Intel + Apple Silicon), Linux (X11/Wayland).
This repository contains the source and build infrastructure. The full engineering plan and
roadmap live in docs/plan.md; architecture decision records are under
docs/adr/.
Status
Pre-M0. This is the initial repository scaffold described in §14 of the plan: CMake + vcpkg skeleton, governance docs, CI matrix, packaging pipeline, an empty-window application shell, the pixel-diff harness scaffolding, and the Spike A (QPDF verbatim round-trip) harness. The feasibility spikes that gate the project run on top of this scaffolding.
Building
cmake --preset default
cmake --build --preset default
ctest --preset default
See CONTRIBUTING.md for the full build setup, gate matrix, and coding
standard.
Source control
All code is developed on the project Gitea instance at https://gitea.lm.je/ai-ad4/freepdfeditor
per docs/plan.md §13. See SECURITY.md for vulnerability reporting.