mirror of
https://github.com/paperclipai/paperclip-docs.git
synced 2026-11-07 06:16:07 -10:00
Follow-up to #117. That PR got `<lastmod>` publishing at all; this one makes the dates worth resubmitting. ## The problem **190 of 193 pages read `2026-08-25`** — the date of #115, which added `seo_title`/`seo_description` to all 192 pages. Here is everything it changed in a representative file: ```diff +--- +seo_title: "Key Concepts: Companies, Agents, Tasks" +seo_description: The seven ideas behind Paperclip — company, agent, task... +--- + # Key Concepts ``` Not a word of prose. `lastmod` is meant to carry the date a page's **content** last changed, so resubmitting this hands Search Console the "whole site changed at once" signal that `dropUniformLastmod` and the shallow-checkout guard both exist to prevent. It cleared `dropUniformLastmod` only because 3 pages happened to differ. ## The fix Walk each file's history and report the newest commit that changed the **rendered body** — comparing `parseFrontmatter().body` across consecutive commits, so frontmatter-only commits are skipped. Reusing the build's own parser means the body compared is exactly the body the site renders. | | Before | After | |---|---|---| | Distinct dates | **2** | **31** | | Largest single-date cluster | 190 pages | 54 pages | | Range | 2 days | 2026-04-17 → 2026-08-27 | Top of the new distribution: | Date | Pages | |---|---| | 2026-08-18 | 54 | | 2026-06-04 | 21 | | 2026-08-25 | 17 | | 2026-07-08 | 16 | | 2026-07-20 | 15 | | 2026-04-22 | 12 | Spot-checked both directions: - `key-concepts.md` — last touched by the frontmatter sweep, now dates to **2026-07-08**, the commit that changed "Claude Local" to "Claude Code" in the body. - `day-to-day/issues.md` — **keeps 2026-08-25**, because release commit `6c4519a` that day added a real "Who may resolve a card" section. Its frontmatter-only `paperclip_version` bump in the same release was correctly skipped. ## Two supporting fixes **Concurrency.** ~600 git round-trips in series cost 40s. Resolving them in parallel: **11s**. **A race the concurrency exposed** — and the reason this is worth reading closely. `hasTrustworthyGitHistory()` memoised its *resolved value*, so once all 192 pages asked at once, every one of them passed the guard before the first resolved: ``` Could not deepen the shallow checkout: fatal: Unable to create '.git/shallow.lock': File exists. Still shallow: omitting sitemap <lastmod> rather than dating every page alike. × 192 ``` 192 concurrent `git fetch --unshallow` calls fighting over the lock, and **a sitemap with no dates at all**. This only reproduces on a shallow clone — which is to say only on Cloudflare Pages, never locally or in `docs-test`. Fixed by memoising the promise (single-flight). ## Verification | Scenario | Result | |---|---| | Full clone | 193 dates, 31 distinct, 11s | | `git clone --depth 1` (reproduces CF) | one unshallow, **193 dates, 31 distinct** | | Shallow + unreachable remote | no dates, exit 0 | | `npm run docs:test` (6 suites) | pass | | `npm run sync:test` | 39 pass, 0 fail (+1 new) | New unit test covers the `--follow --name-status` rename parsing — 55 docs files have been renamed, and reading the wrong field silently drops their pre-rename history. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <[email protected]>