--- type: architecture title: Anniversary Matching description: Rules and file boundaries used to discover Jekyll posts whose publication anniversary is exactly ten years before the current date. tags: [matching, jekyll, anniversary, posts] timestamp: 2026-08-04T18:35:00Z --- # Purpose `tenbackward.matching` scans the synchronized blog at `/_posts/blog` and returns posts whose date is exactly ten years before the current date. The current date is evaluated in the configured IANA timezone, defaulting to `Europe/Berlin` in the matcher. # Discovery Rules 1. Walk every Markdown file below the configured post root recursively. 2. Parse YAML front matter when present. 3. Require a filename stem shaped as `YYYY-MM-DD-slug` with a valid calendar date and non-empty slug. 4. Prefer a valid front matter `date`; otherwise use the date in the filename. 5. Match the post year to `today.year - 10` and the month/day to today. 6. Skip posts with `published: false`. 7. Return a `MatchedPost` containing the relative path, title, date, and canonical site URL. If front matter has no title, use the filename slug. # Leap-Day Behavior A February 29 post matches February 29 when the current year is a leap year. In a non-leap year it matches March 1, but only when the post's year is exactly ten years before the current year (`today.year − 10`). Because `today.year − 10` is never itself a leap year whenever today is a leap year (`10 mod 4 == 2`), the Feb 29 ↔ Feb 29 branch is reached independently of the year-equality check: any Feb 29 post from a prior leap year is a candidate, and its canonical URL keeps the original `YYYY/02/29//` path. # Output and Integration `find_anniversary_matches()` returns `MatchedPost` values for callers that need metadata. `iter_anniversary_paths()` yields only relative paths; the pipeline uses those paths as deduplication identifiers in the [system state store](/architecture/system-overview.md) and persists new IDs in `posted.json`. Unreadable files, malformed front matter, invalid filenames, unpublished posts, and unexpected per-file errors are skipped with structured warning events rather than aborting the full scan. # Key Files | Path | Responsibility | |---|---| | `/repo/src/tenbackward/matching.py` | Date parsing, Jekyll front matter handling, anniversary rules, URL construction, and recursive scanning. | | `/repo/src/tenbackward/main.py` | Supplies the blog post root and site URL, then applies state deduplication. | | `/repo/tests/test_matching.py` | Covers filename/front matter parsing, date matching, unpublished posts, malformed files, URL output, and leap-day behavior. | | `/repo/src/tenbackward/blog.py` | Ensures the source repository is cloned or fast-forwarded before matching. | # Examples ## Matching post On 2026-08-04, a file named `_posts/blog/2016/2016-08-04-release.md` is eligible. Its identifier is `2016/2016-08-04-release.md` and its generated URL is: ```text https://example.com/2016/08/04/release/ ``` ## Skipped post A file with `published: false`, an invalid date, or a non-matching month/day is not yielded and does not enter `posted.json`. # Related * [Pipeline Runner](/architecture/pipeline-runner.md) * [System Architecture](/architecture/system-overview.md) * [Daily Run Guide](/guides/daily-run.md)