The roadmap table is duplicated across nine files — the root README.md and each
src/*/README.md, wired in as the per-package NuGet README by src/Directory.Build.targets. Every
milestone change has to be hand-applied nine times, and it has now demonstrably drifted twice:
- Before: the table described "2.3 — PDF content extraction" and "2.4 — PDF/A-1 profile" while the
live milestones were v2.3 — Reader robustness, v2.4 — PDF content extraction and
v2.5 — PDF/A-4 and PDF/A-1 profiles. Two rows wrong, one milestone missing entirely.
- Again, within a single session: milestones were added, one issue moved between them, and one
milestone was deleted. The table kept a row for Layout I, a milestone that no longer existed, and
described work under a milestone it had been moved out of.
The second case is the interesting one, because the drift appeared between writing the table and
finishing the same piece of work. Hand-syncing nine copies does not survive even that.
docs/architecture.md already states the principle:
Live scope lives in one place — the roadmap table in README.md, tracked as GitHub milestones. A
second copy here would only drift, which is how the list above came to describe a target the library
had long since passed.
That reasoning is right, and it applies with equal force to the nine copies of the table itself.
What to do
Generate the block from the GitHub milestones, the way docs/pdf20-conformance.md is generated from
its sources: an eng/generate-roadmap.py that reads milestone titles, descriptions and open counts,
renders the table, and writes it between markers in all nine files. A --check mode makes drift a CI
failure rather than something noticed a release later.
Milestone descriptions then become the single source of truth, which is where they belong — they
are already the thing a maintainer edits when scope changes, and they are visible on the milestones
page next to the issues they describe.
Two details worth settling in the implementation:
- The per-package READMEs need the
docs/ link rewritten relative to their own directory; the current
copies use ../../docs/.
- Open issue counts are useful in the table but churn on every issue move, which would make the
generated file dirty constantly. Probably omit them, or put them behind a flag.
Relates to
- The
vellumpdf-per-package-readmes convention this works within.
eng/generate-pdf20-inventory.py — the precedent, including its --check mode.
The roadmap table is duplicated across nine files — the root
README.mdand eachsrc/*/README.md, wired in as the per-package NuGet README bysrc/Directory.Build.targets. Everymilestone change has to be hand-applied nine times, and it has now demonstrably drifted twice:
live milestones were
v2.3 — Reader robustness,v2.4 — PDF content extractionandv2.5 — PDF/A-4 and PDF/A-1 profiles. Two rows wrong, one milestone missing entirely.milestone was deleted. The table kept a row for
Layout I, a milestone that no longer existed, anddescribed work under a milestone it had been moved out of.
The second case is the interesting one, because the drift appeared between writing the table and
finishing the same piece of work. Hand-syncing nine copies does not survive even that.
docs/architecture.mdalready states the principle:That reasoning is right, and it applies with equal force to the nine copies of the table itself.
What to do
Generate the block from the GitHub milestones, the way
docs/pdf20-conformance.mdis generated fromits sources: an
eng/generate-roadmap.pythat reads milestone titles, descriptions and open counts,renders the table, and writes it between markers in all nine files. A
--checkmode makes drift a CIfailure rather than something noticed a release later.
Milestone descriptions then become the single source of truth, which is where they belong — they
are already the thing a maintainer edits when scope changes, and they are visible on the milestones
page next to the issues they describe.
Two details worth settling in the implementation:
docs/link rewritten relative to their own directory; the currentcopies use
../../docs/.generated file dirty constantly. Probably omit them, or put them behind a flag.
Relates to
vellumpdf-per-package-readmesconvention this works within.eng/generate-pdf20-inventory.py— the precedent, including its--checkmode.