Commit Graph

2 Commits

Author SHA1 Message Date
ai-ad4 c299236743 feat(spike-B): reconstruction pipeline; F1=0.963 on synthetic corpus (§14 step 5)
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>
2026-07-25 20:38:24 +00:00
ai-ad4 0dc0a578bc build(license): convert dep5 to REUSE.toml; record Spike A result
Convert the deprecated .reuse/dep5 copyright file to the modern REUSE.toml
format (REUSE 3.3). The old reuse.toml (non-standard schema) is removed;
REUSE.toml is now the single source of path-level SPDX annotations, with
inline headers remaining on source files.

Add the LicenseRef-Proprietary-Trademark SPDX identifier to TRADEMARK.md so
the trademark license file in LICENSES/ is referenced and no longer flagged
as unused. # SUMMARY

* Bad licenses: 0
* Deprecated licenses: 0
* Licenses without file extension: 0
* Missing licenses: 0
* Unused licenses: 0
* Used licenses: GPL-3.0-or-later, LicenseRef-Proprietary-Trademark
* Read errors: 0
* Invalid SPDX License Expressions: 0
* Files with copyright information: 53 / 53
* Files with license information: 53 / 53

Congratulations! Your project is compliant with version 3.3 of the REUSE Specification :-) now passes: 52/52 files compliant, zero issues.

Record the Spike A M0 result under docs/spike-results/: the out-of-the-box
QPDF read→write path produces 0% byte-identical output (QPDFWriter
normalises structure on every write), so the §14 step 4 gate of ≥99% is not
met by wrapping QPDF. This validates the §4.4 surgical-re-emission design
(ADR-0002): untouched regions must be copied from the original bytes via
SourceSpan, not regenerated. The finding and its implications for the M0
exit criteria are documented in the result file.

Signed-off-by: ai-ad4 <ai-ad4@users.noreply.gitea.lm.je>
2026-07-25 20:30:43 +00:00