Dependencies
Blocked by: #7 — staleness reads the pins the contract defines.
Blocks: nothing.
Can run in parallel with: #8, #9.
Independent of #3 (upstream intelligence): this works whether or not #3 is ever built.
Part of #4 — the handbook knowledge layer.
Detect when a handbook page's sources have changed since the page was written, and say so.
Each page pins repo + ref + commit + paths. A scheduled job asks one mechanical question per source:
git fetch origin "$ref" # 1. get current state
git merge-base --is-ancestor "$commit" FETCH_HEAD || exit 1 # 2. fail closed
git log --oneline "$commit"..FETCH_HEAD -- $paths # 3. what moved
Non-empty output from step 3 means a file the page was built from has changed. No model, no embeddings — just git.
Steps 1 and 2 are not optional
git log A..B returns empty and exits 0 when A is not an ancestor of B. It does not error. So a pin taken on a branch that later diverged reports "nothing changed" while the cited file may have been rewritten or deleted.
Reproduced on launchpad-26/buzz: git log c060e936c..32f0988c8 -- <a file> prints nothing, yet the file exists at the first commit and not at the second.
Fetching a named ref fixes the undefined comparison target; the ancestor check turns a silent false negative into a loud failure. A staleness check that can quietly pass is worse than none, because it is believed.
Detection is mechanical; triage is judgement
The job reports only "page X cites files that moved". Whether the page is now wrong is a separate call made by a human or an agent. Conflating the two makes the check both expensive and untrustworthy.
Clearing a flag is a human procedure, not a mechanical guarantee. It means updating sources[].commit and last_verified in the same PR. Nothing can prove the person read the diff — a blind bump clears the check too. A green staleness check is not evidence that anyone reviewed the upstream change.
Also in scope — the published index
The build emits a machine-readable index: page path → sources → pinned commits. This is the seam for #3 (upstream intelligence), which can read it to answer "does this upstream change affect our documentation?". No dependency runs from this issue to #3 — the job works standalone.
Acceptance
Dependencies
Blocked by: #7 — staleness reads the pins the contract defines.
Blocks: nothing.
Can run in parallel with: #8, #9.
Independent of #3 (upstream intelligence): this works whether or not #3 is ever built.
Part of #4 — the handbook knowledge layer.
Detect when a handbook page's sources have changed since the page was written, and say so.
Each page pins
repo + ref + commit + paths. A scheduled job asks one mechanical question per source:Non-empty output from step 3 means a file the page was built from has changed. No model, no embeddings — just git.
Steps 1 and 2 are not optional
git log A..Breturns empty and exits 0 whenAis not an ancestor ofB. It does not error. So a pin taken on a branch that later diverged reports "nothing changed" while the cited file may have been rewritten or deleted.Reproduced on
launchpad-26/buzz:git log c060e936c..32f0988c8 -- <a file>prints nothing, yet the file exists at the first commit and not at the second.Fetching a named
reffixes the undefined comparison target; the ancestor check turns a silent false negative into a loud failure. A staleness check that can quietly pass is worse than none, because it is believed.Detection is mechanical; triage is judgement
The job reports only "page X cites files that moved". Whether the page is now wrong is a separate call made by a human or an agent. Conflating the two makes the check both expensive and untrustworthy.
Clearing a flag is a human procedure, not a mechanical guarantee. It means updating
sources[].commitandlast_verifiedin the same PR. Nothing can prove the person read the diff — a blind bump clears the check too. A green staleness check is not evidence that anyone reviewed the upstream change.Also in scope — the published index
The build emits a machine-readable index:
page path → sources → pinned commits. This is the seam for #3 (upstream intelligence), which can read it to answer "does this upstream change affect our documentation?". No dependency runs from this issue to #3 — the job works standalone.Acceptance
reffails loudly rather than reporting "no change"